V8 Project
codegen.cc
Go to the documentation of this file.
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/runtime.h"
15 
16 namespace v8 {
17 namespace internal {
18 
19 
20 #if defined(_WIN64)
21 typedef double (*ModuloFunction)(double, double);
22 static ModuloFunction modulo_function = NULL;
23 // Defined in codegen-x64.cc.
24 ModuloFunction CreateModuloFunction();
25 
26 void init_modulo_function() {
27  modulo_function = CreateModuloFunction();
28 }
29 
30 
31 double 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 
38 double 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 
50 double 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) \
57 static UnaryMathFunction fast_##name##_function = NULL; \
58 void init_fast_##name##_function() { \
59  fast_##name##_function = generator; \
60 } \
61 double fast_##name(double x) { \
62  return (*fast_##name##_function)(x); \
63 }
64 
67 
68 #undef UNARY_MATH_FUNCTION
69 
70 
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 
82 Comment::Comment(MacroAssembler* masm, const char* msg)
83  : masm_(masm), msg_(msg) {
84  __ RecordComment(msg);
85 }
86 
87 
88 Comment::~Comment() {
89  if (msg_[0] == '[') __ RecordComment("]");
90 }
91 
92 #endif // DEBUG
93 
94 #undef __
95 
96 
97 void 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 
139 Handle<Code> CodeGenerator::MakeCodeEpilogue(MacroAssembler* masm,
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 
163 void 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";
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 
225 bool 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
void GetCode(CodeDesc *desc)
PositionsRecorder * positions_recorder()
Comment(MacroAssembler *, const char *)
HydrogenCodeStub * code_stub() const
Definition: compiler.h:115
Handle< Script > script() const
Definition: compiler.h:113
FunctionLiteral * function() const
Definition: compiler.h:107
Handle< JSFunction > closure() const
Definition: compiler.h:111
Isolate * isolate() const
Definition: compiler.h:96
void IncrementCodeGeneratedBytes(bool is_crankshafted, int size)
Definition: heap.h:1176
Counters * counters()
Definition: isolate.h:857
CodeTracer * GetCodeTracer()
Definition: isolate.cc:2154
Factory * factory()
Definition: isolate.h:982
Bootstrapper * bootstrapper()
Definition: isolate.h:856
#define __
Definition: codegen.cc:78
#define UNARY_MATH_FUNCTION(name, generator)
Definition: codegen.cc:56
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
double modulo(double x, double y)
Definition: codegen.cc:50
void lazily_initialize_fast_exp()
Definition: codegen.cc:71
UnaryMathFunction CreateExpFunction()
void PrintF(const char *format,...)
Definition: utils.cc:80
UnaryMathFunction CreateSqrtFunction()
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20