v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
code-stubs.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "bootstrapper.h"
31 #include "code-stubs.h"
32 #include "stub-cache.h"
33 #include "factory.h"
34 #include "gdb-jit.h"
35 #include "macro-assembler.h"
36 
37 namespace v8 {
38 namespace internal {
39 
40 bool CodeStub::FindCodeInCache(Code** code_out) {
41  Heap* heap = Isolate::Current()->heap();
42  int index = heap->code_stubs()->FindEntry(GetKey());
44  *code_out = Code::cast(heap->code_stubs()->ValueAt(index));
45  return true;
46  }
47  return false;
48 }
49 
50 
51 void CodeStub::GenerateCode(MacroAssembler* masm) {
52  // Update the static counter each time a new code stub is generated.
53  masm->isolate()->counters()->code_stubs()->Increment();
54 
55  // Nested stubs are not allowed for leaves.
56  AllowStubCallsScope allow_scope(masm, false);
57 
58  // Generate the code for the stub.
59  masm->set_generating_stub(true);
60  NoCurrentFrameScope scope(masm);
61  Generate(masm);
62 }
63 
64 
65 SmartArrayPointer<const char> CodeStub::GetName() {
66  char buffer[100];
67  NoAllocationStringAllocator allocator(buffer,
68  static_cast<unsigned>(sizeof(buffer)));
69  StringStream stream(&allocator);
70  PrintName(&stream);
71  return stream.ToCString();
72 }
73 
74 
75 void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
76  Isolate* isolate = masm->isolate();
77  SmartArrayPointer<const char> name = GetName();
78  PROFILE(isolate, CodeCreateEvent(Logger::STUB_TAG, code, *name));
79  GDBJIT(AddCode(GDBJITInterface::STUB, *name, code));
80  Counters* counters = isolate->counters();
81  counters->total_stubs_code_size()->Increment(code->instruction_size());
82 }
83 
84 
85 int CodeStub::GetCodeKind() {
86  return Code::STUB;
87 }
88 
89 
90 Handle<Code> CodeStub::GetCode() {
91  Isolate* isolate = Isolate::Current();
92  Factory* factory = isolate->factory();
93  Heap* heap = isolate->heap();
94  Code* code;
95  if (UseSpecialCache()
96  ? FindCodeInSpecialCache(&code)
97  : FindCodeInCache(&code)) {
98  ASSERT(IsPregenerated() == code->is_pregenerated());
99  return Handle<Code>(code);
100  }
101 
102  {
103  HandleScope scope(isolate);
104 
105  // Generate the new code.
106  MacroAssembler masm(isolate, NULL, 256);
107  GenerateCode(&masm);
108 
109  // Create the code object.
110  CodeDesc desc;
111  masm.GetCode(&desc);
112 
113  // Copy the generated code into a heap object.
115  static_cast<Code::Kind>(GetCodeKind()),
116  GetICState());
117  Handle<Code> new_object = factory->NewCode(
118  desc, flags, masm.CodeObject(), NeedsImmovableCode());
119  new_object->set_major_key(MajorKey());
120  FinishCode(new_object);
121  RecordCodeGeneration(*new_object, &masm);
122 
123 #ifdef ENABLE_DISASSEMBLER
124  if (FLAG_print_code_stubs) {
125  new_object->Disassemble(*GetName());
126  PrintF("\n");
127  }
128 #endif
129 
130  if (UseSpecialCache()) {
131  AddToSpecialCache(new_object);
132  } else {
133  // Update the dictionary and the root in Heap.
134  Handle<UnseededNumberDictionary> dict =
135  factory->DictionaryAtNumberPut(
136  Handle<UnseededNumberDictionary>(heap->code_stubs()),
137  GetKey(),
138  new_object);
139  heap->public_set_code_stubs(*dict);
140  }
141  code = *new_object;
142  }
143 
144  Activate(code);
145  ASSERT(!NeedsImmovableCode() ||
146  heap->lo_space()->Contains(code) ||
147  heap->code_space()->FirstPage()->Contains(code->address()));
148  return Handle<Code>(code, isolate);
149 }
150 
151 
152 const char* CodeStub::MajorName(CodeStub::Major major_key,
153  bool allow_unknown_keys) {
154  switch (major_key) {
155 #define DEF_CASE(name) case name: return #name "Stub";
157 #undef DEF_CASE
158  default:
159  if (!allow_unknown_keys) {
160  UNREACHABLE();
161  }
162  return NULL;
163  }
164 }
165 
166 
167 void CodeStub::PrintName(StringStream* stream) {
168  stream->Add("%s", MajorName(MajorKey(), false));
169 }
170 
171 
172 void ICCompareStub::AddToSpecialCache(Handle<Code> new_object) {
173  ASSERT(*known_map_ != NULL);
174  Isolate* isolate = new_object->GetIsolate();
175  Factory* factory = isolate->factory();
176  return Map::UpdateCodeCache(known_map_,
177  strict() ?
178  factory->strict_compare_ic_symbol() :
179  factory->compare_ic_symbol(),
180  new_object);
181 }
182 
183 
184 bool ICCompareStub::FindCodeInSpecialCache(Code** code_out) {
185  Isolate* isolate = known_map_->GetIsolate();
186  Factory* factory = isolate->factory();
188  static_cast<Code::Kind>(GetCodeKind()),
189  UNINITIALIZED);
190  ASSERT(op_ == Token::EQ || op_ == Token::EQ_STRICT);
191  Handle<Object> probe(
192  known_map_->FindInCodeCache(
193  strict() ?
194  *factory->strict_compare_ic_symbol() :
195  *factory->compare_ic_symbol(),
196  flags));
197  if (probe->IsCode()) {
198  *code_out = Code::cast(*probe);
199  ASSERT(op_ == (*code_out)->compare_operation() + Token::EQ);
200  return true;
201  }
202  return false;
203 }
204 
205 
206 int ICCompareStub::MinorKey() {
207  return OpField::encode(op_ - Token::EQ) | StateField::encode(state_);
208 }
209 
210 
212  switch (state_) {
214  GenerateMiss(masm);
215  break;
216  case CompareIC::SMIS:
217  GenerateSmis(masm);
218  break;
220  GenerateHeapNumbers(masm);
221  break;
222  case CompareIC::STRINGS:
223  GenerateStrings(masm);
224  break;
225  case CompareIC::SYMBOLS:
226  GenerateSymbols(masm);
227  break;
228  case CompareIC::OBJECTS:
229  GenerateObjects(masm);
230  break;
232  ASSERT(*known_map_ != NULL);
233  GenerateKnownObjects(masm);
234  break;
235  default:
236  UNREACHABLE();
237  }
238 }
239 
240 
241 void InstanceofStub::PrintName(StringStream* stream) {
242  const char* args = "";
243  if (HasArgsInRegisters()) {
244  args = "_REGS";
245  }
246 
247  const char* inline_check = "";
248  if (HasCallSiteInlineCheck()) {
249  inline_check = "_INLINE";
250  }
251 
252  const char* return_true_false_object = "";
253  if (ReturnTrueFalseObject()) {
254  return_true_false_object = "_TRUEFALSE";
255  }
256 
257  stream->Add("InstanceofStub%s%s%s",
258  args,
259  inline_check,
260  return_true_false_object);
261 }
262 
263 
264 void JSEntryStub::FinishCode(Handle<Code> code) {
265  Handle<FixedArray> handler_table =
266  code->GetIsolate()->factory()->NewFixedArray(1, TENURED);
267  handler_table->set(0, Smi::FromInt(handler_offset_));
268  code->set_handler_table(*handler_table);
269 }
270 
271 
273  switch (elements_kind_) {
274  case FAST_ELEMENTS:
275  case FAST_HOLEY_ELEMENTS:
276  case FAST_SMI_ELEMENTS:
279  break;
283  break;
294  break;
295  case DICTIONARY_ELEMENTS:
297  break;
299  UNREACHABLE();
300  break;
301  }
302 }
303 
304 
306  switch (elements_kind_) {
307  case FAST_ELEMENTS:
308  case FAST_HOLEY_ELEMENTS:
309  case FAST_SMI_ELEMENTS:
312  is_js_array_,
313  elements_kind_,
314  grow_mode_);
315  }
316  break;
320  is_js_array_,
321  grow_mode_);
322  break;
333  break;
334  case DICTIONARY_ELEMENTS:
336  break;
338  UNREACHABLE();
339  break;
340  }
341 }
342 
343 
344 void ArgumentsAccessStub::PrintName(StringStream* stream) {
345  stream->Add("ArgumentsAccessStub_");
346  switch (type_) {
347  case READ_ELEMENT: stream->Add("ReadElement"); break;
348  case NEW_NON_STRICT_FAST: stream->Add("NewNonStrictFast"); break;
349  case NEW_NON_STRICT_SLOW: stream->Add("NewNonStrictSlow"); break;
350  case NEW_STRICT: stream->Add("NewStrict"); break;
351  }
352 }
353 
354 
355 void CallFunctionStub::PrintName(StringStream* stream) {
356  stream->Add("CallFunctionStub_Args%d", argc_);
357  if (ReceiverMightBeImplicit()) stream->Add("_Implicit");
358  if (RecordCallTarget()) stream->Add("_Recording");
359 }
360 
361 
362 void CallConstructStub::PrintName(StringStream* stream) {
363  stream->Add("CallConstructStub");
364  if (RecordCallTarget()) stream->Add("_Recording");
365 }
366 
367 
369  stream->Add("ToBooleanStub_");
370  types_.Print(stream);
371 }
372 
373 
375  if (IsEmpty()) stream->Add("None");
376  if (Contains(UNDEFINED)) stream->Add("Undefined");
377  if (Contains(BOOLEAN)) stream->Add("Bool");
378  if (Contains(NULL_TYPE)) stream->Add("Null");
379  if (Contains(SMI)) stream->Add("Smi");
380  if (Contains(SPEC_OBJECT)) stream->Add("SpecObject");
381  if (Contains(STRING)) stream->Add("String");
382  if (Contains(HEAP_NUMBER)) stream->Add("HeapNumber");
383 }
384 
385 
387  if (!FLAG_trace_ic) return;
388  char buffer[100];
389  NoAllocationStringAllocator allocator(buffer,
390  static_cast<unsigned>(sizeof(buffer)));
391  StringStream stream(&allocator);
392  stream.Add("[ToBooleanIC (");
393  Print(&stream);
394  stream.Add("->");
395  to.Print(&stream);
396  stream.Add(")]\n");
397  stream.OutputToStdOut();
398 }
399 
400 
402  if (object->IsUndefined()) {
403  Add(UNDEFINED);
404  return false;
405  } else if (object->IsBoolean()) {
406  Add(BOOLEAN);
407  return object->IsTrue();
408  } else if (object->IsNull()) {
409  Add(NULL_TYPE);
410  return false;
411  } else if (object->IsSmi()) {
412  Add(SMI);
413  return Smi::cast(*object)->value() != 0;
414  } else if (object->IsSpecObject()) {
415  Add(SPEC_OBJECT);
416  return !object->IsUndetectableObject();
417  } else if (object->IsString()) {
418  Add(STRING);
419  return !object->IsUndetectableObject() &&
420  String::cast(*object)->length() != 0;
421  } else if (object->IsHeapNumber()) {
422  ASSERT(!object->IsUndetectableObject());
423  Add(HEAP_NUMBER);
424  double value = HeapNumber::cast(*object)->value();
425  return value != 0 && !isnan(value);
426  } else {
427  // We should never see an internal object at runtime here!
428  UNREACHABLE();
429  return true;
430  }
431 }
432 
433 
435  return Contains(ToBooleanStub::SPEC_OBJECT)
436  || Contains(ToBooleanStub::STRING)
437  || Contains(ToBooleanStub::HEAP_NUMBER);
438 }
439 
440 
442  return Contains(ToBooleanStub::SPEC_OBJECT)
443  || Contains(ToBooleanStub::STRING);
444 }
445 
446 
447 void ElementsTransitionAndStoreStub::Generate(MacroAssembler* masm) {
448  Label fail;
450  if (!FLAG_trace_elements_transitions) {
452  if (IsFastSmiOrObjectElementsKind(from_)) {
455  } else if (IsFastDoubleElementsKind(from_)) {
458  } else {
459  UNREACHABLE();
460  }
462  is_jsarray_,
463  to_,
464  grow_mode_);
465  } else if (IsFastSmiElementsKind(from_) &&
469  is_jsarray_,
470  grow_mode_);
471  } else if (IsFastDoubleElementsKind(from_)) {
475  } else {
476  UNREACHABLE();
477  }
478  }
479  masm->bind(&fail);
480  KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_);
481 }
482 
483 
484 FunctionEntryHook ProfileEntryHookStub::entry_hook_ = NULL;
485 
486 
487 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function,
488  intptr_t stack_pointer) {
489  if (entry_hook_ != NULL)
490  entry_hook_(function, stack_pointer);
491 }
492 
493 
495  // We don't allow setting a new entry hook over one that's
496  // already active, as the hooks won't stack.
497  if (entry_hook != 0 && entry_hook_ != 0)
498  return false;
499 
500  entry_hook_ = entry_hook;
501  return true;
502 }
503 
504 
505 } } // namespace v8::internal
void PrintF(const char *format,...)
Definition: v8utils.cc:40
#define DEF_CASE(name)
static String * cast(Object *obj)
static Smi * FromInt(int value)
Definition: objects-inl.h:981
static void GenerateStoreExternalArray(MacroAssembler *masm, ElementsKind elements_kind)
static void GenerateLoadFastDoubleElement(MacroAssembler *masm)
virtual void PrintName(StringStream *stream)
Definition: code-stubs.cc:368
bool Record(Handle< Object > object)
Definition: code-stubs.cc:401
#define ASSERT(condition)
Definition: checks.h:270
v8::Handle< v8::Value > Print(const v8::Arguments &args)
static bool SetFunctionEntryHook(FunctionEntryHook entry_hook)
Definition: code-stubs.cc:494
#define PROFILE(isolate, Call)
Definition: cpu-profiler.h:190
int isnan(double x)
static Code * cast(Object *obj)
static Smi * cast(Object *object)
void Add(Vector< const char > format, Vector< FmtElm > elms)
void(* FunctionEntryHook)(uintptr_t function, uintptr_t return_addr_location)
Definition: v8.h:2965
#define UNREACHABLE()
Definition: checks.h:50
static void GenerateStoreFastElement(MacroAssembler *masm, bool is_js_array, ElementsKind element_kind, KeyedAccessGrowMode grow_mode)
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, StubType type=NORMAL, int argc=-1, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:3491
bool IsFastSmiElementsKind(ElementsKind kind)
static void GenerateSmiToDouble(MacroAssembler *masm, Label *fail)
static void GenerateMapChangeElementsTransition(MacroAssembler *masm)
static void GenerateLoadDictionaryElement(MacroAssembler *masm)
static void GenerateLoadExternalArray(MacroAssembler *masm, ElementsKind elements_kind)
bool IsFastSmiOrObjectElementsKind(ElementsKind kind)
#define GDBJIT(action)
Definition: gdb-jit.h:141
static void UpdateCodeCache(Handle< Map > map, Handle< String > name, Handle< Code > code)
Definition: objects.cc:5261
static HeapNumber * cast(Object *obj)
static void GenerateRuntimeSetProperty(MacroAssembler *masm, StrictModeFlag strict_mode)
static void GenerateDoubleToObject(MacroAssembler *masm, Label *fail)
static void GenerateLoadFastElement(MacroAssembler *masm)
static void GenerateStoreFastDoubleElement(MacroAssembler *masm, bool is_js_array, KeyedAccessGrowMode grow_mode)
void Generate(MacroAssembler *masm)
Definition: code-stubs.cc:305
void TraceTransition(Types to) const
Definition: code-stubs.cc:386
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
bool IsFastHoleyElementsKind(ElementsKind kind)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
bool Contains(Type type) const
Definition: code-stubs.h:1055
virtual void Generate(MacroAssembler *masm)
Definition: code-stubs.cc:211
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage including flags
Definition: flags.cc:495
#define CODE_STUB_LIST(V)
Definition: code-stubs.h:101
void Print(StringStream *stream) const
Definition: code-stubs.cc:374
void Generate(MacroAssembler *masm)
Definition: code-stubs.cc:272
bool IsFastDoubleElementsKind(ElementsKind kind)
static void GenerateStoreDictionaryElement(MacroAssembler *masm)
Definition: stub-cache.cc:1425