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) 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 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 79 Comment::~Comment() { 80 if (msg_[0] == '[') __ RecordComment("]"); 81 } 82 83 #endif // DEBUG 84 85 #undef __ 86 87 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 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 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