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/v8.h" 6 7#include "src/bootstrapper.h" 8#include "src/codegen.h" 9#include "src/compiler.h" 10#include "src/cpu-profiler.h" 11#include "src/debug.h" 12#include "src/prettyprinter.h" 13#include "src/rewriter.h" 14#include "src/runtime.h" 15 16namespace v8 { 17namespace internal { 18 19 20#if defined(_WIN64) 21typedef double (*ModuloFunction)(double, double); 22static ModuloFunction modulo_function = NULL; 23// Defined in codegen-x64.cc. 24ModuloFunction CreateModuloFunction(); 25 26void init_modulo_function() { 27 modulo_function = CreateModuloFunction(); 28} 29 30 31double modulo(double x, double y) { 32 // Note: here we rely on dependent reads being ordered. This is true 33 // on all architectures we currently support. 34 return (*modulo_function)(x, y); 35} 36#elif defined(_WIN32) 37 38double modulo(double x, double y) { 39 // Workaround MS fmod bugs. ECMA-262 says: 40 // dividend is finite and divisor is an infinity => result equals dividend 41 // dividend is a zero and divisor is nonzero finite => result equals dividend 42 if (!(std::isfinite(x) && (!std::isfinite(y) && !std::isnan(y))) && 43 !(x == 0 && (y != 0 && std::isfinite(y)))) { 44 x = fmod(x, y); 45 } 46 return x; 47} 48#else // POSIX 49 50double modulo(double x, double y) { 51 return std::fmod(x, y); 52} 53#endif // defined(_WIN64) 54 55 56#define UNARY_MATH_FUNCTION(name, generator) \ 57static UnaryMathFunction fast_##name##_function = NULL; \ 58void init_fast_##name##_function() { \ 59 fast_##name##_function = generator; \ 60} \ 61double fast_##name(double x) { \ 62 return (*fast_##name##_function)(x); \ 63} 64 65UNARY_MATH_FUNCTION(exp, CreateExpFunction()) 66UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction()) 67 68#undef UNARY_MATH_FUNCTION 69 70 71void lazily_initialize_fast_exp() { 72 if (fast_exp_function == NULL) { 73 init_fast_exp_function(); 74 } 75} 76 77 78#define __ ACCESS_MASM(masm_) 79 80#ifdef DEBUG 81 82Comment::Comment(MacroAssembler* masm, const char* msg) 83 : masm_(masm), msg_(msg) { 84 __ RecordComment(msg); 85} 86 87 88Comment::~Comment() { 89 if (msg_[0] == '[') __ RecordComment("]"); 90} 91 92#endif // DEBUG 93 94#undef __ 95 96 97void CodeGenerator::MakeCodePrologue(CompilationInfo* info, const char* kind) { 98 bool print_source = false; 99 bool print_ast = false; 100 const char* ftype; 101 102 if (info->isolate()->bootstrapper()->IsActive()) { 103 print_source = FLAG_print_builtin_source; 104 print_ast = FLAG_print_builtin_ast; 105 ftype = "builtin"; 106 } else { 107 print_source = FLAG_print_source; 108 print_ast = FLAG_print_ast; 109 ftype = "user-defined"; 110 } 111 112 if (FLAG_trace_codegen || print_source || print_ast) { 113 PrintF("[generating %s code for %s function: ", kind, ftype); 114 if (info->IsStub()) { 115 const char* name = 116 CodeStub::MajorName(info->code_stub()->MajorKey(), true); 117 PrintF("%s", name == NULL ? "<unknown>" : name); 118 } else { 119 AllowDeferredHandleDereference allow_deference_for_trace; 120 PrintF("%s", info->function()->debug_name()->ToCString().get()); 121 } 122 PrintF("]\n"); 123 } 124 125#ifdef DEBUG 126 if (!info->IsStub() && print_source) { 127 PrintF("--- Source from AST ---\n%s\n", 128 PrettyPrinter(info->zone()).PrintProgram(info->function())); 129 } 130 131 if (!info->IsStub() && print_ast) { 132 PrintF("--- AST ---\n%s\n", 133 AstPrinter(info->zone()).PrintProgram(info->function())); 134 } 135#endif // DEBUG 136} 137 138 139Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm, 140 Code::Flags flags, 141 CompilationInfo* info) { 142 Isolate* isolate = info->isolate(); 143 144 // Allocate and install the code. 145 CodeDesc desc; 146 bool is_crankshafted = 147 Code::ExtractKindFromFlags(flags) == Code::OPTIMIZED_FUNCTION || 148 info->IsStub(); 149 masm->GetCode(&desc); 150 Handle<Code> code = 151 isolate->factory()->NewCode(desc, flags, masm->CodeObject(), 152 false, is_crankshafted, 153 info->prologue_offset(), 154 info->is_debug() && !is_crankshafted); 155 isolate->counters()->total_compiled_code_size()->Increment( 156 code->instruction_size()); 157 isolate->heap()->IncrementCodeGeneratedBytes(is_crankshafted, 158 code->instruction_size()); 159 return code; 160} 161 162 163void CodeGenerator::PrintCode(Handle<Code> code, CompilationInfo* info) { 164#ifdef ENABLE_DISASSEMBLER 165 AllowDeferredHandleDereference allow_deference_for_print_code; 166 bool print_code = info->isolate()->bootstrapper()->IsActive() 167 ? FLAG_print_builtin_code 168 : (FLAG_print_code || 169 (info->IsStub() && FLAG_print_code_stubs) || 170 (info->IsOptimizing() && FLAG_print_opt_code)); 171 if (print_code) { 172 // Print the source code if available. 173 FunctionLiteral* function = info->function(); 174 bool print_source = code->kind() == Code::OPTIMIZED_FUNCTION || 175 code->kind() == Code::FUNCTION; 176 177 CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer()); 178 OFStream os(tracing_scope.file()); 179 if (print_source) { 180 Handle<Script> script = info->script(); 181 if (!script->IsUndefined() && !script->source()->IsUndefined()) { 182 os << "--- Raw source ---\n"; 183 ConsStringIteratorOp op; 184 StringCharacterStream stream(String::cast(script->source()), 185 &op, 186 function->start_position()); 187 // fun->end_position() points to the last character in the stream. We 188 // need to compensate by adding one to calculate the length. 189 int source_len = 190 function->end_position() - function->start_position() + 1; 191 for (int i = 0; i < source_len; i++) { 192 if (stream.HasMore()) { 193 os << AsReversiblyEscapedUC16(stream.GetNext()); 194 } 195 } 196 os << "\n\n"; 197 } 198 } 199 if (info->IsOptimizing()) { 200 if (FLAG_print_unopt_code) { 201 os << "--- Unoptimized code ---\n"; 202 info->closure()->shared()->code()->Disassemble( 203 function->debug_name()->ToCString().get(), os); 204 } 205 os << "--- Optimized code ---\n" 206 << "optimization_id = " << info->optimization_id() << "\n"; 207 } else { 208 os << "--- Code ---\n"; 209 } 210 if (print_source) { 211 os << "source_position = " << function->start_position() << "\n"; 212 } 213 if (info->IsStub()) { 214 CodeStub::Major major_key = info->code_stub()->MajorKey(); 215 code->Disassemble(CodeStub::MajorName(major_key, false), os); 216 } else { 217 code->Disassemble(function->debug_name()->ToCString().get(), os); 218 } 219 os << "--- End code ---\n"; 220 } 221#endif // ENABLE_DISASSEMBLER 222} 223 224 225bool CodeGenerator::RecordPositions(MacroAssembler* masm, 226 int pos, 227 bool right_here) { 228 if (pos != RelocInfo::kNoPosition) { 229 masm->positions_recorder()->RecordStatementPosition(pos); 230 masm->positions_recorder()->RecordPosition(pos); 231 if (right_here) { 232 return masm->positions_recorder()->WriteRecordedPositions(); 233 } 234 } 235 return false; 236} 237 238} } // namespace v8::internal 239