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
ic.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 "accessors.h"
31 #include "api.h"
32 #include "arguments.h"
33 #include "codegen.h"
34 #include "execution.h"
35 #include "ic-inl.h"
36 #include "runtime.h"
37 #include "stub-cache.h"
38 
39 namespace v8 {
40 namespace internal {
41 
42 #ifdef DEBUG
43 char IC::TransitionMarkFromState(IC::State state) {
44  switch (state) {
45  case UNINITIALIZED: return '0';
46  case PREMONOMORPHIC: return 'P';
47  case MONOMORPHIC: return '1';
48  case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
49  case MEGAMORPHIC: return IsGeneric() ? 'G' : 'N';
50 
51  // We never see the debugger states here, because the state is
52  // computed from the original code - not the patched code. Let
53  // these cases fall through to the unreachable code below.
54  case DEBUG_BREAK: break;
55  case DEBUG_PREPARE_STEP_IN: break;
56  }
57  UNREACHABLE();
58  return 0;
59 }
60 
61 void IC::TraceIC(const char* type,
62  Handle<Object> name,
63  State old_state,
64  Code* new_target) {
65  if (FLAG_trace_ic) {
66  State new_state = StateFrom(new_target,
67  HEAP->undefined_value(),
68  HEAP->undefined_value());
69  PrintF("[%s in ", type);
70  StackFrameIterator it;
71  while (it.frame()->fp() != this->fp()) it.Advance();
72  StackFrame* raw_frame = it.frame();
73  if (raw_frame->is_internal()) {
74  Isolate* isolate = new_target->GetIsolate();
75  Code* apply_builtin = isolate->builtins()->builtin(
76  Builtins::kFunctionApply);
77  if (raw_frame->unchecked_code() == apply_builtin) {
78  PrintF("apply from ");
79  it.Advance();
80  raw_frame = it.frame();
81  }
82  }
83  JavaScriptFrame::PrintTop(stdout, false, true);
84  bool new_can_grow =
85  Code::GetKeyedAccessGrowMode(new_target->extra_ic_state()) ==
87  PrintF(" (%c->%c%s)",
88  TransitionMarkFromState(old_state),
89  TransitionMarkFromState(new_state),
90  new_can_grow ? ".GROW" : "");
91  name->Print();
92  PrintF("]\n");
93  }
94 }
95 
96 #define TRACE_GENERIC_IC(type, reason) \
97  do { \
98  if (FLAG_trace_ic) { \
99  PrintF("[%s patching generic stub in ", type); \
100  JavaScriptFrame::PrintTop(stdout, false, true); \
101  PrintF(" (%s)]\n", reason); \
102  } \
103  } while (false)
104 
105 #else
106 #define TRACE_GENERIC_IC(type, reason)
107 #endif // DEBUG
108 
109 #define TRACE_IC(type, name, old_state, new_target) \
110  ASSERT((TraceIC(type, name, old_state, new_target), true))
111 
112 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
113  ASSERT(isolate == Isolate::Current());
114  // To improve the performance of the (much used) IC code, we unfold
115  // a few levels of the stack frame iteration code. This yields a
116  // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag.
117  const Address entry =
119  Address* pc_address =
120  reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
122  // If there's another JavaScript frame on the stack, we need to look
123  // one frame further down the stack to find the frame pointer and
124  // the return address stack slot.
125  if (depth == EXTRA_CALL_FRAME) {
126  const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
127  pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
129  }
130 #ifdef DEBUG
131  StackFrameIterator it;
132  for (int i = 0; i < depth + 1; i++) it.Advance();
133  StackFrame* frame = it.frame();
134  ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
135 #endif
136  fp_ = fp;
137  pc_address_ = pc_address;
138 }
139 
140 
141 #ifdef ENABLE_DEBUGGER_SUPPORT
142 Address IC::OriginalCodeAddress() const {
143  HandleScope scope;
144  // Compute the JavaScript frame for the frame pointer of this IC
145  // structure. We need this to be able to find the function
146  // corresponding to the frame.
147  StackFrameIterator it;
148  while (it.frame()->fp() != this->fp()) it.Advance();
149  JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
150  // Find the function on the stack and both the active code for the
151  // function and the original code.
152  JSFunction* function = JSFunction::cast(frame->function());
153  Handle<SharedFunctionInfo> shared(function->shared());
154  Code* code = shared->code();
155  ASSERT(Debug::HasDebugInfo(shared));
156  Code* original_code = Debug::GetDebugInfo(shared)->original_code();
157  ASSERT(original_code->IsCode());
158  // Get the address of the call site in the active code. This is the
159  // place where the call to DebugBreakXXX is and where the IC
160  // normally would be.
162  // Return the address in the original code. This is the place where
163  // the call which has been overwritten by the DebugBreakXXX resides
164  // and the place where the inline cache system should look.
165  intptr_t delta =
166  original_code->instruction_start() - code->instruction_start();
167  return addr + delta;
168 }
169 #endif
170 
171 
172 static bool HasNormalObjectsInPrototypeChain(Isolate* isolate,
173  LookupResult* lookup,
174  Object* receiver) {
175  Object* end = lookup->IsProperty()
176  ? lookup->holder() : Object::cast(isolate->heap()->null_value());
177  for (Object* current = receiver;
178  current != end;
179  current = current->GetPrototype()) {
180  if (current->IsJSObject() &&
181  !JSObject::cast(current)->HasFastProperties() &&
182  !current->IsJSGlobalProxy() &&
183  !current->IsJSGlobalObject()) {
184  return true;
185  }
186  }
187 
188  return false;
189 }
190 
191 
192 static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
193  Object* receiver,
194  Object* name) {
195  InlineCacheHolderFlag cache_holder =
196  Code::ExtractCacheHolderFromFlags(target->flags());
197 
198  if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
199  // The stub was generated for JSObject but called for non-JSObject.
200  // IC::GetCodeCacheHolder is not applicable.
201  return false;
202  } else if (cache_holder == PROTOTYPE_MAP &&
203  receiver->GetPrototype()->IsNull()) {
204  // IC::GetCodeCacheHolder is not applicable.
205  return false;
206  }
207  Map* map = IC::GetCodeCacheHolder(receiver, cache_holder)->map();
208 
209  // Decide whether the inline cache failed because of changes to the
210  // receiver itself or changes to one of its prototypes.
211  //
212  // If there are changes to the receiver itself, the map of the
213  // receiver will have changed and the current target will not be in
214  // the receiver map's code cache. Therefore, if the current target
215  // is in the receiver map's code cache, the inline cache failed due
216  // to prototype check failure.
217  int index = map->IndexInCodeCache(name, target);
218  if (index >= 0) {
219  map->RemoveFromCodeCache(String::cast(name), target, index);
220  return true;
221  }
222 
223  return false;
224 }
225 
226 
227 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
228  IC::State state = target->ic_state();
229 
230  if (state != MONOMORPHIC || !name->IsString()) return state;
231  if (receiver->IsUndefined() || receiver->IsNull()) return state;
232 
233  // For keyed load/store/call, the most likely cause of cache failure is
234  // that the key has changed. We do not distinguish between
235  // prototype and non-prototype failures for keyed access.
236  Code::Kind kind = target->kind();
237  if (kind == Code::KEYED_LOAD_IC ||
238  kind == Code::KEYED_STORE_IC ||
239  kind == Code::KEYED_CALL_IC) {
240  return MONOMORPHIC;
241  }
242 
243  // Remove the target from the code cache if it became invalid
244  // because of changes in the prototype chain to avoid hitting it
245  // again.
246  // Call stubs handle this later to allow extra IC state
247  // transitions.
248  if (kind != Code::CALL_IC &&
249  TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
251  }
252 
253  // The builtins object is special. It only changes when JavaScript
254  // builtins are loaded lazily. It is important to keep inline
255  // caches for the builtins object monomorphic. Therefore, if we get
256  // an inline cache miss for the builtins object after lazily loading
257  // JavaScript builtins, we return uninitialized as the state to
258  // force the inline cache back to monomorphic state.
259  if (receiver->IsJSBuiltinsObject()) {
260  return UNINITIALIZED;
261  }
262 
263  return MONOMORPHIC;
264 }
265 
266 
267 RelocInfo::Mode IC::ComputeMode() {
268  Address addr = address();
269  Code* code = Code::cast(isolate()->heap()->FindCodeObject(addr));
270  for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
271  !it.done(); it.next()) {
272  RelocInfo* info = it.rinfo();
273  if (info->pc() == addr) return info->rmode();
274  }
275  UNREACHABLE();
276  return RelocInfo::NONE;
277 }
278 
279 
280 Failure* IC::TypeError(const char* type,
281  Handle<Object> object,
282  Handle<Object> key) {
283  HandleScope scope(isolate());
284  Handle<Object> args[2] = { key, object };
286  type, HandleVector(args, 2));
287  return isolate()->Throw(*error);
288 }
289 
290 
291 Failure* IC::ReferenceError(const char* type, Handle<String> name) {
292  HandleScope scope(isolate());
294  type, HandleVector(&name, 1));
295  return isolate()->Throw(*error);
296 }
297 
298 
299 static int ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state) {
300  bool was_uninitialized =
301  old_state == UNINITIALIZED || old_state == PREMONOMORPHIC;
302  bool is_uninitialized =
303  new_state == UNINITIALIZED || new_state == PREMONOMORPHIC;
304  return (was_uninitialized && !is_uninitialized) ? 1 :
305  (!was_uninitialized && is_uninitialized) ? -1 : 0;
306 }
307 
308 
309 void IC::PostPatching(Address address, Code* target, Code* old_target) {
310  if (FLAG_type_info_threshold == 0 && !FLAG_watch_ic_patching) {
311  return;
312  }
313  Code* host = target->GetHeap()->isolate()->
314  inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
315  if (host->kind() != Code::FUNCTION) return;
316 
317  if (FLAG_type_info_threshold > 0 &&
318  old_target->is_inline_cache_stub() &&
319  target->is_inline_cache_stub()) {
320  int delta = ComputeTypeInfoCountDelta(old_target->ic_state(),
321  target->ic_state());
322  // Not all Code objects have TypeFeedbackInfo.
323  if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) {
324  TypeFeedbackInfo* info =
325  TypeFeedbackInfo::cast(host->type_feedback_info());
326  info->change_ic_with_type_info_count(delta);
327  }
328  }
329  if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
330  TypeFeedbackInfo* info =
331  TypeFeedbackInfo::cast(host->type_feedback_info());
333  }
334  if (FLAG_watch_ic_patching) {
335  host->set_profiler_ticks(0);
336  Isolate::Current()->runtime_profiler()->NotifyICChanged();
337  }
338  // TODO(2029): When an optimized function is patched, it would
339  // be nice to propagate the corresponding type information to its
340  // unoptimized version for the benefit of later inlining.
341 }
342 
343 
344 void IC::Clear(Address address) {
345  Code* target = GetTargetAtAddress(address);
346 
347  // Don't clear debug break inline cache as it will remove the break point.
348  if (target->ic_state() == DEBUG_BREAK) return;
349 
350  switch (target->kind()) {
351  case Code::LOAD_IC: return LoadIC::Clear(address, target);
352  case Code::KEYED_LOAD_IC:
353  return KeyedLoadIC::Clear(address, target);
354  case Code::STORE_IC: return StoreIC::Clear(address, target);
355  case Code::KEYED_STORE_IC:
356  return KeyedStoreIC::Clear(address, target);
357  case Code::CALL_IC: return CallIC::Clear(address, target);
358  case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
359  case Code::COMPARE_IC: return CompareIC::Clear(address, target);
360  case Code::UNARY_OP_IC:
361  case Code::BINARY_OP_IC:
362  case Code::TO_BOOLEAN_IC:
363  // Clearing these is tricky and does not
364  // make any performance difference.
365  return;
366  default: UNREACHABLE();
367  }
368 }
369 
370 
371 void CallICBase::Clear(Address address, Code* target) {
372  if (target->ic_state() == UNINITIALIZED) return;
373  bool contextual = CallICBase::Contextual::decode(target->extra_ic_state());
374  Code* code =
375  Isolate::Current()->stub_cache()->FindCallInitialize(
376  target->arguments_count(),
377  contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET,
378  target->kind());
379  SetTargetAtAddress(address, code);
380 }
381 
382 
383 void KeyedLoadIC::Clear(Address address, Code* target) {
384  if (target->ic_state() == UNINITIALIZED) return;
385  // Make sure to also clear the map used in inline fast cases. If we
386  // do not clear these maps, cached code can keep objects alive
387  // through the embedded maps.
388  SetTargetAtAddress(address, initialize_stub());
389 }
390 
391 
392 void LoadIC::Clear(Address address, Code* target) {
393  if (target->ic_state() == UNINITIALIZED) return;
394  SetTargetAtAddress(address, initialize_stub());
395 }
396 
397 
398 void StoreIC::Clear(Address address, Code* target) {
399  if (target->ic_state() == UNINITIALIZED) return;
400  SetTargetAtAddress(address,
401  (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
402  ? initialize_stub_strict()
403  : initialize_stub());
404 }
405 
406 
407 void KeyedStoreIC::Clear(Address address, Code* target) {
408  if (target->ic_state() == UNINITIALIZED) return;
409  SetTargetAtAddress(address,
410  (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
411  ? initialize_stub_strict()
412  : initialize_stub());
413 }
414 
415 
416 void CompareIC::Clear(Address address, Code* target) {
417  // Only clear ICCompareStubs, we currently cannot clear generic CompareStubs.
418  if (target->major_key() != CodeStub::CompareIC) return;
419  // Only clear CompareICs that can retain objects.
420  if (target->compare_state() != KNOWN_OBJECTS) return;
422  SetTargetAtAddress(address, GetRawUninitialized(op));
424 }
425 
426 
427 static bool HasInterceptorGetter(JSObject* object) {
428  return !object->GetNamedInterceptor()->getter()->IsUndefined();
429 }
430 
431 
432 static void LookupForRead(Handle<Object> object,
433  Handle<String> name,
434  LookupResult* lookup) {
435  // Skip all the objects with named interceptors, but
436  // without actual getter.
437  while (true) {
438  object->Lookup(*name, lookup);
439  // Besides normal conditions (property not found or it's not
440  // an interceptor), bail out if lookup is not cacheable: we won't
441  // be able to IC it anyway and regular lookup should work fine.
442  if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
443  return;
444  }
445 
446  Handle<JSObject> holder(lookup->holder());
447  if (HasInterceptorGetter(*holder)) {
448  return;
449  }
450 
451  holder->LocalLookupRealNamedProperty(*name, lookup);
452  if (lookup->IsFound()) {
453  ASSERT(!lookup->IsInterceptor());
454  return;
455  }
456 
457  Handle<Object> proto(holder->GetPrototype());
458  if (proto->IsNull()) {
459  ASSERT(!lookup->IsFound());
460  return;
461  }
462 
463  object = proto;
464  }
465 }
466 
467 
470 
471  if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) {
472  // Patch the receiver and use the delegate as the function to
473  // invoke. This is used for invoking objects as if they were functions.
474  const int argc = target()->arguments_count();
475  StackFrameLocator locator;
476  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
477  int index = frame->ComputeExpressionsCount() - (argc + 1);
478  frame->SetExpression(index, *object);
479  }
480 
481  return delegate;
482 }
483 
484 
486  Handle<Object> object) {
487  while (callee->IsJSFunctionProxy()) {
488  callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap());
489  }
490 
491  if (callee->IsJSFunction()) {
492  Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
493  if (!function->shared()->is_classic_mode() || function->IsBuiltin()) {
494  // Do not wrap receiver for strict mode functions or for builtins.
495  return;
496  }
497  }
498 
499  // And only wrap string, number or boolean.
500  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
501  // Change the receiver to the result of calling ToObject on it.
502  const int argc = this->target()->arguments_count();
503  StackFrameLocator locator;
504  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
505  int index = frame->ComputeExpressionsCount() - (argc + 1);
506  frame->SetExpression(index, *isolate()->factory()->ToObject(object));
507  }
508 }
509 
510 
511 MaybeObject* CallICBase::LoadFunction(State state,
512  Code::ExtraICState extra_ic_state,
513  Handle<Object> object,
514  Handle<String> name) {
515  // If the object is undefined or null it's illegal to try to get any
516  // of its properties; throw a TypeError in that case.
517  if (object->IsUndefined() || object->IsNull()) {
518  return TypeError("non_object_property_call", object, name);
519  }
520 
521  // Check if the name is trivially convertible to an index and get
522  // the element if so.
523  uint32_t index;
524  if (name->AsArrayIndex(&index)) {
525  Handle<Object> result = Object::GetElement(object, index);
526  RETURN_IF_EMPTY_HANDLE(isolate(), result);
527  if (result->IsJSFunction()) return *result;
528 
529  // Try to find a suitable function delegate for the object at hand.
530  result = TryCallAsFunction(result);
531  if (result->IsJSFunction()) return *result;
532 
533  // Otherwise, it will fail in the lookup step.
534  }
535 
536  // Lookup the property in the object.
537  LookupResult lookup(isolate());
538  LookupForRead(object, name, &lookup);
539 
540  if (!lookup.IsFound()) {
541  // If the object does not have the requested property, check which
542  // exception we need to throw.
543  return IsContextual(object)
544  ? ReferenceError("not_defined", name)
545  : TypeError("undefined_method", object, name);
546  }
547 
548  // Lookup is valid: Update inline cache and stub cache.
549  if (FLAG_use_ic) {
550  UpdateCaches(&lookup, state, extra_ic_state, object, name);
551  }
552 
553  // Get the property.
554  PropertyAttributes attr;
555  Handle<Object> result =
556  Object::GetProperty(object, object, &lookup, name, &attr);
557  RETURN_IF_EMPTY_HANDLE(isolate(), result);
558 
559  if (lookup.IsInterceptor() && attr == ABSENT) {
560  // If the object does not have the requested property, check which
561  // exception we need to throw.
562  return IsContextual(object)
563  ? ReferenceError("not_defined", name)
564  : TypeError("undefined_method", object, name);
565  }
566 
567  ASSERT(!result->IsTheHole());
568 
569  // Make receiver an object if the callee requires it. Strict mode or builtin
570  // functions do not wrap the receiver, non-strict functions and objects
571  // called as functions do.
572  ReceiverToObjectIfRequired(result, object);
573 
574  if (result->IsJSFunction()) {
575  Handle<JSFunction> function = Handle<JSFunction>::cast(result);
576 #ifdef ENABLE_DEBUGGER_SUPPORT
577  // Handle stepping into a function if step into is active.
578  Debug* debug = isolate()->debug();
579  if (debug->StepInActive()) {
580  // Protect the result in a handle as the debugger can allocate and might
581  // cause GC.
582  debug->HandleStepIn(function, object, fp(), false);
583  }
584 #endif
585  return *function;
586  }
587 
588  // Try to find a suitable function delegate for the object at hand.
589  result = TryCallAsFunction(result);
590  if (result->IsJSFunction()) return *result;
591 
592  return TypeError("property_not_function", object, name);
593 }
594 
595 
596 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
597  Handle<Object> object,
598  Code::ExtraICState* extra_ic_state) {
599  ASSERT(kind_ == Code::CALL_IC);
600  if (lookup->type() != CONSTANT_FUNCTION) return false;
601  JSFunction* function = lookup->GetConstantFunction();
602  if (!function->shared()->HasBuiltinFunctionId()) return false;
603 
604  // Fetch the arguments passed to the called function.
605  const int argc = target()->arguments_count();
606  Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
608  Arguments args(argc + 1,
609  &Memory::Object_at(fp +
611  argc * kPointerSize));
612  switch (function->shared()->builtin_function_id()) {
613  case kStringCharCodeAt:
614  case kStringCharAt:
615  if (object->IsString()) {
616  String* string = String::cast(*object);
617  // Check there's the right string value or wrapper in the receiver slot.
618  ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
619  // If we're in the default (fastest) state and the index is
620  // out of bounds, update the state to record this fact.
621  if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB &&
622  argc >= 1 && args[1]->IsNumber()) {
623  double index = DoubleToInteger(args.number_at(1));
624  if (index < 0 || index >= string->length()) {
625  *extra_ic_state =
626  StringStubState::update(*extra_ic_state,
628  return true;
629  }
630  }
631  }
632  break;
633  default:
634  return false;
635  }
636  return false;
637 }
638 
639 
641  State state,
642  Code::ExtraICState extra_state,
643  Handle<Object> object,
644  Handle<String> name) {
645  int argc = target()->arguments_count();
646  Handle<JSObject> holder(lookup->holder());
647  switch (lookup->type()) {
648  case FIELD: {
649  int index = lookup->GetFieldIndex();
650  return isolate()->stub_cache()->ComputeCallField(
651  argc, kind_, extra_state, name, object, holder, index);
652  }
653  case CONSTANT_FUNCTION: {
654  // Get the constant function and compute the code stub for this
655  // call; used for rewriting to monomorphic state and making sure
656  // that the code stub is in the stub cache.
657  Handle<JSFunction> function(lookup->GetConstantFunction());
659  argc, kind_, extra_state, name, object, holder, function);
660  }
661  case NORMAL: {
662  // If we return a null handle, the IC will not be patched.
663  if (!object->IsJSObject()) return Handle<Code>::null();
664  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
665 
666  if (holder->IsGlobalObject()) {
668  Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
669  if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
670  Handle<JSFunction> function(JSFunction::cast(cell->value()));
671  return isolate()->stub_cache()->ComputeCallGlobal(
672  argc, kind_, extra_state, name, receiver, global, cell, function);
673  } else {
674  // There is only one shared stub for calling normalized
675  // properties. It does not traverse the prototype chain, so the
676  // property must be found in the receiver for the stub to be
677  // applicable.
678  if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
679  return isolate()->stub_cache()->ComputeCallNormal(
680  argc, kind_, extra_state);
681  }
682  break;
683  }
684  case INTERCEPTOR:
685  ASSERT(HasInterceptorGetter(*holder));
687  argc, kind_, extra_state, name, object, holder);
688  default:
689  return Handle<Code>::null();
690  }
691 }
692 
693 
694 void CallICBase::UpdateCaches(LookupResult* lookup,
695  State state,
696  Code::ExtraICState extra_ic_state,
697  Handle<Object> object,
698  Handle<String> name) {
699  // Bail out if we didn't find a result.
700  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
701 
702  if (lookup->holder() != *object &&
703  HasNormalObjectsInPrototypeChain(
704  isolate(), lookup, object->GetPrototype())) {
705  // Suppress optimization for prototype chains with slow properties objects
706  // in the middle.
707  return;
708  }
709 
710  // Compute the number of arguments.
711  int argc = target()->arguments_count();
712  bool had_proto_failure = false;
714  if (state == UNINITIALIZED) {
715  // This is the first time we execute this inline cache.
716  // Set the target to the pre monomorphic stub to delay
717  // setting the monomorphic state.
719  argc, kind_, extra_ic_state);
720  } else if (state == MONOMORPHIC) {
721  if (kind_ == Code::CALL_IC &&
722  TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
723  code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
724  object, name);
725  } else if (kind_ == Code::CALL_IC &&
726  TryRemoveInvalidPrototypeDependentStub(target(),
727  *object,
728  *name)) {
729  had_proto_failure = true;
730  code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
731  object, name);
732  } else {
734  argc, kind_, extra_ic_state);
735  }
736  } else {
737  code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
738  object, name);
739  }
740 
741  // If there's no appropriate stub we simply avoid updating the caches.
742  if (code.is_null()) return;
743 
744  // Patch the call site depending on the state of the cache.
745  if (state == UNINITIALIZED ||
746  state == PREMONOMORPHIC ||
747  state == MONOMORPHIC ||
749  set_target(*code);
750  } else if (state == MEGAMORPHIC) {
751  // Cache code holding map should be consistent with
752  // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
753  Handle<JSObject> cache_object = object->IsJSObject()
754  ? Handle<JSObject>::cast(object)
755  : Handle<JSObject>(JSObject::cast(object->GetPrototype()));
756  // Update the stub cache.
757  isolate()->stub_cache()->Set(*name, cache_object->map(), *code);
758  }
759 
760  if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
761  TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
762  name, state, target());
763 }
764 
765 
766 MaybeObject* KeyedCallIC::LoadFunction(State state,
767  Handle<Object> object,
768  Handle<Object> key) {
769  if (key->IsSymbol()) {
770  return CallICBase::LoadFunction(state,
772  object,
773  Handle<String>::cast(key));
774  }
775 
776  if (object->IsUndefined() || object->IsNull()) {
777  return TypeError("non_object_property_call", object, key);
778  }
779 
780  if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) {
781  int argc = target()->arguments_count();
782  Handle<Map> map =
783  isolate()->factory()->non_strict_arguments_elements_map();
784  if (object->IsJSObject() &&
785  Handle<JSObject>::cast(object)->elements()->map() == *map) {
787  argc, Code::KEYED_CALL_IC);
788  set_target(*code);
789  TRACE_IC("KeyedCallIC", key, state, target());
790  } else if (!object->IsAccessCheckNeeded()) {
792  argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
793  set_target(*code);
794  TRACE_IC("KeyedCallIC", key, state, target());
795  }
796  }
797 
798  Handle<Object> result = GetProperty(object, key);
799  RETURN_IF_EMPTY_HANDLE(isolate(), result);
800 
801  // Make receiver an object if the callee requires it. Strict mode or builtin
802  // functions do not wrap the receiver, non-strict functions and objects
803  // called as functions do.
804  ReceiverToObjectIfRequired(result, object);
805  if (result->IsJSFunction()) return *result;
806 
807  result = TryCallAsFunction(result);
808  if (result->IsJSFunction()) return *result;
809 
810  return TypeError("property_not_function", object, key);
811 }
812 
813 
814 MaybeObject* LoadIC::Load(State state,
815  Handle<Object> object,
816  Handle<String> name) {
817  // If the object is undefined or null it's illegal to try to get any
818  // of its properties; throw a TypeError in that case.
819  if (object->IsUndefined() || object->IsNull()) {
820  return TypeError("non_object_property_load", object, name);
821  }
822 
823  if (FLAG_use_ic) {
824  // Use specialized code for getting the length of strings and
825  // string wrapper objects. The length property of string wrapper
826  // objects is read-only and therefore always returns the length of
827  // the underlying string value. See ECMA-262 15.5.5.1.
828  if ((object->IsString() || object->IsStringWrapper()) &&
829  name->Equals(isolate()->heap()->length_symbol())) {
830  Handle<Code> stub;
831  if (state == UNINITIALIZED) {
832  stub = pre_monomorphic_stub();
833  } else if (state == PREMONOMORPHIC) {
834  stub = object->IsString()
835  ? isolate()->builtins()->LoadIC_StringLength()
836  : isolate()->builtins()->LoadIC_StringWrapperLength();
837  } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
838  stub = isolate()->builtins()->LoadIC_StringWrapperLength();
839  } else if (state != MEGAMORPHIC) {
840  stub = megamorphic_stub();
841  }
842  if (!stub.is_null()) {
843  set_target(*stub);
844 #ifdef DEBUG
845  if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
846 #endif
847  }
848  // Get the string if we have a string wrapper object.
849  Handle<Object> string = object->IsJSValue()
850  ? Handle<Object>(Handle<JSValue>::cast(object)->value())
851  : object;
852  return Smi::FromInt(String::cast(*string)->length());
853  }
854 
855  // Use specialized code for getting the length of arrays.
856  if (object->IsJSArray() &&
857  name->Equals(isolate()->heap()->length_symbol())) {
858  Handle<Code> stub;
859  if (state == UNINITIALIZED) {
860  stub = pre_monomorphic_stub();
861  } else if (state == PREMONOMORPHIC) {
862  stub = isolate()->builtins()->LoadIC_ArrayLength();
863  } else if (state != MEGAMORPHIC) {
864  stub = megamorphic_stub();
865  }
866  if (!stub.is_null()) {
867  set_target(*stub);
868 #ifdef DEBUG
869  if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
870 #endif
871  }
872  return JSArray::cast(*object)->length();
873  }
874 
875  // Use specialized code for getting prototype of functions.
876  if (object->IsJSFunction() &&
877  name->Equals(isolate()->heap()->prototype_symbol()) &&
878  Handle<JSFunction>::cast(object)->should_have_prototype()) {
879  Handle<Code> stub;
880  if (state == UNINITIALIZED) {
881  stub = pre_monomorphic_stub();
882  } else if (state == PREMONOMORPHIC) {
883  stub = isolate()->builtins()->LoadIC_FunctionPrototype();
884  } else if (state != MEGAMORPHIC) {
885  stub = megamorphic_stub();
886  }
887  if (!stub.is_null()) {
888  set_target(*stub);
889 #ifdef DEBUG
890  if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
891 #endif
892  }
893  return Accessors::FunctionGetPrototype(*object, 0);
894  }
895  }
896 
897  // Check if the name is trivially convertible to an index and get
898  // the element if so.
899  uint32_t index;
900  if (name->AsArrayIndex(&index)) return object->GetElement(index);
901 
902  // Named lookup in the object.
903  LookupResult lookup(isolate());
904  LookupForRead(object, name, &lookup);
905 
906  // If we did not find a property, check if we need to throw an exception.
907  if (!lookup.IsFound()) {
908  if (IsContextual(object)) {
909  return ReferenceError("not_defined", name);
910  }
911  LOG(isolate(), SuspectReadEvent(*name, *object));
912  }
913 
914  // Update inline cache and stub cache.
915  if (FLAG_use_ic) {
916  UpdateCaches(&lookup, state, object, name);
917  }
918 
919  PropertyAttributes attr;
920  if (lookup.IsInterceptor() || lookup.IsHandler()) {
921  // Get the property.
922  Handle<Object> result =
923  Object::GetProperty(object, object, &lookup, name, &attr);
924  RETURN_IF_EMPTY_HANDLE(isolate(), result);
925  // If the property is not present, check if we need to throw an
926  // exception.
927  if (attr == ABSENT && IsContextual(object)) {
928  return ReferenceError("not_defined", name);
929  }
930  return *result;
931  }
932 
933  // Get the property.
934  return object->GetProperty(*object, &lookup, *name, &attr);
935 }
936 
937 
938 void LoadIC::UpdateCaches(LookupResult* lookup,
939  State state,
940  Handle<Object> object,
941  Handle<String> name) {
942  // Bail out if the result is not cacheable.
943  if (!lookup->IsCacheable()) return;
944 
945  // Loading properties from values is not common, so don't try to
946  // deal with non-JS objects here.
947  if (!object->IsJSObject()) return;
948  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
949 
950  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
951 
952  // Compute the code stub for this load.
954  if (state == UNINITIALIZED) {
955  // This is the first time we execute this inline cache.
956  // Set the target to the pre monomorphic stub to delay
957  // setting the monomorphic state.
958  code = pre_monomorphic_stub();
959  } else if (!lookup->IsProperty()) {
960  // Nonexistent property. The result is undefined.
961  code = isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
962  } else {
963  // Compute monomorphic stub.
964  Handle<JSObject> holder(lookup->holder());
965  switch (lookup->type()) {
966  case FIELD:
967  code = isolate()->stub_cache()->ComputeLoadField(
968  name, receiver, holder, lookup->GetFieldIndex());
969  break;
970  case CONSTANT_FUNCTION: {
971  Handle<JSFunction> constant(lookup->GetConstantFunction());
973  name, receiver, holder, constant);
974  break;
975  }
976  case NORMAL:
977  if (holder->IsGlobalObject()) {
978  Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
979  Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
980  code = isolate()->stub_cache()->ComputeLoadGlobal(
981  name, receiver, global, cell, lookup->IsDontDelete());
982  } else {
983  // There is only one shared stub for loading normalized
984  // properties. It does not traverse the prototype chain, so the
985  // property must be found in the receiver for the stub to be
986  // applicable.
987  if (!holder.is_identical_to(receiver)) return;
988  code = isolate()->stub_cache()->ComputeLoadNormal();
989  }
990  break;
991  case CALLBACKS: {
992  Handle<Object> callback(lookup->GetCallbackObject());
993  if (callback->IsAccessorInfo()) {
994  Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
995  if (v8::ToCData<Address>(info->getter()) == 0) return;
996  if (!info->IsCompatibleReceiver(*receiver)) return;
998  name, receiver, holder, info);
999  } else if (callback->IsAccessorPair()) {
1000  Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter());
1001  if (!getter->IsJSFunction()) return;
1002  if (holder->IsGlobalObject()) return;
1003  if (!holder->HasFastProperties()) return;
1005  name, receiver, holder, Handle<JSFunction>::cast(getter));
1006  } else {
1007  ASSERT(callback->IsForeign());
1008  // No IC support for old-style native accessors.
1009  return;
1010  }
1011  break;
1012  }
1013  case INTERCEPTOR:
1014  ASSERT(HasInterceptorGetter(*holder));
1016  name, receiver, holder);
1017  break;
1018  default:
1019  return;
1020  }
1021  }
1022 
1023  // Patch the call site depending on the state of the cache.
1024  if (state == UNINITIALIZED ||
1025  state == PREMONOMORPHIC ||
1026  state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1027  set_target(*code);
1028  } else if (state == MONOMORPHIC) {
1029  // We are transitioning from monomorphic to megamorphic case.
1030  // Place the current monomorphic stub and stub compiled for
1031  // the receiver into stub cache.
1032  Map* map = target()->FindFirstMap();
1033  if (map != NULL) {
1034  isolate()->stub_cache()->Set(*name, map, target());
1035  }
1036  isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1037 
1038  set_target(*megamorphic_stub());
1039  } else if (state == MEGAMORPHIC) {
1040  // Cache code holding map should be consistent with
1041  // GenerateMonomorphicCacheProbe.
1042  isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1043  }
1044 
1045  TRACE_IC("LoadIC", name, state, target());
1046 }
1047 
1048 
1050  bool is_js_array,
1051  ElementsKind elements_kind,
1052  KeyedAccessGrowMode grow_mode) {
1053  ASSERT(grow_mode == DO_NOT_ALLOW_JSARRAY_GROWTH);
1054  return KeyedLoadElementStub(elements_kind).GetCode();
1055 }
1056 
1057 
1059  MapHandleList* receiver_maps,
1060  StrictModeFlag strict_mode,
1061  KeyedAccessGrowMode growth_mode) {
1062  CodeHandleList handler_ics(receiver_maps->length());
1063  for (int i = 0; i < receiver_maps->length(); ++i) {
1064  Handle<Map> receiver_map = receiver_maps->at(i);
1066  receiver_map, strict_mode, growth_mode);
1067  handler_ics.Add(cached_stub);
1068  }
1069  KeyedLoadStubCompiler compiler(isolate());
1070  Handle<Code> code = compiler.CompileLoadPolymorphic(
1071  receiver_maps, &handler_ics);
1072  isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
1073  PROFILE(isolate(),
1074  CodeCreateEvent(Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, *code, 0));
1075  return code;
1076 }
1077 
1078 
1079 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1080  // This helper implements a few common fast cases for converting
1081  // non-smi keys of keyed loads/stores to a smi or a string.
1082  if (key->IsHeapNumber()) {
1083  double value = Handle<HeapNumber>::cast(key)->value();
1084  if (isnan(value)) {
1085  key = isolate->factory()->nan_symbol();
1086  } else {
1087  int int_value = FastD2I(value);
1088  if (value == int_value && Smi::IsValid(int_value)) {
1089  key = Handle<Smi>(Smi::FromInt(int_value));
1090  }
1091  }
1092  } else if (key->IsUndefined()) {
1093  key = isolate->factory()->undefined_symbol();
1094  }
1095  return key;
1096 }
1097 
1098 
1099 MaybeObject* KeyedLoadIC::Load(State state,
1100  Handle<Object> object,
1101  Handle<Object> key,
1102  bool force_generic_stub) {
1103  // Check for values that can be converted into a symbol directly or
1104  // is representable as a smi.
1105  key = TryConvertKey(key, isolate());
1106 
1107  if (key->IsSymbol()) {
1109 
1110  // If the object is undefined or null it's illegal to try to get any
1111  // of its properties; throw a TypeError in that case.
1112  if (object->IsUndefined() || object->IsNull()) {
1113  return TypeError("non_object_property_load", object, name);
1114  }
1115 
1116  if (FLAG_use_ic) {
1117  // TODO(1073): don't ignore the current stub state.
1118 
1119  // Use specialized code for getting the length of strings.
1120  if (object->IsString() &&
1121  name->Equals(isolate()->heap()->length_symbol())) {
1122  Handle<String> string = Handle<String>::cast(object);
1123  Handle<Code> code =
1124  isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, string);
1125  ASSERT(!code.is_null());
1126  set_target(*code);
1127  TRACE_IC("KeyedLoadIC", name, state, target());
1128  return Smi::FromInt(string->length());
1129  }
1130 
1131  // Use specialized code for getting the length of arrays.
1132  if (object->IsJSArray() &&
1133  name->Equals(isolate()->heap()->length_symbol())) {
1134  Handle<JSArray> array = Handle<JSArray>::cast(object);
1135  Handle<Code> code =
1136  isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array);
1137  ASSERT(!code.is_null());
1138  set_target(*code);
1139  TRACE_IC("KeyedLoadIC", name, state, target());
1140  return array->length();
1141  }
1142 
1143  // Use specialized code for getting prototype of functions.
1144  if (object->IsJSFunction() &&
1145  name->Equals(isolate()->heap()->prototype_symbol()) &&
1146  Handle<JSFunction>::cast(object)->should_have_prototype()) {
1147  Handle<JSFunction> function = Handle<JSFunction>::cast(object);
1148  Handle<Code> code =
1150  name, function);
1151  ASSERT(!code.is_null());
1152  set_target(*code);
1153  TRACE_IC("KeyedLoadIC", name, state, target());
1154  return Accessors::FunctionGetPrototype(*object, 0);
1155  }
1156  }
1157 
1158  // Check if the name is trivially convertible to an index and get
1159  // the element or char if so.
1160  uint32_t index = 0;
1161  if (name->AsArrayIndex(&index)) {
1162  // Rewrite to the generic keyed load stub.
1163  if (FLAG_use_ic) set_target(*generic_stub());
1164  return Runtime::GetElementOrCharAt(isolate(), object, index);
1165  }
1166 
1167  // Named lookup.
1168  LookupResult lookup(isolate());
1169  LookupForRead(object, name, &lookup);
1170 
1171  // If we did not find a property, check if we need to throw an exception.
1172  if (!lookup.IsFound() && IsContextual(object)) {
1173  return ReferenceError("not_defined", name);
1174  }
1175 
1176  if (FLAG_use_ic) {
1177  UpdateCaches(&lookup, state, object, name);
1178  }
1179 
1180  PropertyAttributes attr;
1181  if (lookup.IsInterceptor()) {
1182  // Get the property.
1183  Handle<Object> result =
1184  Object::GetProperty(object, object, &lookup, name, &attr);
1185  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1186  // If the property is not present, check if we need to throw an
1187  // exception.
1188  if (attr == ABSENT && IsContextual(object)) {
1189  return ReferenceError("not_defined", name);
1190  }
1191  return *result;
1192  }
1193 
1194  return object->GetProperty(*object, &lookup, *name, &attr);
1195  }
1196 
1197  // Do not use ICs for objects that require access checks (including
1198  // the global object).
1199  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1200 
1201  if (use_ic) {
1202  Handle<Code> stub = generic_stub();
1203  if (!force_generic_stub) {
1204  if (object->IsString() && key->IsNumber()) {
1205  if (state == UNINITIALIZED) {
1206  stub = string_stub();
1207  }
1208  } else if (object->IsJSObject()) {
1209  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1210  if (receiver->elements()->map() ==
1211  isolate()->heap()->non_strict_arguments_elements_map()) {
1212  stub = non_strict_arguments_stub();
1213  } else if (receiver->HasIndexedInterceptor()) {
1214  stub = indexed_interceptor_stub();
1215  } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
1216  stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub);
1217  }
1218  }
1219  } else {
1220  TRACE_GENERIC_IC("KeyedLoadIC", "force generic");
1221  }
1222  if (!stub.is_null()) set_target(*stub);
1223  }
1224 
1225  TRACE_IC("KeyedLoadIC", key, state, target());
1226 
1227  // Get the property.
1228  return Runtime::GetObjectProperty(isolate(), object, key);
1229 }
1230 
1231 
1232 void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
1233  State state,
1234  Handle<Object> object,
1235  Handle<String> name) {
1236  // Bail out if we didn't find a result.
1237  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
1238 
1239  if (!object->IsJSObject()) return;
1240  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1241 
1242  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
1243 
1244  // Compute the code stub for this load.
1246 
1247  if (state == UNINITIALIZED) {
1248  // This is the first time we execute this inline cache.
1249  // Set the target to the pre monomorphic stub to delay
1250  // setting the monomorphic state.
1251  code = pre_monomorphic_stub();
1252  } else {
1253  // Compute a monomorphic stub.
1254  Handle<JSObject> holder(lookup->holder());
1255  switch (lookup->type()) {
1256  case FIELD:
1258  name, receiver, holder, lookup->GetFieldIndex());
1259  break;
1260  case CONSTANT_FUNCTION: {
1261  Handle<JSFunction> constant(lookup->GetConstantFunction());
1263  name, receiver, holder, constant);
1264  break;
1265  }
1266  case CALLBACKS: {
1267  Handle<Object> callback_object(lookup->GetCallbackObject());
1268  if (!callback_object->IsAccessorInfo()) return;
1269  Handle<AccessorInfo> callback =
1270  Handle<AccessorInfo>::cast(callback_object);
1271  if (v8::ToCData<Address>(callback->getter()) == 0) return;
1272  if (!callback->IsCompatibleReceiver(*receiver)) return;
1274  name, receiver, holder, callback);
1275  break;
1276  }
1277  case INTERCEPTOR:
1278  ASSERT(HasInterceptorGetter(lookup->holder()));
1280  name, receiver, holder);
1281  break;
1282  default:
1283  // Always rewrite to the generic case so that we do not
1284  // repeatedly try to rewrite.
1285  code = generic_stub();
1286  break;
1287  }
1288  }
1289 
1290  // Patch the call site depending on the state of the cache. Make
1291  // sure to always rewrite from monomorphic to megamorphic.
1293  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1294  set_target(*code);
1295  } else if (state == MONOMORPHIC) {
1296  set_target(*megamorphic_stub());
1297  }
1298 
1299  TRACE_IC("KeyedLoadIC", name, state, target());
1300 }
1301 
1302 
1303 static bool StoreICableLookup(LookupResult* lookup) {
1304  // Bail out if we didn't find a result.
1305  if (!lookup->IsFound()) return false;
1306 
1307  // Bail out if inline caching is not allowed.
1308  if (!lookup->IsCacheable()) return false;
1309 
1310  // If the property is read-only, we leave the IC in its current state.
1311  if (lookup->IsTransition()) {
1312  return !lookup->GetTransitionDetails().IsReadOnly();
1313  }
1314  return !lookup->IsReadOnly();
1315 }
1316 
1317 
1318 static bool LookupForWrite(Handle<JSObject> receiver,
1319  Handle<String> name,
1320  LookupResult* lookup) {
1321  receiver->LocalLookup(*name, lookup);
1322  if (!lookup->IsFound()) {
1323  receiver->map()->LookupTransition(*receiver, *name, lookup);
1324  }
1325  if (!StoreICableLookup(lookup)) {
1326  // 2nd chance: There can be accessors somewhere in the prototype chain.
1327  receiver->Lookup(*name, lookup);
1328  return lookup->IsPropertyCallbacks() && StoreICableLookup(lookup);
1329  }
1330 
1331  if (lookup->IsInterceptor() &&
1332  receiver->GetNamedInterceptor()->setter()->IsUndefined()) {
1333  receiver->LocalLookupRealNamedProperty(*name, lookup);
1334  return StoreICableLookup(lookup);
1335  }
1336 
1337  return true;
1338 }
1339 
1340 
1341 MaybeObject* StoreIC::Store(State state,
1342  StrictModeFlag strict_mode,
1343  Handle<Object> object,
1344  Handle<String> name,
1345  Handle<Object> value) {
1346  if (!object->IsJSObject()) {
1347  // Handle proxies.
1348  if (object->IsJSProxy()) {
1349  return JSProxy::cast(*object)->
1350  SetProperty(*name, *value, NONE, strict_mode);
1351  }
1352 
1353  // If the object is undefined or null it's illegal to try to set any
1354  // properties on it; throw a TypeError in that case.
1355  if (object->IsUndefined() || object->IsNull()) {
1356  return TypeError("non_object_property_store", object, name);
1357  }
1358 
1359  // The length property of string values is read-only. Throw in strict mode.
1360  if (strict_mode == kStrictMode && object->IsString() &&
1361  name->Equals(isolate()->heap()->length_symbol())) {
1362  return TypeError("strict_read_only_property", object, name);
1363  }
1364  // Ignore other stores where the receiver is not a JSObject.
1365  // TODO(1475): Must check prototype chains of object wrappers.
1366  return *value;
1367  }
1368 
1369  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1370 
1371  // Check if the given name is an array index.
1372  uint32_t index;
1373  if (name->AsArrayIndex(&index)) {
1374  Handle<Object> result =
1375  JSObject::SetElement(receiver, index, value, NONE, strict_mode);
1376  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1377  return *value;
1378  }
1379 
1380  // Use specialized code for setting the length of arrays with fast
1381  // properties. Slow properties might indicate redefinition of the
1382  // length property.
1383  if (receiver->IsJSArray() &&
1384  name->Equals(isolate()->heap()->length_symbol()) &&
1385  Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
1386  receiver->HasFastProperties()) {
1387 #ifdef DEBUG
1388  if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
1389 #endif
1390  Handle<Code> stub = (strict_mode == kStrictMode)
1391  ? isolate()->builtins()->StoreIC_ArrayLength_Strict()
1392  : isolate()->builtins()->StoreIC_ArrayLength();
1393  set_target(*stub);
1394  return receiver->SetProperty(*name, *value, NONE, strict_mode);
1395  }
1396 
1397  // Lookup the property locally in the receiver.
1398  if (!receiver->IsJSGlobalProxy()) {
1399  LookupResult lookup(isolate());
1400 
1401  if (LookupForWrite(receiver, name, &lookup)) {
1402  if (FLAG_use_ic) { // Generate a stub for this store.
1403  UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1404  }
1405  } else {
1406  // Strict mode doesn't allow setting non-existent global property
1407  // or an assignment to a read only property.
1408  if (strict_mode == kStrictMode) {
1409  if (lookup.IsProperty() && lookup.IsReadOnly()) {
1410  return TypeError("strict_read_only_property", object, name);
1411  } else if (IsContextual(object)) {
1412  return ReferenceError("not_defined", name);
1413  }
1414  }
1415  }
1416  }
1417 
1418  if (receiver->IsJSGlobalProxy()) {
1419  // TODO(ulan): find out why we patch this site even with --no-use-ic
1420  // Generate a generic stub that goes to the runtime when we see a global
1421  // proxy as receiver.
1422  Handle<Code> stub = (strict_mode == kStrictMode)
1423  ? global_proxy_stub_strict()
1424  : global_proxy_stub();
1425  if (target() != *stub) {
1426  set_target(*stub);
1427  TRACE_IC("StoreIC", name, state, target());
1428  }
1429  }
1430 
1431  // Set the property.
1432  return receiver->SetProperty(*name,
1433  *value,
1434  NONE,
1435  strict_mode,
1437 }
1438 
1439 
1440 void StoreIC::UpdateCaches(LookupResult* lookup,
1441  State state,
1442  StrictModeFlag strict_mode,
1443  Handle<JSObject> receiver,
1444  Handle<String> name,
1445  Handle<Object> value) {
1446  ASSERT(!receiver->IsJSGlobalProxy());
1447  ASSERT(StoreICableLookup(lookup));
1448  ASSERT(lookup->IsFound());
1449 
1450  // These are not cacheable, so we never see such LookupResults here.
1451  ASSERT(!lookup->IsHandler());
1452 
1453  // If the property has a non-field type allowing map transitions
1454  // where there is extra room in the object, we leave the IC in its
1455  // current state.
1456  PropertyType type = lookup->type();
1457 
1458  // Compute the code stub for this store; used for rewriting to
1459  // monomorphic state and making sure that the code stub is in the
1460  // stub cache.
1461  Handle<JSObject> holder(lookup->holder());
1463  switch (type) {
1464  case FIELD:
1465  code = isolate()->stub_cache()->ComputeStoreField(name,
1466  receiver,
1467  lookup->GetFieldIndex(),
1469  strict_mode);
1470  break;
1471  case NORMAL:
1472  if (receiver->IsGlobalObject()) {
1473  // The stub generated for the global object picks the value directly
1474  // from the property cell. So the property must be directly on the
1475  // global object.
1477  Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
1478  code = isolate()->stub_cache()->ComputeStoreGlobal(
1479  name, global, cell, strict_mode);
1480  } else {
1481  if (!holder.is_identical_to(receiver)) return;
1482  code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
1483  }
1484  break;
1485  case CALLBACKS: {
1486  Handle<Object> callback(lookup->GetCallbackObject());
1487  if (callback->IsAccessorInfo()) {
1488  Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
1489  if (v8::ToCData<Address>(info->setter()) == 0) return;
1490  if (!holder->HasFastProperties()) return;
1491  if (!info->IsCompatibleReceiver(*receiver)) return;
1493  name, receiver, holder, info, strict_mode);
1494  } else if (callback->IsAccessorPair()) {
1495  Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter());
1496  if (!setter->IsJSFunction()) return;
1497  if (holder->IsGlobalObject()) return;
1498  if (!holder->HasFastProperties()) return;
1500  name, receiver, holder, Handle<JSFunction>::cast(setter),
1501  strict_mode);
1502  } else {
1503  ASSERT(callback->IsForeign());
1504  // No IC support for old-style native accessors.
1505  return;
1506  }
1507  break;
1508  }
1509  case INTERCEPTOR:
1510  ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
1512  name, receiver, strict_mode);
1513  break;
1514  case CONSTANT_FUNCTION:
1515  return;
1516  case TRANSITION: {
1517  Handle<Map> transition(lookup->GetTransitionTarget());
1518  int descriptor = transition->LastAdded();
1519 
1520  DescriptorArray* target_descriptors = transition->instance_descriptors();
1521  PropertyDetails details = target_descriptors->GetDetails(descriptor);
1522 
1523  if (details.type() != FIELD || details.attributes() != NONE) return;
1524 
1525  int field_index = target_descriptors->GetFieldIndex(descriptor);
1526  code = isolate()->stub_cache()->ComputeStoreField(
1527  name, receiver, field_index, transition, strict_mode);
1528 
1529  break;
1530  }
1531  case NONEXISTENT:
1532  case HANDLER:
1533  UNREACHABLE();
1534  return;
1535  }
1536 
1537  // Patch the call site depending on the state of the cache.
1538  if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1539  set_target(*code);
1540  } else if (state == MONOMORPHIC) {
1541  // Only move to megamorphic if the target changes.
1542  if (target() != *code) {
1543  set_target((strict_mode == kStrictMode)
1544  ? megamorphic_stub_strict()
1545  : megamorphic_stub());
1546  }
1547  } else if (state == MEGAMORPHIC) {
1548  // Update the stub cache.
1549  isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1550  }
1551 
1552  TRACE_IC("StoreIC", name, state, target());
1553 }
1554 
1555 
1556 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
1557  Handle<Map> new_receiver_map) {
1558  ASSERT(!new_receiver_map.is_null());
1559  for (int current = 0; current < receiver_maps->length(); ++current) {
1560  if (!receiver_maps->at(current).is_null() &&
1561  receiver_maps->at(current).is_identical_to(new_receiver_map)) {
1562  return false;
1563  }
1564  }
1565  receiver_maps->Add(new_receiver_map);
1566  return true;
1567 }
1568 
1569 
1570 void KeyedIC::GetReceiverMapsForStub(Handle<Code> stub,
1571  MapHandleList* result) {
1572  ASSERT(stub->is_inline_cache_stub());
1573  if (!string_stub().is_null() && stub.is_identical_to(string_stub())) {
1574  return result->Add(isolate()->factory()->string_map());
1575  } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
1576  if (stub->ic_state() == MONOMORPHIC) {
1577  result->Add(Handle<Map>(stub->FindFirstMap()));
1578  } else {
1579  ASSERT(stub->ic_state() == MEGAMORPHIC);
1580  AssertNoAllocation no_allocation;
1581  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1582  for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
1583  RelocInfo* info = it.rinfo();
1584  Handle<Object> object(info->target_object());
1585  ASSERT(object->IsMap());
1586  AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
1587  }
1588  }
1589  }
1590 }
1591 
1592 
1594  StubKind stub_kind,
1595  StrictModeFlag strict_mode,
1596  Handle<Code> generic_stub) {
1597  State ic_state = target()->ic_state();
1598  KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind)
1601 
1602  // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1603  // via megamorphic stubs, since they don't have a map in their relocation info
1604  // and so the stubs can't be harvested for the object needed for a map check.
1605  if (target()->type() != Code::NORMAL) {
1606  TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type");
1607  return generic_stub;
1608  }
1609 
1610  bool monomorphic = false;
1611  bool is_transition_stub = IsTransitionStubKind(stub_kind);
1612  Handle<Map> receiver_map(receiver->map());
1613  Handle<Map> monomorphic_map = receiver_map;
1614  MapHandleList target_receiver_maps;
1615  if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1616  // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1617  // yet will do so and stay there.
1618  monomorphic = true;
1619  } else {
1620  GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
1621  if (ic_state == MONOMORPHIC && (is_transition_stub || stub_kind == LOAD)) {
1622  // The first time a receiver is seen that is a transitioned version of the
1623  // previous monomorphic receiver type, assume the new ElementsKind is the
1624  // monomorphic type. This benefits global arrays that only transition
1625  // once, and all call sites accessing them are faster if they remain
1626  // monomorphic. If this optimistic assumption is not true, the IC will
1627  // miss again and it will become polymorphic and support both the
1628  // untransitioned and transitioned maps.
1630  target_receiver_maps.at(0)->elements_kind(),
1631  receiver->GetElementsKind());
1632  }
1633  }
1634 
1635  if (monomorphic) {
1636  if (is_transition_stub) {
1637  monomorphic_map = ComputeTransitionedMap(receiver, stub_kind);
1638  ASSERT(*monomorphic_map != *receiver_map);
1639  stub_kind = GetNoTransitionStubKind(stub_kind);
1640  }
1641  return ComputeMonomorphicStub(
1642  monomorphic_map, stub_kind, strict_mode, generic_stub);
1643  }
1644  ASSERT(target() != *generic_stub);
1645 
1646  // Determine the list of receiver maps that this call site has seen,
1647  // adding the map that was just encountered.
1648  bool map_added =
1649  AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1650  if (IsTransitionStubKind(stub_kind)) {
1651  Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind);
1652  map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map);
1653  }
1654  if (!map_added) {
1655  // If the miss wasn't due to an unseen map, a polymorphic stub
1656  // won't help, use the generic stub.
1657  TRACE_GENERIC_IC("KeyedIC", "same map added twice");
1658  return generic_stub;
1659  }
1660 
1661  // If the maximum number of receiver maps has been exceeded, use the generic
1662  // version of the IC.
1663  if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1664  TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded");
1665  return generic_stub;
1666  }
1667 
1668  if ((Code::GetKeyedAccessGrowMode(target()->extra_ic_state()) ==
1670  grow_mode = ALLOW_JSARRAY_GROWTH;
1671  }
1672 
1674  isolate()->factory()->polymorphic_code_cache();
1675  Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode,
1676  strict_mode);
1678  Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags);
1679  if (probe->IsCode()) return Handle<Code>::cast(probe);
1680 
1681  Handle<Code> stub =
1682  ComputePolymorphicStub(&target_receiver_maps, strict_mode, grow_mode);
1683  PolymorphicCodeCache::Update(cache, &target_receiver_maps, flags, stub);
1684  return stub;
1685 }
1686 
1687 
1689  Handle<Map> receiver_map,
1690  StrictModeFlag strict_mode,
1691  KeyedAccessGrowMode grow_mode) {
1692  if ((receiver_map->instance_type() & kNotStringTag) == 0) {
1693  ASSERT(!string_stub().is_null());
1694  return string_stub();
1695  } else {
1696  ASSERT(receiver_map->has_dictionary_elements() ||
1697  receiver_map->has_fast_smi_or_object_elements() ||
1698  receiver_map->has_fast_double_elements() ||
1699  receiver_map->has_external_array_elements());
1700  bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1701  return GetElementStubWithoutMapCheck(is_js_array,
1702  receiver_map->elements_kind(),
1703  grow_mode);
1704  }
1705 }
1706 
1707 
1708 Handle<Code> KeyedIC::ComputeMonomorphicStub(Handle<Map> receiver_map,
1709  StubKind stub_kind,
1710  StrictModeFlag strict_mode,
1711  Handle<Code> generic_stub) {
1712  ElementsKind elements_kind = receiver_map->elements_kind();
1713  if (IsFastElementsKind(elements_kind) ||
1714  IsExternalArrayElementsKind(elements_kind) ||
1715  IsDictionaryElementsKind(elements_kind)) {
1717  receiver_map, stub_kind, strict_mode);
1718  } else {
1719  return generic_stub;
1720  }
1721 }
1722 
1723 
1724 Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver,
1725  StubKind stub_kind) {
1726  switch (stub_kind) {
1739  return JSObject::GetElementsTransitionMap(receiver,
1743  return JSObject::GetElementsTransitionMap(receiver,
1745  case KeyedIC::LOAD:
1748  UNREACHABLE();
1749  break;
1750  }
1751  return Handle<Map>::null();
1752 }
1753 
1754 
1756  bool is_js_array,
1757  ElementsKind elements_kind,
1758  KeyedAccessGrowMode grow_mode) {
1759  return KeyedStoreElementStub(is_js_array, elements_kind, grow_mode).GetCode();
1760 }
1761 
1762 
1764  MapHandleList* receiver_maps,
1765  StrictModeFlag strict_mode,
1766  KeyedAccessGrowMode grow_mode) {
1767  // Collect MONOMORPHIC stubs for all target_receiver_maps.
1768  CodeHandleList handler_ics(receiver_maps->length());
1769  MapHandleList transitioned_maps(receiver_maps->length());
1770  for (int i = 0; i < receiver_maps->length(); ++i) {
1771  Handle<Map> receiver_map(receiver_maps->at(i));
1772  Handle<Code> cached_stub;
1773  Handle<Map> transitioned_map =
1774  receiver_map->FindTransitionedMap(receiver_maps);
1775  if (!transitioned_map.is_null()) {
1776  cached_stub = ElementsTransitionAndStoreStub(
1777  receiver_map->elements_kind(), // original elements_kind
1778  transitioned_map->elements_kind(),
1779  receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array
1780  strict_mode, grow_mode).GetCode();
1781  } else {
1782  cached_stub = ComputeMonomorphicStubWithoutMapCheck(receiver_map,
1783  strict_mode,
1784  grow_mode);
1785  }
1786  ASSERT(!cached_stub.is_null());
1787  handler_ics.Add(cached_stub);
1788  transitioned_maps.Add(transitioned_map);
1789  }
1790  KeyedStoreStubCompiler compiler(isolate(), strict_mode, grow_mode);
1791  Handle<Code> code = compiler.CompileStorePolymorphic(
1792  receiver_maps, &handler_ics, &transitioned_maps);
1793  isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1794  PROFILE(isolate(),
1795  CodeCreateEvent(Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, *code, 0));
1796  return code;
1797 }
1798 
1799 
1800 KeyedIC::StubKind KeyedStoreIC::GetStubKind(Handle<JSObject> receiver,
1801  Handle<Object> key,
1802  Handle<Object> value) {
1803  ASSERT(key->IsSmi());
1804  int index = Smi::cast(*key)->value();
1805  bool allow_growth = receiver->IsJSArray() &&
1806  JSArray::cast(*receiver)->length()->IsSmi() &&
1807  index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
1808 
1809  if (allow_growth) {
1810  // Handle growing array in stub if necessary.
1811  if (receiver->HasFastSmiElements()) {
1812  if (value->IsHeapNumber()) {
1813  if (receiver->HasFastHoleyElements()) {
1815  } else {
1817  }
1818  }
1819  if (value->IsHeapObject()) {
1820  if (receiver->HasFastHoleyElements()) {
1822  } else {
1824  }
1825  }
1826  } else if (receiver->HasFastDoubleElements()) {
1827  if (!value->IsSmi() && !value->IsHeapNumber()) {
1828  if (receiver->HasFastHoleyElements()) {
1830  } else {
1832  }
1833  }
1834  }
1836  } else {
1837  // Handle only in-bounds elements accesses.
1838  if (receiver->HasFastSmiElements()) {
1839  if (value->IsHeapNumber()) {
1840  if (receiver->HasFastHoleyElements()) {
1842  } else {
1844  }
1845  } else if (value->IsHeapObject()) {
1846  if (receiver->HasFastHoleyElements()) {
1848  } else {
1850  }
1851  }
1852  } else if (receiver->HasFastDoubleElements()) {
1853  if (!value->IsSmi() && !value->IsHeapNumber()) {
1854  if (receiver->HasFastHoleyElements()) {
1856  } else {
1858  }
1859  }
1860  }
1861  return STORE_NO_TRANSITION;
1862  }
1863 }
1864 
1865 
1866 MaybeObject* KeyedStoreIC::Store(State state,
1867  StrictModeFlag strict_mode,
1868  Handle<Object> object,
1869  Handle<Object> key,
1870  Handle<Object> value,
1871  bool force_generic) {
1872  // Check for values that can be converted into a symbol directly or
1873  // is representable as a smi.
1874  key = TryConvertKey(key, isolate());
1875 
1876  if (key->IsSymbol()) {
1878 
1879  // Handle proxies.
1880  if (object->IsJSProxy()) {
1881  return JSProxy::cast(*object)->SetProperty(
1882  *name, *value, NONE, strict_mode);
1883  }
1884 
1885  // If the object is undefined or null it's illegal to try to set any
1886  // properties on it; throw a TypeError in that case.
1887  if (object->IsUndefined() || object->IsNull()) {
1888  return TypeError("non_object_property_store", object, name);
1889  }
1890 
1891  // Ignore stores where the receiver is not a JSObject.
1892  if (!object->IsJSObject()) return *value;
1893  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1894 
1895  // Check if the given name is an array index.
1896  uint32_t index;
1897  if (name->AsArrayIndex(&index)) {
1898  Handle<Object> result =
1899  JSObject::SetElement(receiver, index, value, NONE, strict_mode);
1900  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1901  return *value;
1902  }
1903 
1904  // Update inline cache and stub cache.
1905  if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
1906  LookupResult lookup(isolate());
1907  if (LookupForWrite(receiver, name, &lookup)) {
1908  UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1909  }
1910  }
1911 
1912  // Set the property.
1913  return receiver->SetProperty(*name, *value, NONE, strict_mode);
1914  }
1915 
1916  // Do not use ICs for objects that require access checks (including
1917  // the global object).
1918  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1919  ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1920 
1921  if (use_ic) {
1922  Handle<Code> stub = (strict_mode == kStrictMode)
1923  ? generic_stub_strict()
1924  : generic_stub();
1925  if (object->IsJSObject()) {
1926  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1927  if (receiver->elements()->map() ==
1928  isolate()->heap()->non_strict_arguments_elements_map()) {
1929  stub = non_strict_arguments_stub();
1930  } else if (!force_generic) {
1931  if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
1932  StubKind stub_kind = GetStubKind(receiver, key, value);
1933  stub = ComputeStub(receiver, stub_kind, strict_mode, stub);
1934  }
1935  } else {
1936  TRACE_GENERIC_IC("KeyedStoreIC", "force generic");
1937  }
1938  }
1939  if (!stub.is_null()) set_target(*stub);
1940  }
1941 
1942  TRACE_IC("KeyedStoreIC", key, state, target());
1943 
1944  // Set the property.
1946  isolate(), object , key, value, NONE, strict_mode);
1947 }
1948 
1949 
1950 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1951  State state,
1952  StrictModeFlag strict_mode,
1953  Handle<JSObject> receiver,
1954  Handle<String> name,
1955  Handle<Object> value) {
1956  ASSERT(!receiver->IsJSGlobalProxy());
1957  ASSERT(StoreICableLookup(lookup));
1958  ASSERT(lookup->IsFound());
1959 
1960  // These are not cacheable, so we never see such LookupResults here.
1961  ASSERT(!lookup->IsHandler());
1962 
1963  // If the property has a non-field type allowing map transitions
1964  // where there is extra room in the object, we leave the IC in its
1965  // current state.
1966  PropertyType type = lookup->type();
1967 
1968  // Compute the code stub for this store; used for rewriting to
1969  // monomorphic state and making sure that the code stub is in the
1970  // stub cache.
1972 
1973  switch (type) {
1974  case FIELD:
1976  name, receiver, lookup->GetFieldIndex(),
1977  Handle<Map>::null(), strict_mode);
1978  break;
1979  case TRANSITION: {
1980  Handle<Map> transition(lookup->GetTransitionTarget());
1981  int descriptor = transition->LastAdded();
1982 
1983  DescriptorArray* target_descriptors = transition->instance_descriptors();
1984  PropertyDetails details = target_descriptors->GetDetails(descriptor);
1985 
1986  if (details.type() == FIELD && details.attributes() == NONE) {
1987  int field_index = target_descriptors->GetFieldIndex(descriptor);
1989  name, receiver, field_index, transition, strict_mode);
1990  break;
1991  }
1992  // fall through.
1993  }
1994  case NORMAL:
1995  case CONSTANT_FUNCTION:
1996  case CALLBACKS:
1997  case INTERCEPTOR:
1998  // Always rewrite to the generic case so that we do not
1999  // repeatedly try to rewrite.
2000  code = (strict_mode == kStrictMode)
2001  ? generic_stub_strict()
2002  : generic_stub();
2003  break;
2004  case HANDLER:
2005  case NONEXISTENT:
2006  UNREACHABLE();
2007  return;
2008  }
2009 
2010  ASSERT(!code.is_null());
2011 
2012  // Patch the call site depending on the state of the cache. Make
2013  // sure to always rewrite from monomorphic to megamorphic.
2015  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
2016  set_target(*code);
2017  } else if (state == MONOMORPHIC) {
2018  set_target((strict_mode == kStrictMode)
2019  ? *megamorphic_stub_strict()
2020  : *megamorphic_stub());
2021  }
2022 
2023  TRACE_IC("KeyedStoreIC", name, state, target());
2024 }
2025 
2026 
2027 #undef TRACE_IC
2028 
2029 
2030 // ----------------------------------------------------------------------------
2031 // Static IC stub generators.
2032 //
2033 
2034 // Used from ic-<arch>.cc.
2035 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
2036  HandleScope scope(isolate);
2037  ASSERT(args.length() == 2);
2038  CallIC ic(isolate);
2039  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2040  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2041  MaybeObject* maybe_result = ic.LoadFunction(state,
2042  extra_ic_state,
2043  args.at<Object>(0),
2044  args.at<String>(1));
2045  // Result could be a function or a failure.
2046  JSFunction* raw_function = NULL;
2047  if (!maybe_result->To(&raw_function)) return maybe_result;
2048 
2049  // The first time the inline cache is updated may be the first time the
2050  // function it references gets called. If the function is lazily compiled
2051  // then the first call will trigger a compilation. We check for this case
2052  // and we do the compilation immediately, instead of waiting for the stub
2053  // currently attached to the JSFunction object to trigger compilation.
2054  if (raw_function->is_compiled()) return raw_function;
2055 
2056  Handle<JSFunction> function(raw_function);
2058  return *function;
2059 }
2060 
2061 
2062 // Used from ic-<arch>.cc.
2063 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
2064  HandleScope scope(isolate);
2065  ASSERT(args.length() == 2);
2066  KeyedCallIC ic(isolate);
2067  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2068  MaybeObject* maybe_result =
2069  ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
2070  // Result could be a function or a failure.
2071  JSFunction* raw_function = NULL;
2072  if (!maybe_result->To(&raw_function)) return maybe_result;
2073 
2074  if (raw_function->is_compiled()) return raw_function;
2075 
2076  Handle<JSFunction> function(raw_function);
2078  return *function;
2079 }
2080 
2081 
2082 // Used from ic-<arch>.cc.
2083 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
2084  HandleScope scope(isolate);
2085  ASSERT(args.length() == 2);
2086  LoadIC ic(isolate);
2087  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2088  return ic.Load(state, args.at<Object>(0), args.at<String>(1));
2089 }
2090 
2091 
2092 // Used from ic-<arch>.cc
2093 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
2094  HandleScope scope(isolate);
2095  ASSERT(args.length() == 2);
2096  KeyedLoadIC ic(isolate);
2097  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2098  return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false);
2099 }
2100 
2101 
2102 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2103  HandleScope scope(isolate);
2104  ASSERT(args.length() == 2);
2105  KeyedLoadIC ic(isolate);
2106  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2107  return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true);
2108 }
2109 
2110 
2111 // Used from ic-<arch>.cc.
2112 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
2113  HandleScope scope;
2114  ASSERT(args.length() == 3);
2115  StoreIC ic(isolate);
2116  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2117  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2118  return ic.Store(state,
2119  Code::GetStrictMode(extra_ic_state),
2120  args.at<Object>(0),
2121  args.at<String>(1),
2122  args.at<Object>(2));
2123 }
2124 
2125 
2126 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
2127  NoHandleAllocation nha;
2128 
2129  ASSERT(args.length() == 2);
2130  JSArray* receiver = JSArray::cast(args[0]);
2131  Object* len = args[1];
2132 
2133  // The generated code should filter out non-Smis before we get here.
2134  ASSERT(len->IsSmi());
2135 
2136 #ifdef DEBUG
2137  // The length property has to be a writable callback property.
2138  LookupResult debug_lookup(isolate);
2139  receiver->LocalLookup(isolate->heap()->length_symbol(), &debug_lookup);
2140  ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly());
2141 #endif
2142 
2143  Object* result;
2144  { MaybeObject* maybe_result = receiver->SetElementsLength(len);
2145  if (!maybe_result->ToObject(&result)) return maybe_result;
2146  }
2147  return len;
2148 }
2149 
2150 
2151 // Extend storage is called in a store inline cache when
2152 // it is necessary to extend the properties array of a
2153 // JSObject.
2154 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
2155  NoHandleAllocation na;
2156  ASSERT(args.length() == 3);
2157 
2158  // Convert the parameters
2159  JSObject* object = JSObject::cast(args[0]);
2160  Map* transition = Map::cast(args[1]);
2161  Object* value = args[2];
2162 
2163  // Check the object has run out out property space.
2164  ASSERT(object->HasFastProperties());
2165  ASSERT(object->map()->unused_property_fields() == 0);
2166 
2167  // Expand the properties array.
2168  FixedArray* old_storage = object->properties();
2169  int new_unused = transition->unused_property_fields();
2170  int new_size = old_storage->length() + new_unused + 1;
2171  Object* result;
2172  { MaybeObject* maybe_result = old_storage->CopySize(new_size);
2173  if (!maybe_result->ToObject(&result)) return maybe_result;
2174  }
2175  FixedArray* new_storage = FixedArray::cast(result);
2176  new_storage->set(old_storage->length(), value);
2177 
2178  // Set the new property value and do the map transition.
2179  object->set_properties(new_storage);
2180  object->set_map(transition);
2181 
2182  // Return the stored value.
2183  return value;
2184 }
2185 
2186 
2187 // Used from ic-<arch>.cc.
2188 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
2189  HandleScope scope(isolate);
2190  ASSERT(args.length() == 3);
2191  KeyedStoreIC ic(isolate);
2192  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2193  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2194  return ic.Store(state,
2195  Code::GetStrictMode(extra_ic_state),
2196  args.at<Object>(0),
2197  args.at<Object>(1),
2198  args.at<Object>(2),
2199  false);
2200 }
2201 
2202 
2203 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
2204  NoHandleAllocation na;
2205  ASSERT(args.length() == 3);
2206  KeyedStoreIC ic(isolate);
2207  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2208  Handle<Object> object = args.at<Object>(0);
2209  Handle<Object> key = args.at<Object>(1);
2210  Handle<Object> value = args.at<Object>(2);
2211  StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state);
2212  return Runtime::SetObjectProperty(isolate,
2213  object,
2214  key,
2215  value,
2216  NONE,
2217  strict_mode);
2218 }
2219 
2220 
2221 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2222  HandleScope scope(isolate);
2223  ASSERT(args.length() == 3);
2224  KeyedStoreIC ic(isolate);
2225  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2226  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2227  return ic.Store(state,
2228  Code::GetStrictMode(extra_ic_state),
2229  args.at<Object>(0),
2230  args.at<Object>(1),
2231  args.at<Object>(2),
2232  true);
2233 }
2234 
2235 
2236 void UnaryOpIC::patch(Code* code) {
2237  set_target(code);
2238 }
2239 
2240 
2241 const char* UnaryOpIC::GetName(TypeInfo type_info) {
2242  switch (type_info) {
2243  case UNINITIALIZED: return "Uninitialized";
2244  case SMI: return "Smi";
2245  case HEAP_NUMBER: return "HeapNumbers";
2246  case GENERIC: return "Generic";
2247  default: return "Invalid";
2248  }
2249 }
2250 
2251 
2253  switch (type_info) {
2254  case UNINITIALIZED:
2256  case SMI:
2257  case HEAP_NUMBER:
2258  return MONOMORPHIC;
2259  case GENERIC:
2260  return MEGAMORPHIC;
2261  }
2262  UNREACHABLE();
2264 }
2265 
2267  ::v8::internal::TypeInfo operand_type =
2269  if (operand_type.IsSmi()) {
2270  return SMI;
2271  } else if (operand_type.IsNumber()) {
2272  return HEAP_NUMBER;
2273  } else {
2274  return GENERIC;
2275  }
2276 }
2277 
2278 
2280  UnaryOpIC::TypeInfo current_type,
2281  UnaryOpIC::TypeInfo previous_type) {
2282  switch (previous_type) {
2284  return current_type;
2285  case UnaryOpIC::SMI:
2286  return (current_type == UnaryOpIC::GENERIC)
2290  return UnaryOpIC::GENERIC;
2291  case UnaryOpIC::GENERIC:
2292  // We should never do patching if we are in GENERIC state.
2293  UNREACHABLE();
2294  return UnaryOpIC::GENERIC;
2295  }
2296  UNREACHABLE();
2297  return UnaryOpIC::GENERIC;
2298 }
2299 
2300 
2302  set_target(code);
2303 }
2304 
2305 
2306 const char* BinaryOpIC::GetName(TypeInfo type_info) {
2307  switch (type_info) {
2308  case UNINITIALIZED: return "Uninitialized";
2309  case SMI: return "SMI";
2310  case INT32: return "Int32s";
2311  case HEAP_NUMBER: return "HeapNumbers";
2312  case ODDBALL: return "Oddball";
2313  case BOTH_STRING: return "BothStrings";
2314  case STRING: return "Strings";
2315  case GENERIC: return "Generic";
2316  default: return "Invalid";
2317  }
2318 }
2319 
2320 
2322  switch (type_info) {
2323  case UNINITIALIZED:
2325  case SMI:
2326  case INT32:
2327  case HEAP_NUMBER:
2328  case ODDBALL:
2329  case BOTH_STRING:
2330  case STRING:
2331  return MONOMORPHIC;
2332  case GENERIC:
2333  return MEGAMORPHIC;
2334  }
2335  UNREACHABLE();
2337 }
2338 
2339 
2342  if (x == UNINITIALIZED) return y;
2343  if (y == UNINITIALIZED) return x;
2344  if (x == y) return x;
2345  if (x == BOTH_STRING && y == STRING) return STRING;
2346  if (x == STRING && y == BOTH_STRING) return STRING;
2347  if (x == STRING || x == BOTH_STRING || y == STRING || y == BOTH_STRING) {
2348  return GENERIC;
2349  }
2350  if (x > y) return x;
2351  return y;
2352 }
2353 
2354 
2356  Handle<Object> right) {
2357  ::v8::internal::TypeInfo left_type =
2359  ::v8::internal::TypeInfo right_type =
2361 
2362  if (left_type.IsSmi() && right_type.IsSmi()) {
2363  return SMI;
2364  }
2365 
2366  if (left_type.IsInteger32() && right_type.IsInteger32()) {
2367  // Platforms with 32-bit Smis have no distinct INT32 type.
2368  if (kSmiValueSize == 32) return SMI;
2369  return INT32;
2370  }
2371 
2372  if (left_type.IsNumber() && right_type.IsNumber()) {
2373  return HEAP_NUMBER;
2374  }
2375 
2376  // Patching for fast string ADD makes sense even if only one of the
2377  // arguments is a string.
2378  if (left_type.IsString()) {
2379  return right_type.IsString() ? BOTH_STRING : STRING;
2380  } else if (right_type.IsString()) {
2381  return STRING;
2382  }
2383 
2384  // Check for oddball objects.
2385  if (left->IsUndefined() && right->IsNumber()) return ODDBALL;
2386  if (left->IsNumber() && right->IsUndefined()) return ODDBALL;
2387 
2388  return GENERIC;
2389 }
2390 
2391 
2392 RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) {
2393  ASSERT(args.length() == 4);
2394 
2395  HandleScope scope(isolate);
2396  Handle<Object> operand = args.at<Object>(0);
2397  Token::Value op = static_cast<Token::Value>(args.smi_at(1));
2398  UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2));
2399  UnaryOpIC::TypeInfo previous_type =
2400  static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3));
2401 
2403  type = UnaryOpIC::ComputeNewType(type, previous_type);
2404 
2405  UnaryOpStub stub(op, mode, type);
2406  Handle<Code> code = stub.GetCode();
2407  if (!code.is_null()) {
2408  if (FLAG_trace_ic) {
2409  PrintF("[UnaryOpIC (%s->%s)#%s]\n",
2410  UnaryOpIC::GetName(previous_type),
2411  UnaryOpIC::GetName(type),
2412  Token::Name(op));
2413  }
2414  UnaryOpIC ic(isolate);
2415  ic.patch(*code);
2416  }
2417 
2419  isolate->thread_local_top()->context_->builtins(), isolate);
2420  Object* builtin = NULL; // Initialization calms down the compiler.
2421  switch (op) {
2422  case Token::SUB:
2423  builtin = builtins->javascript_builtin(Builtins::UNARY_MINUS);
2424  break;
2425  case Token::BIT_NOT:
2426  builtin = builtins->javascript_builtin(Builtins::BIT_NOT);
2427  break;
2428  default:
2429  UNREACHABLE();
2430  }
2431 
2432  Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
2433 
2434  bool caught_exception;
2435  Handle<Object> result = Execution::Call(builtin_function, operand, 0, NULL,
2436  &caught_exception);
2437  if (caught_exception) {
2438  return Failure::Exception();
2439  }
2440  return *result;
2441 }
2442 
2443 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
2444  ASSERT(args.length() == 5);
2445 
2446  HandleScope scope(isolate);
2447  Handle<Object> left = args.at<Object>(0);
2448  Handle<Object> right = args.at<Object>(1);
2449  int key = args.smi_at(2);
2450  Token::Value op = static_cast<Token::Value>(args.smi_at(3));
2451  BinaryOpIC::TypeInfo previous_type =
2452  static_cast<BinaryOpIC::TypeInfo>(args.smi_at(4));
2453 
2454  BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(left, right);
2455  type = BinaryOpIC::JoinTypes(type, previous_type);
2457  if ((type == BinaryOpIC::STRING || type == BinaryOpIC::BOTH_STRING) &&
2458  op != Token::ADD) {
2459  type = BinaryOpIC::GENERIC;
2460  }
2461  if (type == BinaryOpIC::SMI && previous_type == BinaryOpIC::SMI) {
2462  if (op == Token::DIV ||
2463  op == Token::MUL ||
2464  op == Token::SHR ||
2465  kSmiValueSize == 32) {
2466  // Arithmetic on two Smi inputs has yielded a heap number.
2467  // That is the only way to get here from the Smi stub.
2468  // With 32-bit Smis, all overflows give heap numbers, but with
2469  // 31-bit Smis, most operations overflow to int32 results.
2470  result_type = BinaryOpIC::HEAP_NUMBER;
2471  } else {
2472  // Other operations on SMIs that overflow yield int32s.
2473  result_type = BinaryOpIC::INT32;
2474  }
2475  }
2476  if (type == BinaryOpIC::INT32 && previous_type == BinaryOpIC::INT32) {
2477  // We must be here because an operation on two INT32 types overflowed.
2478  result_type = BinaryOpIC::HEAP_NUMBER;
2479  }
2480 
2481  BinaryOpStub stub(key, type, result_type);
2482  Handle<Code> code = stub.GetCode();
2483  if (!code.is_null()) {
2484  if (FLAG_trace_ic) {
2485  PrintF("[BinaryOpIC (%s->(%s->%s))#%s]\n",
2486  BinaryOpIC::GetName(previous_type),
2487  BinaryOpIC::GetName(type),
2488  BinaryOpIC::GetName(result_type),
2489  Token::Name(op));
2490  }
2491  BinaryOpIC ic(isolate);
2492  ic.patch(*code);
2493 
2494  // Activate inlined smi code.
2495  if (previous_type == BinaryOpIC::UNINITIALIZED) {
2497  }
2498  }
2499 
2501  isolate->thread_local_top()->context_->builtins(), isolate);
2502  Object* builtin = NULL; // Initialization calms down the compiler.
2503  switch (op) {
2504  case Token::ADD:
2505  builtin = builtins->javascript_builtin(Builtins::ADD);
2506  break;
2507  case Token::SUB:
2508  builtin = builtins->javascript_builtin(Builtins::SUB);
2509  break;
2510  case Token::MUL:
2511  builtin = builtins->javascript_builtin(Builtins::MUL);
2512  break;
2513  case Token::DIV:
2514  builtin = builtins->javascript_builtin(Builtins::DIV);
2515  break;
2516  case Token::MOD:
2517  builtin = builtins->javascript_builtin(Builtins::MOD);
2518  break;
2519  case Token::BIT_AND:
2520  builtin = builtins->javascript_builtin(Builtins::BIT_AND);
2521  break;
2522  case Token::BIT_OR:
2523  builtin = builtins->javascript_builtin(Builtins::BIT_OR);
2524  break;
2525  case Token::BIT_XOR:
2526  builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
2527  break;
2528  case Token::SHR:
2529  builtin = builtins->javascript_builtin(Builtins::SHR);
2530  break;
2531  case Token::SAR:
2532  builtin = builtins->javascript_builtin(Builtins::SAR);
2533  break;
2534  case Token::SHL:
2535  builtin = builtins->javascript_builtin(Builtins::SHL);
2536  break;
2537  default:
2538  UNREACHABLE();
2539  }
2540 
2541  Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
2542 
2543  bool caught_exception;
2544  Handle<Object> builtin_args[] = { right };
2545  Handle<Object> result = Execution::Call(builtin_function,
2546  left,
2547  ARRAY_SIZE(builtin_args),
2548  builtin_args,
2549  &caught_exception);
2550  if (caught_exception) {
2551  return Failure::Exception();
2552  }
2553  return *result;
2554 }
2555 
2556 
2557 Code* CompareIC::GetRawUninitialized(Token::Value op) {
2558  ICCompareStub stub(op, UNINITIALIZED);
2559  Code* code = NULL;
2560  CHECK(stub.FindCodeInCache(&code));
2561  return code;
2562 }
2563 
2564 
2566  ICCompareStub stub(op, UNINITIALIZED);
2567  return stub.GetCode();
2568 }
2569 
2570 
2572  int key = target->major_key();
2573  if (key == CodeStub::Compare) return GENERIC;
2574  ASSERT(key == CodeStub::CompareIC);
2575  return static_cast<State>(target->compare_state());
2576 }
2577 
2578 
2580  ASSERT(target->major_key() == CodeStub::CompareIC);
2581  return static_cast<Token::Value>(
2582  target->compare_operation() + Token::EQ);
2583 }
2584 
2585 
2586 const char* CompareIC::GetStateName(State state) {
2587  switch (state) {
2588  case UNINITIALIZED: return "UNINITIALIZED";
2589  case SMIS: return "SMIS";
2590  case HEAP_NUMBERS: return "HEAP_NUMBERS";
2591  case OBJECTS: return "OBJECTS";
2592  case KNOWN_OBJECTS: return "KNOWN_OBJECTS";
2593  case SYMBOLS: return "SYMBOLS";
2594  case STRINGS: return "STRINGS";
2595  case GENERIC: return "GENERIC";
2596  default:
2597  UNREACHABLE();
2598  return NULL;
2599  }
2600 }
2601 
2602 
2603 CompareIC::State CompareIC::TargetState(State state,
2604  bool has_inlined_smi_code,
2605  Handle<Object> x,
2606  Handle<Object> y) {
2607  switch (state) {
2608  case UNINITIALIZED:
2609  if (x->IsSmi() && y->IsSmi()) return SMIS;
2610  if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS;
2612  // Ordered comparisons treat undefined as NaN, so the
2613  // HEAP_NUMBER stub will do the right thing.
2614  if ((x->IsNumber() && y->IsUndefined()) ||
2615  (y->IsNumber() && x->IsUndefined())) {
2616  return HEAP_NUMBERS;
2617  }
2618  }
2619  if (x->IsSymbol() && y->IsSymbol()) {
2620  // We compare symbols as strings if we need to determine
2621  // the order in a non-equality compare.
2622  return Token::IsEqualityOp(op_) ? SYMBOLS : STRINGS;
2623  }
2624  if (x->IsString() && y->IsString()) return STRINGS;
2625  if (!Token::IsEqualityOp(op_)) return GENERIC;
2626  if (x->IsJSObject() && y->IsJSObject()) {
2627  if (Handle<JSObject>::cast(x)->map() ==
2628  Handle<JSObject>::cast(y)->map() &&
2629  Token::IsEqualityOp(op_)) {
2630  return KNOWN_OBJECTS;
2631  } else {
2632  return OBJECTS;
2633  }
2634  }
2635  return GENERIC;
2636  case SMIS:
2637  return has_inlined_smi_code && x->IsNumber() && y->IsNumber()
2638  ? HEAP_NUMBERS
2639  : GENERIC;
2640  case SYMBOLS:
2642  return x->IsString() && y->IsString() ? STRINGS : GENERIC;
2643  case HEAP_NUMBERS:
2644  case STRINGS:
2645  case OBJECTS:
2646  case KNOWN_OBJECTS:
2647  case GENERIC:
2648  return GENERIC;
2649  }
2650  UNREACHABLE();
2651  return GENERIC;
2652 }
2653 
2654 
2655 // Used from ic_<arch>.cc.
2656 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2657  NoHandleAllocation na;
2658  ASSERT(args.length() == 3);
2659  CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2660  ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2661  return ic.target();
2662 }
2663 
2664 
2665 RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) {
2666  ASSERT(args.length() == 3);
2667 
2668  HandleScope scope(isolate);
2669  Handle<Object> object = args.at<Object>(0);
2670  Register tos = Register::from_code(args.smi_at(1));
2671  ToBooleanStub::Types old_types(args.smi_at(2));
2672 
2673  ToBooleanStub::Types new_types(old_types);
2674  bool to_boolean_value = new_types.Record(object);
2675  old_types.TraceTransition(new_types);
2676 
2677  ToBooleanStub stub(tos, new_types);
2678  Handle<Code> code = stub.GetCode();
2679  ToBooleanIC ic(isolate);
2680  ic.patch(*code);
2681  return Smi::FromInt(to_boolean_value ? 1 : 0);
2682 }
2683 
2684 
2686  set_target(code);
2687 }
2688 
2689 
2690 static const Address IC_utilities[] = {
2691 #define ADDR(name) FUNCTION_ADDR(name),
2693  NULL
2694 #undef ADDR
2695 };
2696 
2697 
2699  return IC_utilities[id];
2700 }
2701 
2702 
2703 } } // namespace v8::internal
byte * Address
Definition: globals.h:157
void patch(Code *code)
Definition: ic.cc:2685
virtual Handle< Code > string_stub()
Definition: ic.h:527
int IndexInCodeCache(Object *name, Code *code)
Definition: objects.cc:5297
static TypeInfo GetTypeInfo(Handle< Object > operand)
Definition: ic.cc:2266
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:1893
Code * builtin(Name name)
Definition: builtins.h:320
static bool CompileLazy(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7643
Object * function() const
Definition: frames-inl.h:231
static Object *& Object_at(Address addr)
Definition: v8memory.h:75
bool IsExternalArrayElementsKind(ElementsKind kind)
Definition: elements-kind.h:94
void UpdateCaches(LookupResult *lookup, State state, Code::ExtraICState extra_ic_state, Handle< Object > object, Handle< String > name)
Definition: ic.cc:694
virtual Code::Kind kind() const =0
Handle< Code > ComputeLoadNormal()
Definition: stub-cache.cc:235
Handle< Code > ComputeCallGlobal(int argc, Code::Kind, Code::ExtraICState extra_state, Handle< String > name, Handle< JSObject > receiver, Handle< GlobalObject > holder, Handle< JSGlobalPropertyCell > cell, Handle< JSFunction > function)
Definition: stub-cache.cc:704
Code * target() const
Definition: ic.h:97
void set(int index, Object *value)
Definition: objects-inl.h:1757
void PrintF(const char *format,...)
Definition: v8utils.cc:40
Handle< Code > ComputeKeyedLoadFunctionPrototype(Handle< String > name, Handle< JSFunction > receiver)
Definition: stub-cache.cc:373
Handle< Code > ComputeStoreField(Handle< String > name, Handle< JSObject > receiver, int field_index, Handle< Map > transition, StrictModeFlag strict_mode)
Definition: stub-cache.cc:390
static TypeFeedbackInfo * cast(Object *obj)
static String * cast(Object *obj)
virtual bool IsGeneric() const
Definition: ic.h:100
static const char * GetName(TypeInfo type_info)
Definition: ic.cc:2241
Code * Set(String *name, Map *map, Code *code)
Definition: stub-cache.cc:59
virtual Handle< Code > GetElementStubWithoutMapCheck(bool is_js_array, ElementsKind elements_kind, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1755
Isolate * isolate()
Definition: heap-inl.h:503
double DoubleToInteger(double x)
int unused_property_fields()
Definition: objects-inl.h:3019
static const char * Name(Value tok)
Definition: token.h:196
static Smi * FromInt(int value)
Definition: objects-inl.h:981
#define LOG(isolate, Call)
Definition: log.h:81
MUST_USE_RESULT MaybeObject * LoadFunction(State state, Handle< Object > object, Handle< Object > key)
Definition: ic.cc:766
void patch(Code *code)
Definition: ic.cc:2236
MUST_USE_RESULT MaybeObject * Load(State state, Handle< Object > object, Handle< String > name)
Definition: ic.cc:814
static Handle< T > cast(Handle< S > that)
Definition: handles.h:81
const int kSmiValueSize
Definition: v8.h:4061
static Map * cast(Object *obj)
static KeyedAccessGrowMode GetKeyedAccessGrowMode(ExtraICState extra_ic_state)
Definition: objects.h:4418
T & at(int i) const
Definition: list.h:90
Builtins * builtins()
Definition: isolate.h:924
static Failure * Exception()
Definition: objects-inl.h:1024
#define TRACE_IC(type, name, old_state, new_target)
Definition: ic.cc:109
static MUST_USE_RESULT MaybeObject * SetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr, StrictModeFlag strict_mode)
Definition: runtime.cc:4222
Handle< Code > ComputeLoadCallback(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< AccessorInfo > callback)
Definition: stub-cache.cc:155
Address address() const
Definition: ic-inl.h:41
void change_ic_with_type_info_count(int count)
Definition: objects-inl.h:5374
Handle< Code > ComputeKeyedLoadOrStoreElement(Handle< Map > receiver_map, KeyedIC::StubKind stub_kind, StrictModeFlag strict_mode)
Definition: stub-cache.cc:412
List< Handle< Map > > MapHandleList
Definition: list.h:198
Failure * TypeError(const char *type, Handle< Object > object, Handle< Object > key)
Definition: ic.cc:280
#define ASSERT(condition)
Definition: checks.h:270
Handle< Code > ComputeStoreViaSetter(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > setter, StrictModeFlag strict_mode)
Definition: stub-cache.cc:526
Handle< Code > ComputeCallMegamorphic(int argc, Code::Kind kind, Code::ExtraICState state)
Definition: stub-cache.cc:846
void set_profiler_ticks(int ticks)
Definition: objects-inl.h:3311
int ComputeExpressionsCount() const
Definition: frames.cc:586
#define PROFILE(isolate, Call)
Definition: cpu-profiler.h:190
static State StateFrom(Code *target, Object *receiver, Object *name)
Definition: ic.cc:227
Handle< Code > ComputeKeyedLoadInterceptor(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder)
Definition: stub-cache.cc:301
static TypeInfo GetTypeInfo(Handle< Object > left, Handle< Object > right)
Definition: ic.cc:2355
Code::Kind kind_
Definition: ic.h:259
static const char * GetName(TypeInfo type_info)
Definition: ic.cc:2306
Isolate * isolate() const
Definition: ic.h:140
static const ExtraICState kNoExtraICState
Definition: objects.h:4236
Handle< Code > ComputeKeyedLoadCallback(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< AccessorInfo > callback)
Definition: stub-cache.cc:319
#define CHECK(condition)
Definition: checks.h:56
int isnan(double x)
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:282
#define RETURN_IF_EMPTY_HANDLE(isolate, call)
Definition: isolate.h:135
Factory * factory()
Definition: isolate.h:992
bool IsFastElementsKind(ElementsKind kind)
PropertyAttributes
static uint32_t update(uint32_t previous, StringStubFeedbackvalue)
Definition: utils.h:268
static TypeInfo TypeFromValue(Handle< Object > value)
Definition: type-info.cc:45
MUST_USE_RESULT MaybeObject * Store(State state, StrictModeFlag strict_mode, Handle< Object > object, Handle< String > name, Handle< Object > value)
Definition: ic.cc:1341
static Code * cast(Object *obj)
static State ToState(TypeInfo type_info)
Definition: ic.cc:2321
void ReceiverToObjectIfRequired(Handle< Object > callee, Handle< Object > object)
Definition: ic.cc:485
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check)
static Smi * cast(Object *object)
Handle< Code > ComputeKeyedLoadArrayLength(Handle< String > name, Handle< JSArray > receiver)
Definition: stub-cache.cc:340
Handle< Code > ComputeCallInterceptor(int argc, Code::Kind, Code::ExtraICState extra_state, Handle< String > name, Handle< Object > object, Handle< JSObject > holder)
Definition: stub-cache.cc:667
Handle< Code > ComputeCallArguments(int argc, Code::Kind kind)
Definition: stub-cache.cc:829
Handle< Code > ComputeLoadField(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, int field_index)
Definition: stub-cache.cc:136
static JSFunctionProxy * cast(Object *obj)
const uint32_t kNotStringTag
Definition: objects.h:457
HANDLE HANDLE LPSTACKFRAME64 StackFrame
static const int kCallerPCOffset
Definition: frames-arm.h:129
#define UNREACHABLE()
Definition: checks.h:50
Handle< Code > ComputeStoreNormal(StrictModeFlag strict_mode)
Definition: stub-cache.cc:480
static void Update(Handle< PolymorphicCodeCache > cache, MapHandleList *maps, Code::Flags flags, Handle< Code > code)
Definition: objects.cc:5782
static void PrintTop(FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:754
static void PostPatching(Address address, Code *target, Code *old_target)
Definition: ic.cc:309
Address pc() const
Definition: ic.h:139
Handle< Code > ComputeCallField(int argc, Code::Kind, Code::ExtraICState extra_state, Handle< String > name, Handle< Object > object, Handle< JSObject > holder, int index)
Definition: stub-cache.cc:629
static Address c_entry_fp(ThreadLocalTop *thread)
Definition: isolate.h:624
Address fp() const
Definition: ic.h:138
static InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags)
Definition: objects-inl.h:3548
IC(FrameDepth depth, Isolate *isolate)
Definition: ic.cc:112
static const int kCallerFPOffset
Definition: frames-arm.h:127
V8EXPORT Local< Value > GetPrototype()
Definition: api.cc:2900
static bool IsValid(intptr_t value)
Definition: objects-inl.h:1059
byte * instruction_start()
Definition: objects-inl.h:4649
static Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:2329
static StrictModeFlag GetStrictMode(ExtraICState extra_ic_state)
Definition: objects.h:4414
const int kPointerSize
Definition: globals.h:220
void SetExpression(int index, Object *value)
Definition: frames-inl.h:158
Handle< Object > SetProperty(Handle< Object > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: handles.cc:232
int Compare(const T &a, const T &b)
Definition: utils.h:156
static Code * GetTargetAtAddress(Address address)
Definition: ic-inl.h:69
static Address & Address_at(Address addr)
Definition: v8memory.h:71
Handle< Code > ComputeKeyedLoadStringLength(Handle< String > name, Handle< String > receiver)
Definition: stub-cache.cc:356
int GetFieldIndex(int descriptor_number)
Definition: objects-inl.h:2141
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
MUST_USE_RESULT MaybeObject * LoadFunction(State state, Code::ExtraICState extra_ic_state, Handle< Object > object, Handle< String > name)
Definition: ic.cc:511
static ExtraICState ComputeExtraICState(KeyedAccessGrowMode grow_mode, StrictModeFlag strict_mode)
Definition: objects.h:4423
static bool decode(uint32_t value)
Definition: utils.h:273
static Register from_code(int code)
static void Clear(Address address, Code *target)
Definition: ic.cc:371
static State ToState(TypeInfo type_info)
Definition: ic.cc:2252
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
static MUST_USE_RESULT Handle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attr, StrictModeFlag strict_mode, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:9886
bool is_inline_cache_stub()
Definition: objects-inl.h:3485
Definition: v8.h:105
PropertyDetails GetDetails(int descriptor_number)
Definition: objects-inl.h:2129
Handle< Code > ComputeStoreGlobal(Handle< String > name, Handle< GlobalObject > receiver, Handle< JSGlobalPropertyCell > cell, StrictModeFlag strict_mode)
Definition: stub-cache.cc:487
static JavaScriptFrame * cast(StackFrame *frame)
Definition: frames.h:532
virtual Handle< Code > GetElementStubWithoutMapCheck(bool is_js_array, ElementsKind elements_kind, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1049
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:945
InlineCacheState ic_state()
Definition: objects-inl.h:3168
static bool IsEqualityOp(Value op)
Definition: token.h:222
Handle< Code > ComputeStoreInterceptor(Handle< String > name, Handle< JSObject > receiver, StrictModeFlag strict_mode)
Definition: stub-cache.cc:546
static Handle< Object > Call(Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:150
#define ADDR(name)
static JSArray * cast(Object *obj)
StubCache * stub_cache()
Definition: isolate.h:837
virtual Handle< Code > ComputePolymorphicStub(MapHandleList *receiver_maps, StrictModeFlag strict_mode, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1058
Handle< Code > ComputeLoadViaGetter(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > getter)
Definition: stub-cache.cc:176
static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous)
Definition: ic.cc:2279
Handle< Object > TryCallAsFunction(Handle< Object > object)
Definition: ic.cc:468
InlineCacheState State
Definition: ic.h:82
Handle< Code > ComputeKeyedLoadField(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, int field_index)
Definition: stub-cache.cc:261
MUST_USE_RESULT MaybeObject * Load(State state, Handle< Object > object, Handle< Object > key, bool force_generic_stub)
Definition: ic.cc:1099
Handle< Code > ComputeCallNormal(int argc, Code::Kind kind, Code::ExtraICState state)
Definition: stub-cache.cc:812
#define IC_UTIL_LIST(ICU)
Definition: ic.h:40
bool is_null() const
Definition: handles.h:87
Handle< Object > NewReferenceError(const char *type, Vector< Handle< Object > > args)
Definition: factory.cc:662
Handle< Code > ComputeKeyedStoreField(Handle< String > name, Handle< JSObject > receiver, int field_index, Handle< Map > transition, StrictModeFlag strict_mode)
Definition: stub-cache.cc:562
ExtraICState extra_ic_state()
Definition: objects-inl.h:3181
static Object * cast(Object *value)
Definition: objects.h:1007
static MUST_USE_RESULT MaybeObject * FunctionGetPrototype(Object *object, void *)
Definition: accessors.cc:443
Handle< Object > NewTypeError(const char *type, Vector< Handle< Object > > args)
Definition: factory.cc:630
static Address target_address_from_return_address(Address pc)
static Token::Value ComputeOperation(Code *target)
Definition: ic.cc:2579
static Handle< Object > GetFunctionDelegate(Handle< Object > object)
Definition: execution.cc:229
static JSValue * cast(Object *obj)
Definition: objects-inl.h:4600
static Handle< T > null()
Definition: handles.h:86
virtual Handle< Code > ComputePolymorphicStub(MapHandleList *receiver_maps, StrictModeFlag strict_mode, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1763
Map * FindFirstMap()
Definition: objects.cc:8401
#define HEAP
Definition: isolate.h:1433
static JSObject * GetCodeCacheHolder(Object *object, InlineCacheHolderFlag holder)
Definition: ic-inl.h:131
static void SetTargetAtAddress(Address address, Code *target)
Definition: ic-inl.h:80
MUST_USE_RESULT MaybeObject * GetProperty(String *key)
Definition: objects-inl.h:859
static MUST_USE_RESULT MaybeObject * GetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key)
Definition: runtime.cc:3970
virtual Handle< Code > ComputePolymorphicStub(MapHandleList *receiver_maps, StrictModeFlag strict_mode, KeyedAccessGrowMode grow_mode)=0
static JSProxy * cast(Object *obj)
static State ComputeState(Code *target)
Definition: ic.cc:2571
virtual Handle< Code > string_stub()
Definition: ic.h:430
Counters * counters()
Definition: isolate.h:819
Handle< Code > ComputeMonomorphicStub(LookupResult *lookup, State state, Code::ExtraICState extra_state, Handle< Object > object, Handle< String > name)
Definition: ic.cc:640
Handle< Code > ComputeStub(Handle< JSObject > receiver, StubKind stub_kind, StrictModeFlag strict_mode, Handle< Code > default_stub)
Definition: ic.cc:1593
static FixedArray * cast(Object *obj)
#define TRACE_GENERIC_IC(type, reason)
Definition: ic.cc:106
static Handle< Object > GetElement(Handle< Object > object, uint32_t index)
Definition: objects.cc:250
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 TryUpdateExtraICState(LookupResult *lookup, Handle< Object > object, Code::ExtraICState *extra_ic_state)
Definition: ic.cc:596
void set_target(Code *code)
Definition: ic.h:149
Handle< Code > ComputeCallPreMonomorphic(int argc, Code::Kind kind, Code::ExtraICState extra_state)
Definition: stub-cache.cc:794
virtual Handle< Code > GetElementStubWithoutMapCheck(bool is_js_array, ElementsKind elements_kind, KeyedAccessGrowMode grow_mode)=0
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
Handle< Code > ComputeLoadNonexistent(Handle< String > name, Handle< JSObject > receiver)
Definition: stub-cache.cc:103
static TypeInfo JoinTypes(TypeInfo x, TypeInfo y)
Definition: ic.cc:2340
Handle< Code > ComputeLoadConstant(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > value)
Definition: stub-cache.cc:196
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:117
const int kMaxKeyedPolymorphism
Definition: type-info.h:39
Handle< Code > ComputeLoadInterceptor(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder)
Definition: stub-cache.cc:216
Handle< Code > CompileLoadPolymorphic(MapHandleList *receiver_maps, CodeHandleList *handler_ics)
Handle< Code > ComputeCallConstant(int argc, Code::Kind, Code::ExtraICState extra_state, Handle< String > name, Handle< Object > object, Handle< JSObject > holder, Handle< JSFunction > function)
Definition: stub-cache.cc:588
Handle< Code > CompileStorePolymorphic(MapHandleList *receiver_maps, CodeHandleList *handler_stubs, MapHandleList *transitioned_maps)
static const char * GetStateName(State state)
Definition: ic.cc:2586
KeyedAccessGrowMode
Definition: objects.h:142
MUST_USE_RESULT MaybeObject * Store(State state, StrictModeFlag strict_mode, Handle< Object > object, Handle< Object > name, Handle< Object > value, bool force_generic)
Definition: ic.cc:1866
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
ThreadLocalTop * thread_local_top()
Definition: isolate.h:839
void patch(Code *code)
Definition: ic.cc:2301
RelocInfo::Mode ComputeMode()
Definition: ic.cc:267
static Address AddressFromUtilityId(UtilityId id)
Definition: ic.cc:2698
static Handle< Code > GetUninitialized(Token::Value op)
Definition: ic.cc:2565
#define ARRAY_SIZE(a)
Definition: globals.h:281
Handle< Code > ComputeKeyedLoadConstant(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > value)
Definition: stub-cache.cc:281
bool IsContextual(Handle< Object > receiver)
Definition: ic.h:115
Failure * ReferenceError(const char *type, Handle< String > name)
Definition: ic.cc:291
Handle< Code > ComputeLoadGlobal(Handle< String > name, Handle< JSObject > receiver, Handle< GlobalObject > holder, Handle< JSGlobalPropertyCell > cell, bool is_dont_delete)
Definition: stub-cache.cc:240
static JSObject * cast(Object *obj)
static MUST_USE_RESULT MaybeObject * GetElementOrCharAt(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: runtime.cc:3945
Handle< Code > ComputeMonomorphicStubWithoutMapCheck(Handle< Map > receiver_map, StrictModeFlag strict_mode, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1688
static void Clear(Address address)
Definition: ic.cc:344
bool IsDictionaryElementsKind(ElementsKind kind)
Definition: elements-kind.h:89
int FastD2I(double x)
Definition: conversions.h:69
static bool IsOrderedRelationalCompareOp(Value op)
Definition: token.h:218
Handle< Code > ComputeStoreCallback(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< AccessorInfo > callback, StrictModeFlag strict_mode)
Definition: stub-cache.cc:505
static JSFunction * cast(Object *obj)