1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/codegen.h"
6
7 #if defined(V8_OS_AIX)
8 #include <fenv.h> // NOLINT(build/c++11)
9 #endif
10 #include "src/ast/prettyprinter.h"
11 #include "src/bootstrapper.h"
12 #include "src/compiler.h"
13 #include "src/debug/debug.h"
14 #include "src/parsing/parser.h"
15 #include "src/profiler/cpu-profiler.h"
16 #include "src/runtime/runtime.h"
17
18 namespace v8 {
19 namespace internal {
20
21
22 #if defined(V8_OS_WIN)
modulo(double x,double y)23 double modulo(double x, double y) {
24 // Workaround MS fmod bugs. ECMA-262 says:
25 // dividend is finite and divisor is an infinity => result equals dividend
26 // dividend is a zero and divisor is nonzero finite => result equals dividend
27 if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) &&
28 !(x == 0 && (y != 0 && std::isfinite(y)))) {
29 x = fmod(x, y);
30 }
31 return x;
32 }
33 #else // POSIX
34
35 double modulo(double x, double y) {
36 #if defined(V8_OS_AIX)
37 // AIX raises an underflow exception for (Number.MIN_VALUE % Number.MAX_VALUE)
38 feclearexcept(FE_ALL_EXCEPT);
39 double result = std::fmod(x, y);
40 int exception = fetestexcept(FE_UNDERFLOW);
41 return (exception ? x : result);
42 #else
43 return std::fmod(x, y);
44 #endif
45 }
46 #endif // defined(V8_OS_WIN)
47
48
49 #define UNARY_MATH_FUNCTION(name, generator) \
50 static UnaryMathFunctionWithIsolate fast_##name##_function = nullptr; \
51 double std_##name(double x, Isolate* isolate) { return std::name(x); } \
52 void init_fast_##name##_function(Isolate* isolate) { \
53 if (FLAG_fast_math) fast_##name##_function = generator(isolate); \
54 if (!fast_##name##_function) fast_##name##_function = std_##name; \
55 } \
56 void lazily_initialize_fast_##name(Isolate* isolate) { \
57 if (!fast_##name##_function) init_fast_##name##_function(isolate); \
58 } \
59 double fast_##name(double x, Isolate* isolate) { \
60 return (*fast_##name##_function)(x, isolate); \
61 }
62
UNARY_MATH_FUNCTION(sqrt,CreateSqrtFunction)63 UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction)
64 UNARY_MATH_FUNCTION(exp, CreateExpFunction)
65
66 #undef UNARY_MATH_FUNCTION
67
68
69 #define __ ACCESS_MASM(masm_)
70
71 #ifdef DEBUG
72
73 Comment::Comment(MacroAssembler* masm, const char* msg)
74 : masm_(masm), msg_(msg) {
75 __ RecordComment(msg);
76 }
77
78
~Comment()79 Comment::~Comment() {
80 if (msg_[0] == '[') __ RecordComment("]");
81 }
82
83 #endif // DEBUG
84
85 #undef __
86
87
MakeCodePrologue(CompilationInfo * info,const char * kind)88 void CodeGenerator::MakeCodePrologue(CompilationInfo* info, const char* kind) {
89 bool print_source = false;
90 bool print_ast = false;
91 const char* ftype;
92
93 if (info->isolate()->bootstrapper()->IsActive()) {
94 print_source = FLAG_print_builtin_source;
95 print_ast = FLAG_print_builtin_ast;
96 ftype = "builtin";
97 } else {
98 print_source = FLAG_print_source;
99 print_ast = FLAG_print_ast;
100 ftype = "user-defined";
101 }
102
103 if (FLAG_trace_codegen || print_source || print_ast) {
104 base::SmartArrayPointer<char> name = info->GetDebugName();
105 PrintF("[generating %s code for %s function: %s]\n", kind, ftype,
106 name.get());
107 }
108
109 #ifdef DEBUG
110 if (info->parse_info() && print_source) {
111 PrintF("--- Source from AST ---\n%s\n",
112 PrettyPrinter(info->isolate()).PrintProgram(info->literal()));
113 }
114
115 if (info->parse_info() && print_ast) {
116 PrintF("--- AST ---\n%s\n",
117 AstPrinter(info->isolate()).PrintProgram(info->literal()));
118 }
119 #endif // DEBUG
120 }
121
122
MakeCodeEpilogue(MacroAssembler * masm,CompilationInfo * info)123 Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
124 CompilationInfo* info) {
125 Isolate* isolate = info->isolate();
126
127 Code::Flags flags;
128 if (info->IsStub() && info->code_stub()) {
129 DCHECK_EQ(info->output_code_kind(), info->code_stub()->GetCodeKind());
130 flags = Code::ComputeFlags(
131 info->output_code_kind(), info->code_stub()->GetICState(),
132 info->code_stub()->GetExtraICState(), info->code_stub()->GetStubType());
133 } else {
134 flags = Code::ComputeFlags(info->output_code_kind());
135 }
136
137 // Allocate and install the code.
138 CodeDesc desc;
139 bool is_crankshafted =
140 Code::ExtractKindFromFlags(flags) == Code::OPTIMIZED_FUNCTION ||
141 info->IsStub();
142 masm->GetCode(&desc);
143 Handle<Code> code =
144 isolate->factory()->NewCode(desc, flags, masm->CodeObject(),
145 false, is_crankshafted,
146 info->prologue_offset(),
147 info->is_debug() && !is_crankshafted);
148 isolate->counters()->total_compiled_code_size()->Increment(
149 code->instruction_size());
150 isolate->heap()->IncrementCodeGeneratedBytes(is_crankshafted,
151 code->instruction_size());
152 return code;
153 }
154
155
PrintCode(Handle<Code> code,CompilationInfo * info)156 void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) {
157 #ifdef ENABLE_DISASSEMBLER
158 AllowDeferredHandleDereference allow_deference_for_print_code;
159 bool print_code = info->isolate()->bootstrapper()->IsActive()
160 ? FLAG_print_builtin_code
161 : (FLAG_print_code ||
162 (info->IsStub() && FLAG_print_code_stubs) ||
163 (info->IsOptimizing() && FLAG_print_opt_code));
164 if (print_code) {
165 base::SmartArrayPointer<char> debug_name = info->GetDebugName();
166 CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
167 OFStream os(tracing_scope.file());
168
169 // Print the source code if available.
170 bool print_source =
171 info->parse_info() && (code->kind() == Code::OPTIMIZED_FUNCTION ||
172 code->kind() == Code::FUNCTION);
173 if (print_source) {
174 FunctionLiteral* literal = info->literal();
175 Handle<Script> script = info->script();
176 if (!script->IsUndefined() && !script->source()->IsUndefined()) {
177 os << "--- Raw source ---\n";
178 StringCharacterStream stream(String::cast(script->source()),
179 literal->start_position());
180 // fun->end_position() points to the last character in the stream. We
181 // need to compensate by adding one to calculate the length.
182 int source_len =
183 literal->end_position() - literal->start_position() + 1;
184 for (int i = 0; i < source_len; i++) {
185 if (stream.HasMore()) {
186 os << AsReversiblyEscapedUC16(stream.GetNext());
187 }
188 }
189 os << "\n\n";
190 }
191 }
192 if (info->IsOptimizing()) {
193 if (FLAG_print_unopt_code && info->parse_info()) {
194 os << "--- Unoptimized code ---\n";
195 info->closure()->shared()->code()->Disassemble(debug_name.get(), os);
196 }
197 os << "--- Optimized code ---\n"
198 << "optimization_id = " << info->optimization_id() << "\n";
199 } else {
200 os << "--- Code ---\n";
201 }
202 if (print_source) {
203 FunctionLiteral* literal = info->literal();
204 os << "source_position = " << literal->start_position() << "\n";
205 }
206 code->Disassemble(debug_name.get(), os);
207 os << "--- End code ---\n";
208 }
209 #endif // ENABLE_DISASSEMBLER
210 }
211
212 } // namespace internal
213 } // namespace v8
214