V8 Project
ic.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "src/v8.h"
6 
7 #include "src/accessors.h"
8 #include "src/api.h"
9 #include "src/arguments.h"
10 #include "src/base/bits.h"
11 #include "src/codegen.h"
12 #include "src/conversions.h"
13 #include "src/execution.h"
16 #include "src/ic/ic-inl.h"
17 #include "src/ic/ic-compiler.h"
18 #include "src/ic/stub-cache.h"
19 #include "src/prototype.h"
20 #include "src/runtime/runtime.h"
21 
22 namespace v8 {
23 namespace internal {
24 
26  switch (state) {
27  case UNINITIALIZED:
28  return '0';
29  case PREMONOMORPHIC:
30  return '.';
31  case MONOMORPHIC:
32  return '1';
33  case PROTOTYPE_FAILURE:
34  return '^';
35  case POLYMORPHIC:
36  return 'P';
37  case MEGAMORPHIC:
38  return 'N';
39  case GENERIC:
40  return 'G';
41 
42  // We never see the debugger states here, because the state is
43  // computed from the original code - not the patched code. Let
44  // these cases fall through to the unreachable code below.
45  case DEBUG_STUB:
46  break;
47  // Type-vector-based ICs resolve state to one of the above.
48  case DEFAULT:
49  break;
50  }
51  UNREACHABLE();
52  return 0;
53 }
54 
55 
57  if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
59  return ".IGNORE_OOB";
60  }
61  if (IsGrowStoreMode(mode)) return ".GROW";
62  return "";
63 }
64 
65 
66 #ifdef DEBUG
67 
68 #define TRACE_GENERIC_IC(isolate, type, reason) \
69  do { \
70  if (FLAG_trace_ic) { \
71  PrintF("[%s patching generic stub in ", type); \
72  JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
73  PrintF(" (%s)]\n", reason); \
74  } \
75  } while (false)
76 
77 #else
78 
79 #define TRACE_GENERIC_IC(isolate, type, reason) \
80  do { \
81  if (FLAG_trace_ic) { \
82  PrintF("[%s patching generic stub in ", type); \
83  PrintF("(see below) (%s)]\n", reason); \
84  } \
85  } while (false)
86 
87 #endif // DEBUG
88 
89 
90 void IC::TraceIC(const char* type, Handle<Object> name) {
91  if (FLAG_trace_ic) {
92  Code* new_target = raw_target();
93  State new_state = new_target->ic_state();
94  TraceIC(type, name, state(), new_state);
95  }
96 }
97 
98 
99 void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
100  State new_state) {
101  if (FLAG_trace_ic) {
102  Code* new_target = raw_target();
103  PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
104 
105  // TODO(jkummerow): Add support for "apply". The logic is roughly:
106  // marker = [fp_ + kMarkerOffset];
107  // if marker is smi and marker.value == INTERNAL and
108  // the frame's code == builtin(Builtins::kFunctionApply):
109  // then print "apply from" and advance one frame
110 
111  Object* maybe_function =
113  if (maybe_function->IsJSFunction()) {
114  JSFunction* function = JSFunction::cast(maybe_function);
115  JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(),
116  stdout, true);
117  }
118 
119  ExtraICState extra_state = new_target->extra_ic_state();
120  const char* modifier = "";
121  if (new_target->kind() == Code::KEYED_STORE_IC) {
122  modifier = GetTransitionMarkModifier(
124  }
125  PrintF(" (%c->%c%s)", TransitionMarkFromState(old_state),
126  TransitionMarkFromState(new_state), modifier);
127 #ifdef OBJECT_PRINT
128  OFStream os(stdout);
129  name->Print(os);
130 #else
131  name->ShortPrint(stdout);
132 #endif
133  PrintF("]\n");
134  }
135 }
136 
137 #define TRACE_IC(type, name) TraceIC(type, name)
138 #define TRACE_VECTOR_IC(type, name, old_state, new_state) \
139  TraceIC(type, name, old_state, new_state)
140 
141 IC::IC(FrameDepth depth, Isolate* isolate)
142  : isolate_(isolate), target_set_(false), target_maps_set_(false) {
143  // To improve the performance of the (much used) IC code, we unfold a few
144  // levels of the stack frame iteration code. This yields a ~35% speedup when
145  // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
148  if (FLAG_enable_ool_constant_pool) {
149  constant_pool =
151  }
152  Address* pc_address =
153  reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
155  // If there's another JavaScript frame on the stack or a
156  // StubFailureTrampoline, we need to look one frame further down the stack to
157  // find the frame pointer and the return address stack slot.
158  if (depth == EXTRA_CALL_FRAME) {
159  if (FLAG_enable_ool_constant_pool) {
160  constant_pool =
162  }
163  const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
164  pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
166  }
167 #ifdef DEBUG
169  for (int i = 0; i < depth + 1; i++) it.Advance();
170  StackFrame* frame = it.frame();
171  DCHECK(fp == frame->fp() && pc_address == frame->pc_address());
172 #endif
173  fp_ = fp;
174  if (FLAG_enable_ool_constant_pool) {
176  ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)),
177  isolate);
178  }
179  pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
181  state_ = target_->ic_state();
182  kind_ = target_->kind();
183  extra_ic_state_ = target_->extra_ic_state();
184 }
185 
186 
188  // Compute the JavaScript frame for the frame pointer of this IC
189  // structure. We need this to be able to find the function
190  // corresponding to the frame.
192  while (it.frame()->fp() != this->fp()) it.Advance();
194  // Find the function on the stack and both the active code for the
195  // function and the original code.
196  JSFunction* function = frame->function();
197  return function->shared();
198 }
199 
200 
201 Code* IC::GetCode() const {
202  HandleScope scope(isolate());
204  Code* code = shared->code();
205  return code;
206 }
207 
208 
210  HandleScope scope(isolate());
212  DCHECK(Debug::HasDebugInfo(shared));
213  Code* original_code = Debug::GetDebugInfo(shared)->original_code();
214  DCHECK(original_code->IsCode());
215  return original_code;
216 }
217 
218 
219 static void LookupForRead(LookupIterator* it) {
220  for (; it->IsFound(); it->Next()) {
221  switch (it->state()) {
222  case LookupIterator::NOT_FOUND:
223  case LookupIterator::TRANSITION:
224  UNREACHABLE();
225  case LookupIterator::JSPROXY:
226  return;
227  case LookupIterator::INTERCEPTOR: {
228  // If there is a getter, return; otherwise loop to perform the lookup.
229  Handle<JSObject> holder = it->GetHolder<JSObject>();
230  if (!holder->GetNamedInterceptor()->getter()->IsUndefined()) {
231  return;
232  }
233  break;
234  }
235  case LookupIterator::ACCESS_CHECK:
236  // PropertyHandlerCompiler::CheckPrototypes() knows how to emit
237  // access checks for global proxies.
238  if (it->GetHolder<JSObject>()->IsJSGlobalProxy() &&
239  it->HasAccess(v8::ACCESS_GET)) {
240  break;
241  }
242  return;
244  case LookupIterator::DATA:
245  return;
246  }
247  }
248 }
249 
250 
253  if (!IsNameCompatibleWithPrototypeFailure(name)) return false;
254  Handle<Map> receiver_map = TypeToMap(*receiver_type(), isolate());
255  maybe_handler_ = target()->FindHandlerForMap(*receiver_map);
256 
257  // The current map wasn't handled yet. There's no reason to stay monomorphic,
258  // *unless* we're moving from a deprecated map to its replacement, or
259  // to a more general elements kind.
260  // TODO(verwaest): Check if the current map is actually what the old map
261  // would transition to.
262  if (maybe_handler_.is_null()) {
263  if (!receiver_map->IsJSObjectMap()) return false;
264  Map* first_map = FirstTargetMap();
265  if (first_map == NULL) return false;
266  Handle<Map> old_map(first_map);
267  if (old_map->is_deprecated()) return true;
268  if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
269  receiver_map->elements_kind())) {
270  return true;
271  }
272  return false;
273  }
274 
276  Handle<Map> ic_holder_map(
278 
279  DCHECK(flag != kCacheOnReceiver || receiver->IsJSObject());
280  DCHECK(flag != kCacheOnPrototype || !receiver->IsJSReceiver());
282 
283  if (state() == MONOMORPHIC) {
284  int index = ic_holder_map->IndexInCodeCache(*name, *target());
285  if (index >= 0) {
286  ic_holder_map->RemoveFromCodeCache(*name, *target(), index);
287  }
288  }
289 
290  if (receiver->IsGlobalObject()) {
292  LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
293  if (it.state() == LookupIterator::ACCESS_CHECK) return false;
294  if (!it.IsFound()) return false;
295  Handle<PropertyCell> cell = it.GetPropertyCell();
296  return cell->type()->IsConstant();
297  }
298 
299  return true;
300 }
301 
302 
304  if (target()->is_keyed_stub()) {
305  // Determine whether the failure is due to a name failure.
306  if (!name->IsName()) return false;
307  Name* stub_name = target()->FindFirstName();
308  if (*name != stub_name) return false;
309  }
310 
311  return true;
312 }
313 
314 
316  update_receiver_type(receiver);
317  if (!name->IsString()) return;
318  if (state() != MONOMORPHIC && state() != POLYMORPHIC) return;
319  if (receiver->IsUndefined() || receiver->IsNull()) return;
320 
321  // Remove the target from the code cache if it became invalid
322  // because of changes in the prototype chain to avoid hitting it
323  // again.
327  return;
328  }
329 
330  // The builtins object is special. It only changes when JavaScript
331  // builtins are loaded lazily. It is important to keep inline
332  // caches for the builtins object monomorphic. Therefore, if we get
333  // an inline cache miss for the builtins object after lazily loading
334  // JavaScript builtins, we return uninitialized as the state to
335  // force the inline cache back to monomorphic state.
336  if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED;
337 }
338 
339 
341  Handle<Object> key) {
342  HandleScope scope(isolate());
343  Handle<Object> args[2] = {key, object};
344  THROW_NEW_ERROR(isolate(), NewTypeError(type, HandleVector(args, 2)), Object);
345 }
346 
347 
349  HandleScope scope(isolate());
350  THROW_NEW_ERROR(isolate(), NewReferenceError(type, HandleVector(&name, 1)),
351  Object);
352 }
353 
354 
355 static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state,
356  int* polymorphic_delta,
357  int* generic_delta) {
358  switch (old_state) {
359  case UNINITIALIZED:
360  case PREMONOMORPHIC:
361  if (new_state == UNINITIALIZED || new_state == PREMONOMORPHIC) break;
362  if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
363  *polymorphic_delta = 1;
364  } else if (new_state == MEGAMORPHIC || new_state == GENERIC) {
365  *generic_delta = 1;
366  }
367  break;
368  case MONOMORPHIC:
369  case POLYMORPHIC:
370  if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) break;
371  *polymorphic_delta = -1;
372  if (new_state == MEGAMORPHIC || new_state == GENERIC) {
373  *generic_delta = 1;
374  }
375  break;
376  case MEGAMORPHIC:
377  case GENERIC:
378  if (new_state == MEGAMORPHIC || new_state == GENERIC) break;
379  *generic_delta = -1;
380  if (new_state == MONOMORPHIC || new_state == POLYMORPHIC) {
381  *polymorphic_delta = 1;
382  }
383  break;
384  case PROTOTYPE_FAILURE:
385  case DEBUG_STUB:
386  case DEFAULT:
387  UNREACHABLE();
388  }
389 }
390 
391 
393  State old_state, State new_state,
394  bool target_remains_ic_stub) {
395  Code* host =
397  if (host->kind() != Code::FUNCTION) return;
398 
399  if (FLAG_type_info_threshold > 0 && target_remains_ic_stub &&
400  // Not all Code objects have TypeFeedbackInfo.
401  host->type_feedback_info()->IsTypeFeedbackInfo()) {
402  int polymorphic_delta = 0; // "Polymorphic" here includes monomorphic.
403  int generic_delta = 0; // "Generic" here includes megamorphic.
404  ComputeTypeInfoCountDelta(old_state, new_state, &polymorphic_delta,
405  &generic_delta);
406  TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
407  info->change_ic_with_type_info_count(polymorphic_delta);
408  info->change_ic_generic_count(generic_delta);
409  }
410  if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
411  TypeFeedbackInfo* info = TypeFeedbackInfo::cast(host->type_feedback_info());
413  }
414  host->set_profiler_ticks(0);
416  // TODO(2029): When an optimized function is patched, it would
417  // be nice to propagate the corresponding type information to its
418  // unoptimized version for the benefit of later inlining.
419 }
420 
421 
422 void IC::PostPatching(Address address, Code* target, Code* old_target) {
423  // Type vector based ICs update these statistics at a different time because
424  // they don't always patch on state change.
425  if (target->kind() == Code::CALL_IC) return;
426 
427  Isolate* isolate = target->GetHeap()->isolate();
428  State old_state = UNINITIALIZED;
429  State new_state = UNINITIALIZED;
430  bool target_remains_ic_stub = false;
431  if (old_target->is_inline_cache_stub() && target->is_inline_cache_stub()) {
432  old_state = old_target->ic_state();
433  new_state = target->ic_state();
434  target_remains_ic_stub = true;
435  }
436 
437  OnTypeFeedbackChanged(isolate, address, old_state, new_state,
438  target_remains_ic_stub);
439 }
440 
441 
443  if (FLAG_collect_maps && FLAG_weak_embedded_maps_in_ic &&
444  stub->CanBeWeakStub()) {
445  DCHECK(!stub->is_weak_stub());
446  MapHandleList maps;
447  stub->FindAllMaps(&maps);
448  if (maps.length() == 1 && stub->IsWeakObjectInIC(*maps.at(0))) {
449  Map::AddDependentIC(maps.at(0), stub);
450  stub->mark_as_weak_stub();
451  if (FLAG_enable_ool_constant_pool) {
452  stub->constant_pool()->set_weak_object_state(
454  }
455  }
456  }
457 }
458 
459 
461  DCHECK(stub->is_weak_stub());
463  Isolate* isolate = stub->GetIsolate();
464  Heap* heap = isolate->heap();
465  Object* undefined = heap->undefined_value();
467  for (RelocIterator it(stub, mode_mask); !it.done(); it.next()) {
468  RelocInfo::Mode mode = it.rinfo()->rmode();
470  it.rinfo()->target_object()->IsMap()) {
471  it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
472  }
473  }
475 }
476 
477 
478 void IC::Clear(Isolate* isolate, Address address,
479  ConstantPoolArray* constant_pool) {
481 
482  // Don't clear debug break inline cache as it will remove the break point.
483  if (target->is_debug_stub()) return;
484 
485  switch (target->kind()) {
486  case Code::LOAD_IC:
488  case Code::KEYED_LOAD_IC:
490  case Code::STORE_IC:
492  case Code::KEYED_STORE_IC:
494  case Code::CALL_IC:
496  case Code::COMPARE_IC:
498  case Code::COMPARE_NIL_IC:
500  case Code::BINARY_OP_IC:
501  case Code::TO_BOOLEAN_IC:
502  // Clearing these is tricky and does not
503  // make any performance difference.
504  return;
505  default:
506  UNREACHABLE();
507  }
508 }
509 
510 
511 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target,
512  ConstantPoolArray* constant_pool) {
513  if (IsCleared(target)) return;
514  // Make sure to also clear the map used in inline fast cases. If we
515  // do not clear these maps, cached code can keep objects alive
516  // through the embedded maps.
518 }
519 
520 
521 void CallIC::Clear(Isolate* isolate, Address address, Code* target,
522  ConstantPoolArray* constant_pool) {
523  // Currently, CallIC doesn't have state changes.
524 }
525 
526 
527 void LoadIC::Clear(Isolate* isolate, Address address, Code* target,
528  ConstantPoolArray* constant_pool) {
529  if (IsCleared(target)) return;
530  Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::LOAD_IC,
531  target->extra_ic_state());
533 }
534 
535 
536 void StoreIC::Clear(Isolate* isolate, Address address, Code* target,
537  ConstantPoolArray* constant_pool) {
538  if (IsCleared(target)) return;
539  Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::STORE_IC,
540  target->extra_ic_state());
542 }
543 
544 
545 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target,
546  ConstantPoolArray* constant_pool) {
547  if (IsCleared(target)) return;
550  isolate, StoreIC::GetStrictMode(target->extra_ic_state())),
551  constant_pool);
552 }
553 
554 
555 void CompareIC::Clear(Isolate* isolate, Address address, Code* target,
556  ConstantPoolArray* constant_pool) {
557  DCHECK(CodeStub::GetMajorKey(target) == CodeStub::CompareIC);
558  CompareICStub stub(target->stub_key(), isolate);
559  // Only clear CompareICs that can retain objects.
560  if (stub.state() != CompareICState::KNOWN_OBJECT) return;
562  constant_pool);
564 }
565 
566 
567 // static
569  if (FLAG_compiled_keyed_generic_loads) {
570  return KeyedLoadGenericStub(isolate).GetCode();
571  } else {
572  return isolate->builtins()->KeyedLoadIC_Generic();
573  }
574 }
575 
576 
577 static bool MigrateDeprecated(Handle<Object> object) {
578  if (!object->IsJSObject()) return false;
579  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
580  if (!receiver->map()->is_deprecated()) return false;
582  return true;
583 }
584 
585 
587  // If the object is undefined or null it's illegal to try to get any
588  // of its properties; throw a TypeError in that case.
589  if (object->IsUndefined() || object->IsNull()) {
590  return TypeError("non_object_property_load", object, name);
591  }
592 
593  // Check if the name is trivially convertible to an index and get
594  // the element or char if so.
595  uint32_t index;
596  if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
597  // Rewrite to the generic keyed load stub.
598  if (FLAG_use_ic) {
600  TRACE_IC("LoadIC", name);
601  TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
602  }
603  Handle<Object> result;
605  isolate(), result,
606  Runtime::GetElementOrCharAt(isolate(), object, index), Object);
607  return result;
608  }
609 
610  bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
611 
612  // Named lookup in the object.
613  LookupIterator it(object, name);
614  LookupForRead(&it);
615 
616  if (it.IsFound() || !IsUndeclaredGlobal(object)) {
617  // Update inline cache and stub cache.
618  if (use_ic) UpdateCaches(&it);
619 
620  // Get the property.
621  Handle<Object> result;
623  Object);
624  if (it.IsFound()) {
625  return result;
626  } else if (!IsUndeclaredGlobal(object)) {
627  LOG(isolate(), SuspectReadEvent(*name, *object));
628  return result;
629  }
630  }
631  return ReferenceError("not_defined", name);
632 }
633 
634 
635 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
636  Handle<Map> new_receiver_map) {
637  DCHECK(!new_receiver_map.is_null());
638  for (int current = 0; current < receiver_maps->length(); ++current) {
639  if (!receiver_maps->at(current).is_null() &&
640  receiver_maps->at(current).is_identical_to(new_receiver_map)) {
641  return false;
642  }
643  }
644  receiver_maps->Add(new_receiver_map);
645  return true;
646 }
647 
648 
650  if (!code->is_handler()) return false;
651  if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false;
653  TypeHandleList types;
654  CodeHandleList handlers;
655 
656  TargetTypes(&types);
657  int number_of_types = types.length();
658  int deprecated_types = 0;
659  int handler_to_overwrite = -1;
660 
661  for (int i = 0; i < number_of_types; i++) {
662  Handle<HeapType> current_type = types.at(i);
663  if (current_type->IsClass() &&
664  current_type->AsClass()->Map()->is_deprecated()) {
665  // Filter out deprecated maps to ensure their instances get migrated.
666  ++deprecated_types;
667  } else if (type->NowIs(current_type)) {
668  // If the receiver type is already in the polymorphic IC, this indicates
669  // there was a prototoype chain failure. In that case, just overwrite the
670  // handler.
671  handler_to_overwrite = i;
672  } else if (handler_to_overwrite == -1 && current_type->IsClass() &&
673  type->IsClass() &&
674  IsTransitionOfMonomorphicTarget(*current_type->AsClass()->Map(),
675  *type->AsClass()->Map())) {
676  handler_to_overwrite = i;
677  }
678  }
679 
680  int number_of_valid_types =
681  number_of_types - deprecated_types - (handler_to_overwrite != -1);
682 
683  if (number_of_valid_types >= 4) return false;
684  if (number_of_types == 0) return false;
685  if (!target()->FindHandlers(&handlers, types.length())) return false;
686 
687  number_of_valid_types++;
688  if (number_of_valid_types > 1 && target()->is_keyed_stub()) return false;
689  Handle<Code> ic;
690  if (number_of_valid_types == 1) {
692  extra_ic_state());
693  } else {
694  if (handler_to_overwrite >= 0) {
695  handlers.Set(handler_to_overwrite, code);
696  if (!type->NowIs(types.at(handler_to_overwrite))) {
697  types.Set(handler_to_overwrite, type);
698  }
699  } else {
700  types.Add(type);
701  handlers.Add(code);
702  }
703  ic = PropertyICCompiler::ComputePolymorphic(kind(), &types, &handlers,
704  number_of_valid_types, name,
705  extra_ic_state());
706  }
707  set_target(*ic);
708  return true;
709 }
710 
711 
713  return object->IsJSGlobalObject()
715  : HeapType::NowOf(object, isolate);
716 }
717 
718 
720  if (type->Is(HeapType::Number()))
721  return isolate->factory()->heap_number_map();
722  if (type->Is(HeapType::Boolean())) return isolate->factory()->boolean_map();
723  if (type->IsConstant()) {
724  return handle(
725  Handle<JSGlobalObject>::cast(type->AsConstant()->Value())->map());
726  }
727  DCHECK(type->IsClass());
728  return type->AsClass()->Map();
729 }
730 
731 
732 template <class T>
733 typename T::TypeHandle IC::MapToType(Handle<Map> map,
734  typename T::Region* region) {
735  if (map->instance_type() == HEAP_NUMBER_TYPE) {
736  return T::Number(region);
737  } else if (map->instance_type() == ODDBALL_TYPE) {
738  // The only oddballs that can be recorded in ICs are booleans.
739  return T::Boolean(region);
740  } else {
741  return T::Class(map, region);
742  }
743 }
744 
745 
746 template Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone);
747 
748 
749 template Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map,
750  Isolate* region);
751 
752 
754  DCHECK(handler->is_handler());
756  kind(), name, receiver_type(), handler, extra_ic_state());
757  set_target(*ic);
758 }
759 
760 
762  TypeHandleList types;
763  CodeHandleList handlers;
764  TargetTypes(&types);
765  if (!target()->FindHandlers(&handlers, types.length())) return;
766  for (int i = 0; i < types.length(); i++) {
767  UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
768  }
769 }
770 
771 
772 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
773  if (source_map == NULL) return true;
774  if (target_map == NULL) return false;
775  ElementsKind target_elements_kind = target_map->elements_kind();
776  bool more_general_transition = IsMoreGeneralElementsKindTransition(
777  source_map->elements_kind(), target_elements_kind);
778  Map* transitioned_map =
779  more_general_transition
780  ? source_map->LookupElementsTransitionMap(target_elements_kind)
781  : NULL;
782 
783  return transitioned_map == target_map;
784 }
785 
786 
788  switch (state()) {
789  case UNINITIALIZED:
790  case PREMONOMORPHIC:
791  UpdateMonomorphicIC(code, name);
792  break;
793  case PROTOTYPE_FAILURE:
794  case MONOMORPHIC:
795  case POLYMORPHIC:
796  if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) {
797  if (UpdatePolymorphicIC(name, code)) break;
799  }
801  // Fall through.
802  case MEGAMORPHIC:
804  break;
805  case DEBUG_STUB:
806  break;
807  case DEFAULT:
808  case GENERIC:
809  UNREACHABLE();
810  break;
811  }
812 }
813 
814 
816  ExtraICState extra_state) {
818 }
819 
820 
822  if (kind() == Code::LOAD_IC) {
823  MegamorphicLoadStub stub(isolate(), LoadICState(extra_ic_state()));
824  return stub.GetCode();
825  } else {
826  DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
828  }
829 }
830 
831 
833  ExtraICState extra_state) {
835 }
836 
837 
839  return isolate->builtins()->KeyedLoadIC_PreMonomorphic();
840 }
841 
842 
844  if (kind() == Code::LOAD_IC) {
846  } else {
847  DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
849  }
850 }
851 
852 
854  LoadFieldStub stub(isolate(), index);
855  return stub.GetCode();
856 }
857 
858 
859 void LoadIC::UpdateCaches(LookupIterator* lookup) {
860  if (state() == UNINITIALIZED) {
861  // This is the first time we execute this inline cache. Set the target to
862  // the pre monomorphic stub to delay setting the monomorphic state.
864  TRACE_IC("LoadIC", lookup->name());
865  return;
866  }
867 
868  Handle<Code> code;
869  if (lookup->state() == LookupIterator::JSPROXY ||
870  lookup->state() == LookupIterator::ACCESS_CHECK) {
871  code = slow_stub();
872  } else if (!lookup->IsFound()) {
873  if (kind() == Code::LOAD_IC) {
875  receiver_type());
876  // TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
877  if (code.is_null()) code = slow_stub();
878  } else {
879  code = slow_stub();
880  }
881  } else {
882  code = ComputeHandler(lookup);
883  }
884 
885  PatchCache(lookup->name(), code);
886  TRACE_IC("LoadIC", lookup->name());
887 }
888 
889 
891  if (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC) return;
892  Map* map = *TypeToMap(type, isolate());
893  isolate()->stub_cache()->Set(name, map, code);
894 }
895 
896 
897 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) {
898  bool receiver_is_holder =
899  lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>());
901  Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder(
902  *receiver_type(), receiver_is_holder, isolate(), &flag);
903 
905  lookup->name(), stub_holder_map, kind(), flag,
906  lookup->is_dictionary_holder() ? Code::NORMAL : Code::FAST);
907  // Use the cached value if it exists, and if it is different from the
908  // handler that just missed.
909  if (!code.is_null()) {
910  if (!maybe_handler_.is_null() &&
911  !maybe_handler_.ToHandleChecked().is_identical_to(code)) {
912  return code;
913  }
914  if (maybe_handler_.is_null()) {
915  // maybe_handler_ is only populated for MONOMORPHIC and POLYMORPHIC ICs.
916  // In MEGAMORPHIC case, check if the handler in the megamorphic stub
917  // cache (which just missed) is different from the cached handler.
918  if (state() == MEGAMORPHIC && lookup->GetReceiver()->IsHeapObject()) {
919  Map* map = Handle<HeapObject>::cast(lookup->GetReceiver())->map();
920  Code* megamorphic_cached_code =
921  isolate()->stub_cache()->Get(*lookup->name(), map, code->flags());
922  if (megamorphic_cached_code != *code) return code;
923  } else {
924  return code;
925  }
926  }
927  }
928 
929  code = CompileHandler(lookup, value, flag);
930  DCHECK(code->is_handler());
931 
932  // TODO(mvstanton): we'd only like to cache code on the map when it's custom
933  // code compiled for this map, otherwise it's already cached in the global
934  // code
935  // cache. We are also guarding against installing code with flags that don't
936  // match the desired CacheHolderFlag computed above, which would lead to
937  // invalid lookups later.
938  if (code->type() != Code::NORMAL &&
939  Code::ExtractCacheHolderFromFlags(code->flags()) == flag) {
940  Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
941  }
942 
943  return code;
944 }
945 
946 
947 Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
948  Handle<Object> unused,
949  CacheHolderFlag cache_holder) {
950  Handle<Object> receiver = lookup->GetReceiver();
951  if (receiver->IsString() &&
952  Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
953  FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
954  return SimpleFieldLoad(index);
955  }
956 
957  if (receiver->IsStringWrapper() &&
958  Name::Equals(isolate()->factory()->length_string(), lookup->name())) {
959  StringLengthStub string_length_stub(isolate());
960  return string_length_stub.GetCode();
961  }
962 
963  // Use specialized code for getting prototype of functions.
964  if (receiver->IsJSFunction() &&
965  Name::Equals(isolate()->factory()->prototype_string(), lookup->name()) &&
966  Handle<JSFunction>::cast(receiver)->should_have_prototype() &&
967  !Handle<JSFunction>::cast(receiver)
968  ->map()
969  ->has_non_instance_prototype()) {
970  Handle<Code> stub;
971  FunctionPrototypeStub function_prototype_stub(isolate());
972  return function_prototype_stub.GetCode();
973  }
974 
976  Handle<JSObject> holder = lookup->GetHolder<JSObject>();
977  bool receiver_is_holder = receiver.is_identical_to(holder);
978  switch (lookup->state()) {
979  case LookupIterator::INTERCEPTOR: {
980  DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined());
981  NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
982  cache_holder);
983  // Perform a lookup behind the interceptor. Copy the LookupIterator since
984  // the original iterator will be used to fetch the value.
985  LookupIterator it = *lookup;
986  it.Next();
987  LookupForRead(&it);
988  return compiler.CompileLoadInterceptor(&it);
989  }
990 
992  // Use simple field loads for some well-known callback properties.
993  if (receiver_is_holder) {
994  DCHECK(receiver->IsJSObject());
995  Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
996  int object_offset;
997  if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, lookup->name(),
998  &object_offset)) {
999  FieldIndex index =
1000  FieldIndex::ForInObjectOffset(object_offset, js_receiver->map());
1001  return SimpleFieldLoad(index);
1002  }
1003  }
1004 
1005  Handle<Object> accessors = lookup->GetAccessors();
1006  if (accessors->IsExecutableAccessorInfo()) {
1009  if (v8::ToCData<Address>(info->getter()) == 0) break;
1011  type)) {
1012  break;
1013  }
1014  if (!holder->HasFastProperties()) break;
1015  NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1016  cache_holder);
1017  return compiler.CompileLoadCallback(lookup->name(), info);
1018  }
1019  if (accessors->IsAccessorPair()) {
1020  Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(),
1021  isolate());
1022  if (!getter->IsJSFunction()) break;
1023  if (!holder->HasFastProperties()) break;
1024  Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1025  if (!receiver->IsJSObject() && !function->IsBuiltin() &&
1026  function->shared()->strict_mode() == SLOPPY) {
1027  // Calling sloppy non-builtins with a value as the receiver
1028  // requires boxing.
1029  break;
1030  }
1031  CallOptimization call_optimization(function);
1032  NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1033  cache_holder);
1034  if (call_optimization.is_simple_api_call() &&
1035  call_optimization.IsCompatibleReceiver(receiver, holder)) {
1036  return compiler.CompileLoadCallback(lookup->name(),
1037  call_optimization);
1038  }
1039  return compiler.CompileLoadViaGetter(lookup->name(), function);
1040  }
1041  // TODO(dcarney): Handle correctly.
1042  DCHECK(accessors->IsDeclaredAccessorInfo());
1043  break;
1044  }
1045 
1046  case LookupIterator::DATA: {
1047  if (lookup->is_dictionary_holder()) {
1048  if (kind() != Code::LOAD_IC) break;
1049  if (holder->IsGlobalObject()) {
1050  NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1051  cache_holder);
1052  Handle<PropertyCell> cell = lookup->GetPropertyCell();
1053  Handle<Code> code = compiler.CompileLoadGlobal(
1054  cell, lookup->name(), lookup->IsConfigurable());
1055  // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1057  Handle<Map> stub_holder_map = GetHandlerCacheHolder(
1058  *type, receiver_is_holder, isolate(), &flag);
1059  Map::UpdateCodeCache(stub_holder_map, lookup->name(), code);
1060  return code;
1061  }
1062  // There is only one shared stub for loading normalized
1063  // properties. It does not traverse the prototype chain, so the
1064  // property must be found in the object for the stub to be
1065  // applicable.
1066  if (!receiver_is_holder) break;
1067  return isolate()->builtins()->LoadIC_Normal();
1068  }
1069 
1070  // -------------- Fields --------------
1071  if (lookup->property_details().type() == FIELD) {
1072  FieldIndex field = lookup->GetFieldIndex();
1073  if (receiver_is_holder) {
1074  return SimpleFieldLoad(field);
1075  }
1076  NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1077  cache_holder);
1078  return compiler.CompileLoadField(lookup->name(), field);
1079  }
1080 
1081  // -------------- Constant properties --------------
1082  DCHECK(lookup->property_details().type() == CONSTANT);
1083  if (receiver_is_holder) {
1084  LoadConstantStub stub(isolate(), lookup->GetConstantIndex());
1085  return stub.GetCode();
1086  }
1087  NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder,
1088  cache_holder);
1089  return compiler.CompileLoadConstant(lookup->name(),
1090  lookup->GetConstantIndex());
1091  }
1092 
1093  case LookupIterator::ACCESS_CHECK:
1094  case LookupIterator::JSPROXY:
1095  case LookupIterator::NOT_FOUND:
1096  case LookupIterator::TRANSITION:
1097  UNREACHABLE();
1098  }
1099 
1100  return slow_stub();
1101 }
1102 
1103 
1105  // This helper implements a few common fast cases for converting
1106  // non-smi keys of keyed loads/stores to a smi or a string.
1107  if (key->IsHeapNumber()) {
1108  double value = Handle<HeapNumber>::cast(key)->value();
1109  if (std::isnan(value)) {
1110  key = isolate->factory()->nan_string();
1111  } else {
1112  int int_value = FastD2I(value);
1113  if (value == int_value && Smi::IsValid(int_value)) {
1114  key = Handle<Smi>(Smi::FromInt(int_value), isolate);
1115  }
1116  }
1117  } else if (key->IsUndefined()) {
1118  key = isolate->factory()->undefined_string();
1119  }
1120  return key;
1121 }
1122 
1123 
1125  Handle<Map> receiver_map(receiver->map(), isolate());
1126  MapHandleList target_receiver_maps;
1127  if (target().is_identical_to(string_stub())) {
1128  target_receiver_maps.Add(isolate()->factory()->string_map());
1129  } else {
1130  TargetMaps(&target_receiver_maps);
1131  }
1132  if (target_receiver_maps.length() == 0) {
1134  }
1135 
1136  // The first time a receiver is seen that is a transitioned version of the
1137  // previous monomorphic receiver type, assume the new ElementsKind is the
1138  // monomorphic type. This benefits global arrays that only transition
1139  // once, and all call sites accessing them are faster if they remain
1140  // monomorphic. If this optimistic assumption is not true, the IC will
1141  // miss again and it will become polymorphic and support both the
1142  // untransitioned and transitioned maps.
1144  target_receiver_maps.at(0)->elements_kind(),
1145  receiver->GetElementsKind())) {
1147  }
1148 
1149  DCHECK(state() != GENERIC);
1150 
1151  // Determine the list of receiver maps that this call site has seen,
1152  // adding the map that was just encountered.
1153  if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1154  // If the miss wasn't due to an unseen map, a polymorphic stub
1155  // won't help, use the generic stub.
1156  TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "same map added twice");
1157  return generic_stub();
1158  }
1159 
1160  // If the maximum number of receiver maps has been exceeded, use the generic
1161  // version of the IC.
1162  if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1163  TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "max polymorph exceeded");
1164  return generic_stub();
1165  }
1166 
1167  return PropertyICCompiler::ComputeKeyedLoadPolymorphic(&target_receiver_maps);
1168 }
1169 
1170 
1172  Handle<Object> key) {
1173  if (MigrateDeprecated(object)) {
1174  Handle<Object> result;
1176  isolate(), result, Runtime::GetObjectProperty(isolate(), object, key),
1177  Object);
1178  return result;
1179  }
1180 
1181  Handle<Object> load_handle;
1182  Handle<Code> stub = generic_stub();
1183 
1184  // Check for non-string values that can be converted into an
1185  // internalized string directly or is representable as a smi.
1186  key = TryConvertKey(key, isolate());
1187 
1188  if (key->IsInternalizedString() || key->IsSymbol()) {
1189  ASSIGN_RETURN_ON_EXCEPTION(isolate(), load_handle,
1190  LoadIC::Load(object, Handle<Name>::cast(key)),
1191  Object);
1192  } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
1193  if (object->IsString() && key->IsNumber()) {
1194  if (state() == UNINITIALIZED) stub = string_stub();
1195  } else if (object->IsJSObject()) {
1196  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1197  if (!Object::ToSmi(isolate(), key).is_null()) {
1198  stub = LoadElementStub(receiver);
1199  }
1200  }
1201  }
1202 
1203  if (!is_target_set()) {
1204  Code* generic = *generic_stub();
1205  if (*stub == generic) {
1206  TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
1207  }
1208  set_target(*stub);
1209  TRACE_IC("LoadIC", key);
1210  }
1211 
1212  if (!load_handle.is_null()) return load_handle;
1213  Handle<Object> result;
1215  Runtime::GetObjectProperty(isolate(), object, key),
1216  Object);
1217  return result;
1218 }
1219 
1220 
1221 bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
1222  JSReceiver::StoreFromKeyed store_mode) {
1223  // Disable ICs for non-JSObjects for now.
1224  Handle<Object> receiver = it->GetReceiver();
1225  if (!receiver->IsJSObject()) return false;
1226  DCHECK(!Handle<JSObject>::cast(receiver)->map()->is_deprecated());
1227 
1228  for (; it->IsFound(); it->Next()) {
1229  switch (it->state()) {
1230  case LookupIterator::NOT_FOUND:
1231  case LookupIterator::TRANSITION:
1232  UNREACHABLE();
1233  case LookupIterator::JSPROXY:
1234  return false;
1235  case LookupIterator::INTERCEPTOR: {
1236  Handle<JSObject> holder = it->GetHolder<JSObject>();
1237  InterceptorInfo* info = holder->GetNamedInterceptor();
1238  if (it->HolderIsReceiverOrHiddenPrototype()) {
1239  if (!info->setter()->IsUndefined()) return true;
1240  } else if (!info->getter()->IsUndefined() ||
1241  !info->query()->IsUndefined()) {
1242  return false;
1243  }
1244  break;
1245  }
1246  case LookupIterator::ACCESS_CHECK:
1247  if (it->GetHolder<JSObject>()->IsAccessCheckNeeded()) return false;
1248  break;
1250  return !it->IsReadOnly();
1251  case LookupIterator::DATA: {
1252  if (it->IsReadOnly()) return false;
1253  Handle<JSObject> holder = it->GetHolder<JSObject>();
1254  if (receiver.is_identical_to(holder)) {
1255  it->PrepareForDataProperty(value);
1256  // The previous receiver map might just have been deprecated,
1257  // so reload it.
1258  update_receiver_type(receiver);
1259  return true;
1260  }
1261 
1262  // Receiver != holder.
1263  PrototypeIterator iter(it->isolate(), receiver);
1264  if (receiver->IsJSGlobalProxy()) {
1265  return it->GetHolder<Object>().is_identical_to(
1267  }
1268 
1269  it->PrepareTransitionToDataProperty(value, NONE, store_mode);
1270  return it->IsCacheableTransition();
1271  }
1272  }
1273  }
1274 
1275  it->PrepareTransitionToDataProperty(value, NONE, store_mode);
1276  return it->IsCacheableTransition();
1277 }
1278 
1279 
1281  Handle<Object> value,
1282  JSReceiver::StoreFromKeyed store_mode) {
1283  // TODO(verwaest): Let SetProperty do the migration, since storing a property
1284  // might deprecate the current map again, if value does not fit.
1285  if (MigrateDeprecated(object) || object->IsJSProxy()) {
1286  Handle<Object> result;
1288  isolate(), result,
1289  Object::SetProperty(object, name, value, strict_mode()), Object);
1290  return result;
1291  }
1292 
1293  // If the object is undefined or null it's illegal to try to set any
1294  // properties on it; throw a TypeError in that case.
1295  if (object->IsUndefined() || object->IsNull()) {
1296  return TypeError("non_object_property_store", object, name);
1297  }
1298 
1299  // Check if the given name is an array index.
1300  uint32_t index;
1301  if (name->AsArrayIndex(&index)) {
1302  // Ignore other stores where the receiver is not a JSObject.
1303  // TODO(1475): Must check prototype chains of object wrappers.
1304  if (!object->IsJSObject()) return value;
1305  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1306 
1307  Handle<Object> result;
1309  isolate(), result,
1310  JSObject::SetElement(receiver, index, value, NONE, strict_mode()),
1311  Object);
1312  return value;
1313  }
1314 
1315  // Observed objects are always modified through the runtime.
1316  if (object->IsHeapObject() &&
1317  Handle<HeapObject>::cast(object)->map()->is_observed()) {
1318  Handle<Object> result;
1320  isolate(), result,
1321  Object::SetProperty(object, name, value, strict_mode(), store_mode),
1322  Object);
1323  return result;
1324  }
1325 
1326  LookupIterator it(object, name);
1327  if (FLAG_use_ic) UpdateCaches(&it, value, store_mode);
1328 
1329  // Set the property.
1330  Handle<Object> result;
1332  isolate(), result,
1333  Object::SetProperty(&it, value, strict_mode(), store_mode), Object);
1334  return result;
1335 }
1336 
1337 
1339  CallICState::CallType call_type) {
1340  CallICStub stub(isolate, CallICState(argc, call_type));
1341  Handle<Code> code = stub.GetCode();
1342  return code;
1343 }
1344 
1345 
1347  StrictMode strict_mode) {
1349  Handle<Code> ic =
1351  return ic;
1352 }
1353 
1354 
1356  if (kind() == Code::STORE_IC) {
1358  extra_ic_state());
1359  } else {
1360  DCHECK(kind() == Code::KEYED_STORE_IC);
1361  if (strict_mode() == STRICT) {
1362  return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
1363  } else {
1364  return isolate()->builtins()->KeyedStoreIC_Generic();
1365  }
1366  }
1367 }
1368 
1369 
1371  if (kind() == Code::STORE_IC) {
1373  extra_ic_state());
1374  } else {
1375  DCHECK(kind() == Code::KEYED_STORE_IC);
1376  if (strict_mode() == STRICT) {
1377  return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
1378  } else {
1379  return isolate()->builtins()->KeyedStoreIC_Generic();
1380  }
1381  }
1382 }
1383 
1384 
1386  if (kind() == Code::STORE_IC) {
1387  return isolate()->builtins()->StoreIC_Slow();
1388  } else {
1389  DCHECK(kind() == Code::KEYED_STORE_IC);
1390  return isolate()->builtins()->KeyedStoreIC_Slow();
1391  }
1392 }
1393 
1394 
1396  StrictMode strict_mode) {
1399 }
1400 
1401 
1402 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value,
1403  JSReceiver::StoreFromKeyed store_mode) {
1404  if (state() == UNINITIALIZED) {
1405  // This is the first time we execute this inline cache. Set the target to
1406  // the pre monomorphic stub to delay setting the monomorphic state.
1408  TRACE_IC("StoreIC", lookup->name());
1409  return;
1410  }
1411 
1412  bool use_ic = LookupForWrite(lookup, value, store_mode);
1413  if (!use_ic) {
1414  TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'");
1415  }
1416  Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub();
1417 
1418  PatchCache(lookup->name(), code);
1419  TRACE_IC("StoreIC", lookup->name());
1420 }
1421 
1422 
1423 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup,
1424  Handle<Object> value,
1425  CacheHolderFlag cache_holder) {
1426  DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
1427 
1428  // This is currently guaranteed by checks in StoreIC::Store.
1429  Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver());
1430  Handle<JSObject> holder = lookup->GetHolder<JSObject>();
1431  DCHECK(!receiver->IsAccessCheckNeeded());
1432 
1433  switch (lookup->state()) {
1434  case LookupIterator::TRANSITION: {
1435  Handle<Map> transition = lookup->transition_map();
1436  // Currently not handled by CompileStoreTransition.
1437  if (!holder->HasFastProperties()) {
1438  TRACE_GENERIC_IC(isolate(), "StoreIC", "transition from slow");
1439  break;
1440  }
1441 
1442  DCHECK(lookup->IsCacheableTransition());
1443  NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1444  return compiler.CompileStoreTransition(transition, lookup->name());
1445  }
1446 
1447  case LookupIterator::INTERCEPTOR: {
1448  DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined());
1449  NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1450  return compiler.CompileStoreInterceptor(lookup->name());
1451  }
1452 
1453  case LookupIterator::ACCESSOR: {
1454  if (!holder->HasFastProperties()) {
1455  TRACE_GENERIC_IC(isolate(), "StoreIC", "accessor on slow map");
1456  break;
1457  }
1458  Handle<Object> accessors = lookup->GetAccessors();
1459  if (accessors->IsExecutableAccessorInfo()) {
1462  if (v8::ToCData<Address>(info->setter()) == 0) {
1463  TRACE_GENERIC_IC(isolate(), "StoreIC", "setter == 0");
1464  break;
1465  }
1467  isolate(), info, receiver_type())) {
1468  TRACE_GENERIC_IC(isolate(), "StoreIC", "incompatible receiver type");
1469  break;
1470  }
1471  NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1472  return compiler.CompileStoreCallback(receiver, lookup->name(), info);
1473  } else if (accessors->IsAccessorPair()) {
1474  Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(),
1475  isolate());
1476  if (!setter->IsJSFunction()) {
1477  TRACE_GENERIC_IC(isolate(), "StoreIC", "setter not a function");
1478  break;
1479  }
1480  Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
1481  CallOptimization call_optimization(function);
1482  NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1483  if (call_optimization.is_simple_api_call() &&
1484  call_optimization.IsCompatibleReceiver(receiver, holder)) {
1485  return compiler.CompileStoreCallback(receiver, lookup->name(),
1486  call_optimization);
1487  }
1488  return compiler.CompileStoreViaSetter(receiver, lookup->name(),
1489  Handle<JSFunction>::cast(setter));
1490  }
1491  // TODO(dcarney): Handle correctly.
1492  DCHECK(accessors->IsDeclaredAccessorInfo());
1493  TRACE_GENERIC_IC(isolate(), "StoreIC", "declared accessor info");
1494  break;
1495  }
1496 
1497  case LookupIterator::DATA: {
1498  if (lookup->is_dictionary_holder()) {
1499  if (holder->IsGlobalObject()) {
1500  Handle<PropertyCell> cell = lookup->GetPropertyCell();
1501  Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
1502  StoreGlobalStub stub(isolate(), union_type->IsConstant(),
1503  receiver->IsJSGlobalProxy());
1505  Handle<GlobalObject>::cast(holder), cell);
1506  // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1507  HeapObject::UpdateMapCodeCache(receiver, lookup->name(), code);
1508  return code;
1509  }
1510  DCHECK(holder.is_identical_to(receiver));
1511  return isolate()->builtins()->StoreIC_Normal();
1512  }
1513 
1514  // -------------- Fields --------------
1515  if (lookup->property_details().type() == FIELD) {
1516  bool use_stub = true;
1517  if (lookup->representation().IsHeapObject()) {
1518  // Only use a generic stub if no types need to be tracked.
1519  Handle<HeapType> field_type = lookup->GetFieldType();
1520  HeapType::Iterator<Map> it = field_type->Classes();
1521  use_stub = it.Done();
1522  }
1523  if (use_stub) {
1524  StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
1525  lookup->representation());
1526  return stub.GetCode();
1527  }
1528  NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder);
1529  return compiler.CompileStoreField(lookup);
1530  }
1531 
1532  // -------------- Constant properties --------------
1533  DCHECK(lookup->property_details().type() == CONSTANT);
1534  TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property");
1535  break;
1536  }
1537 
1538  case LookupIterator::ACCESS_CHECK:
1539  case LookupIterator::JSPROXY:
1540  case LookupIterator::NOT_FOUND:
1541  UNREACHABLE();
1542  }
1543  return slow_stub();
1544 }
1545 
1546 
1548  KeyedAccessStoreMode store_mode) {
1549  // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1550  // via megamorphic stubs, since they don't have a map in their relocation info
1551  // and so the stubs can't be harvested for the object needed for a map check.
1552  if (target()->type() != Code::NORMAL) {
1553  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type");
1554  return generic_stub();
1555  }
1556 
1557  Handle<Map> receiver_map(receiver->map(), isolate());
1558  MapHandleList target_receiver_maps;
1559  TargetMaps(&target_receiver_maps);
1560  if (target_receiver_maps.length() == 0) {
1561  Handle<Map> monomorphic_map =
1562  ComputeTransitionedMap(receiver_map, store_mode);
1563  store_mode = GetNonTransitioningStoreMode(store_mode);
1565  monomorphic_map, strict_mode(), store_mode);
1566  }
1567 
1568  // There are several special cases where an IC that is MONOMORPHIC can still
1569  // transition to a different GetNonTransitioningStoreMode IC that handles a
1570  // superset of the original IC. Handle those here if the receiver map hasn't
1571  // changed or it has transitioned to a more general kind.
1572  KeyedAccessStoreMode old_store_mode =
1574  Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1575  if (state() == MONOMORPHIC) {
1576  Handle<Map> transitioned_receiver_map = receiver_map;
1577  if (IsTransitionStoreMode(store_mode)) {
1578  transitioned_receiver_map =
1579  ComputeTransitionedMap(receiver_map, store_mode);
1580  }
1581  if ((receiver_map.is_identical_to(previous_receiver_map) &&
1582  IsTransitionStoreMode(store_mode)) ||
1583  IsTransitionOfMonomorphicTarget(*previous_receiver_map,
1584  *transitioned_receiver_map)) {
1585  // If the "old" and "new" maps are in the same elements map family, or
1586  // if they at least come from the same origin for a transitioning store,
1587  // stay MONOMORPHIC and use the map for the most generic ElementsKind.
1588  store_mode = GetNonTransitioningStoreMode(store_mode);
1590  transitioned_receiver_map, strict_mode(), store_mode);
1591  } else if (*previous_receiver_map == receiver->map() &&
1592  old_store_mode == STANDARD_STORE &&
1593  (store_mode == STORE_AND_GROW_NO_TRANSITION ||
1595  store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1596  // A "normal" IC that handles stores can switch to a version that can
1597  // grow at the end of the array, handle OOB accesses or copy COW arrays
1598  // and still stay MONOMORPHIC.
1600  receiver_map, strict_mode(), store_mode);
1601  }
1602  }
1603 
1604  DCHECK(state() != GENERIC);
1605 
1606  bool map_added =
1607  AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1608 
1609  if (IsTransitionStoreMode(store_mode)) {
1610  Handle<Map> transitioned_receiver_map =
1611  ComputeTransitionedMap(receiver_map, store_mode);
1612  map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
1613  transitioned_receiver_map);
1614  }
1615 
1616  if (!map_added) {
1617  // If the miss wasn't due to an unseen map, a polymorphic stub
1618  // won't help, use the generic stub.
1619  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "same map added twice");
1620  return generic_stub();
1621  }
1622 
1623  // If the maximum number of receiver maps has been exceeded, use the generic
1624  // version of the IC.
1625  if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1626  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "max polymorph exceeded");
1627  return generic_stub();
1628  }
1629 
1630  // Make sure all polymorphic handlers have the same store mode, otherwise the
1631  // generic stub must be used.
1632  store_mode = GetNonTransitioningStoreMode(store_mode);
1633  if (old_store_mode != STANDARD_STORE) {
1634  if (store_mode == STANDARD_STORE) {
1635  store_mode = old_store_mode;
1636  } else if (store_mode != old_store_mode) {
1637  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "store mode mismatch");
1638  return generic_stub();
1639  }
1640  }
1641 
1642  // If the store mode isn't the standard mode, make sure that all polymorphic
1643  // receivers are either external arrays, or all "normal" arrays. Otherwise,
1644  // use the generic stub.
1645  if (store_mode != STANDARD_STORE) {
1646  int external_arrays = 0;
1647  for (int i = 0; i < target_receiver_maps.length(); ++i) {
1648  if (target_receiver_maps[i]->has_external_array_elements() ||
1649  target_receiver_maps[i]->has_fixed_typed_array_elements()) {
1650  external_arrays++;
1651  }
1652  }
1653  if (external_arrays != 0 &&
1654  external_arrays != target_receiver_maps.length()) {
1655  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
1656  "unsupported combination of external and normal arrays");
1657  return generic_stub();
1658  }
1659  }
1660 
1662  &target_receiver_maps, store_mode, strict_mode());
1663 }
1664 
1665 
1667  Handle<Map> map, KeyedAccessStoreMode store_mode) {
1668  switch (store_mode) {
1686  DCHECK(map->has_external_array_elements());
1687  // Fall through
1689  case STANDARD_STORE:
1691  return map;
1692  }
1693  UNREACHABLE();
1694  return MaybeHandle<Map>().ToHandleChecked();
1695 }
1696 
1697 
1698 bool IsOutOfBoundsAccess(Handle<JSObject> receiver, int index) {
1699  if (receiver->IsJSArray()) {
1700  return JSArray::cast(*receiver)->length()->IsSmi() &&
1701  index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
1702  }
1703  return index >= receiver->elements()->length();
1704 }
1705 
1706 
1708  Handle<Object> key,
1709  Handle<Object> value) {
1710  Handle<Smi> smi_key = Object::ToSmi(isolate(), key).ToHandleChecked();
1711  int index = smi_key->value();
1712  bool oob_access = IsOutOfBoundsAccess(receiver, index);
1713  // Don't consider this a growing store if the store would send the receiver to
1714  // dictionary mode.
1715  bool allow_growth = receiver->IsJSArray() && oob_access &&
1716  !receiver->WouldConvertToSlowElements(key);
1717  if (allow_growth) {
1718  // Handle growing array in stub if necessary.
1719  if (receiver->HasFastSmiElements()) {
1720  if (value->IsHeapNumber()) {
1721  if (receiver->HasFastHoleyElements()) {
1723  } else {
1725  }
1726  }
1727  if (value->IsHeapObject()) {
1728  if (receiver->HasFastHoleyElements()) {
1730  } else {
1732  }
1733  }
1734  } else if (receiver->HasFastDoubleElements()) {
1735  if (!value->IsSmi() && !value->IsHeapNumber()) {
1736  if (receiver->HasFastHoleyElements()) {
1738  } else {
1740  }
1741  }
1742  }
1744  } else {
1745  // Handle only in-bounds elements accesses.
1746  if (receiver->HasFastSmiElements()) {
1747  if (value->IsHeapNumber()) {
1748  if (receiver->HasFastHoleyElements()) {
1750  } else {
1752  }
1753  } else if (value->IsHeapObject()) {
1754  if (receiver->HasFastHoleyElements()) {
1756  } else {
1758  }
1759  }
1760  } else if (receiver->HasFastDoubleElements()) {
1761  if (!value->IsSmi() && !value->IsHeapNumber()) {
1762  if (receiver->HasFastHoleyElements()) {
1764  } else {
1766  }
1767  }
1768  }
1769  if (!FLAG_trace_external_array_abuse &&
1770  receiver->map()->has_external_array_elements() && oob_access) {
1772  }
1773  Heap* heap = receiver->GetHeap();
1774  if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
1776  } else {
1777  return STANDARD_STORE;
1778  }
1779  }
1780 }
1781 
1782 
1784  Handle<Object> key,
1785  Handle<Object> value) {
1786  // TODO(verwaest): Let SetProperty do the migration, since storing a property
1787  // might deprecate the current map again, if value does not fit.
1788  if (MigrateDeprecated(object)) {
1789  Handle<Object> result;
1791  isolate(), result, Runtime::SetObjectProperty(isolate(), object, key,
1792  value, strict_mode()),
1793  Object);
1794  return result;
1795  }
1796 
1797  // Check for non-string values that can be converted into an
1798  // internalized string directly or is representable as a smi.
1799  key = TryConvertKey(key, isolate());
1800 
1801  Handle<Object> store_handle;
1802  Handle<Code> stub = generic_stub();
1803 
1804  if (key->IsInternalizedString()) {
1806  isolate(), store_handle,
1807  StoreIC::Store(object, Handle<String>::cast(key), value,
1809  Object);
1810  // TODO(jkummerow): Ideally we'd wrap this in "if (!is_target_set())",
1811  // but doing so causes Hydrogen crashes. Needs investigation.
1812  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC",
1813  "unhandled internalized string key");
1814  TRACE_IC("StoreIC", key);
1815  set_target(*stub);
1816  return store_handle;
1817  }
1818 
1819  bool use_ic =
1820  FLAG_use_ic && !object->IsStringWrapper() &&
1821  !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() &&
1822  !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed());
1823  if (use_ic && !object->IsSmi()) {
1824  // Don't use ICs for maps of the objects in Array's prototype chain. We
1825  // expect to be able to trap element sets to objects with those maps in
1826  // the runtime to enable optimization of element hole access.
1827  Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
1828  if (heap_object->map()->IsMapInArrayPrototypeChain()) {
1829  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "map in array prototype");
1830  use_ic = false;
1831  }
1832  }
1833 
1834  if (use_ic) {
1835  DCHECK(!object->IsAccessCheckNeeded());
1836 
1837  if (object->IsJSObject()) {
1838  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1839  bool key_is_smi_like = !Object::ToSmi(isolate(), key).is_null();
1840  if (receiver->elements()->map() ==
1841  isolate()->heap()->sloppy_arguments_elements_map()) {
1842  if (strict_mode() == SLOPPY) {
1843  stub = sloppy_arguments_stub();
1844  } else {
1845  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver");
1846  }
1847  } else if (key_is_smi_like &&
1848  !(target().is_identical_to(sloppy_arguments_stub()))) {
1849  // We should go generic if receiver isn't a dictionary, but our
1850  // prototype chain does have dictionary elements. This ensures that
1851  // other non-dictionary receivers in the polymorphic case benefit
1852  // from fast path keyed stores.
1853  if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) {
1854  KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value);
1855  stub = StoreElementStub(receiver, store_mode);
1856  } else {
1857  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "dictionary prototype");
1858  }
1859  } else {
1860  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key");
1861  }
1862  } else {
1863  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver");
1864  }
1865  }
1866 
1867  if (store_handle.is_null()) {
1869  isolate(), store_handle,
1870  Runtime::SetObjectProperty(isolate(), object, key, value,
1871  strict_mode()),
1872  Object);
1873  }
1874 
1875  DCHECK(!is_target_set());
1876  Code* generic = *generic_stub();
1877  if (*stub == generic) {
1878  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
1879  }
1880  if (*stub == *slow_stub()) {
1881  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub");
1882  }
1883  DCHECK(!stub.is_null());
1884  set_target(*stub);
1885  TRACE_IC("StoreIC", key);
1886 
1887  return store_handle;
1888 }
1889 
1890 
1893  Handle<Smi> slot, const CallICState& state) {
1894  DCHECK(FLAG_use_ic && function->IsJSFunction());
1895 
1896  // Are we the array function?
1897  Handle<JSFunction> array_function =
1898  Handle<JSFunction>(isolate()->native_context()->array_function());
1899  if (array_function.is_identical_to(Handle<JSFunction>::cast(function))) {
1900  // Alter the slot.
1901  IC::State old_state = FeedbackToState(vector, slot);
1902  Object* feedback = vector->get(slot->value());
1903  if (!feedback->IsAllocationSite()) {
1904  Handle<AllocationSite> new_site =
1905  isolate()->factory()->NewAllocationSite();
1906  vector->set(slot->value(), *new_site);
1907  }
1908 
1909  CallIC_ArrayStub stub(isolate(), state);
1910  set_target(*stub.GetCode());
1912  if (array_function->shared()->name()->IsString()) {
1913  name = Handle<String>(String::cast(array_function->shared()->name()),
1914  isolate());
1915  }
1916 
1917  IC::State new_state = FeedbackToState(vector, slot);
1918  OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
1919  TRACE_VECTOR_IC("CallIC (custom handler)", name, old_state, new_state);
1920  return true;
1921  }
1922  return false;
1923 }
1924 
1925 
1928  Handle<Smi> slot) {
1929  CallICState state(target()->extra_ic_state());
1930  IC::State old_state = FeedbackToState(vector, slot);
1931 
1932  // We are going generic.
1933  vector->set(slot->value(),
1936 
1937  CallICStub stub(isolate(), state);
1938  Handle<Code> code = stub.GetCode();
1939  set_target(*code);
1940 
1941  Handle<Object> name = isolate()->factory()->empty_string();
1942  if (function->IsJSFunction()) {
1943  Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
1944  name = handle(js_function->shared()->name(), isolate());
1945  }
1946 
1947  IC::State new_state = FeedbackToState(vector, slot);
1948  OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
1949  TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
1950 }
1951 
1952 
1954  Handle<TypeFeedbackVector> vector, Handle<Smi> slot) {
1955  CallICState state(target()->extra_ic_state());
1956  IC::State old_state = FeedbackToState(vector, slot);
1957  Handle<Object> name = isolate()->factory()->empty_string();
1958  Object* feedback = vector->get(slot->value());
1959 
1960  // Hand-coded MISS handling is easier if CallIC slots don't contain smis.
1961  DCHECK(!feedback->IsSmi());
1962 
1963  if (feedback->IsJSFunction() || !function->IsJSFunction()) {
1964  // We are going generic.
1965  vector->set(slot->value(),
1968  } else {
1969  // The feedback is either uninitialized or an allocation site.
1970  // It might be an allocation site because if we re-compile the full code
1971  // to add deoptimization support, we call with the default call-ic, and
1972  // merely need to patch the target to match the feedback.
1973  // TODO(mvstanton): the better approach is to dispense with patching
1974  // altogether, which is in progress.
1976  feedback->IsAllocationSite());
1977 
1978  // Do we want to install a custom handler?
1979  if (FLAG_use_ic &&
1980  DoCustomHandler(receiver, function, vector, slot, state)) {
1981  return;
1982  }
1983 
1984  vector->set(slot->value(), *function);
1985  }
1986 
1987  if (function->IsJSFunction()) {
1988  Handle<JSFunction> js_function = Handle<JSFunction>::cast(function);
1989  name = handle(js_function->shared()->name(), isolate());
1990  }
1991 
1992  IC::State new_state = FeedbackToState(vector, slot);
1993  OnTypeFeedbackChanged(isolate(), address(), old_state, new_state, true);
1994  TRACE_VECTOR_IC("CallIC", name, old_state, new_state);
1995 }
1996 
1997 
1998 #undef TRACE_IC
1999 
2000 
2001 // ----------------------------------------------------------------------------
2002 // Static IC stub generators.
2003 //
2004 
2005 // Used from ic-<arch>.cc.
2006 RUNTIME_FUNCTION(CallIC_Miss) {
2007  TimerEventScope<TimerEventIcMiss> timer(isolate);
2008  HandleScope scope(isolate);
2009  DCHECK(args.length() == 4);
2010  CallIC ic(isolate);
2011  Handle<Object> receiver = args.at<Object>(0);
2012  Handle<Object> function = args.at<Object>(1);
2013  Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
2014  Handle<Smi> slot = args.at<Smi>(3);
2015  ic.HandleMiss(receiver, function, vector, slot);
2016  return *function;
2017 }
2018 
2019 
2020 RUNTIME_FUNCTION(CallIC_Customization_Miss) {
2021  TimerEventScope<TimerEventIcMiss> timer(isolate);
2022  HandleScope scope(isolate);
2023  DCHECK(args.length() == 4);
2024  // A miss on a custom call ic always results in going megamorphic.
2025  CallIC ic(isolate);
2026  Handle<Object> function = args.at<Object>(1);
2027  Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2);
2028  Handle<Smi> slot = args.at<Smi>(3);
2029  ic.PatchMegamorphic(function, vector, slot);
2030  return *function;
2031 }
2032 
2033 
2034 // Used from ic-<arch>.cc.
2035 RUNTIME_FUNCTION(LoadIC_Miss) {
2036  TimerEventScope<TimerEventIcMiss> timer(isolate);
2037  HandleScope scope(isolate);
2038  DCHECK(args.length() == 2);
2039  LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2040  Handle<Object> receiver = args.at<Object>(0);
2041  Handle<Name> key = args.at<Name>(1);
2042  ic.UpdateState(receiver, key);
2043  Handle<Object> result;
2044  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
2045  return *result;
2046 }
2047 
2048 
2049 // Used from ic-<arch>.cc
2050 RUNTIME_FUNCTION(KeyedLoadIC_Miss) {
2051  TimerEventScope<TimerEventIcMiss> timer(isolate);
2052  HandleScope scope(isolate);
2053  DCHECK(args.length() == 2);
2054  KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2055  Handle<Object> receiver = args.at<Object>(0);
2056  Handle<Object> key = args.at<Object>(1);
2057  ic.UpdateState(receiver, key);
2058  Handle<Object> result;
2059  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
2060  return *result;
2061 }
2062 
2063 
2064 RUNTIME_FUNCTION(KeyedLoadIC_MissFromStubFailure) {
2065  TimerEventScope<TimerEventIcMiss> timer(isolate);
2066  HandleScope scope(isolate);
2067  DCHECK(args.length() == 2);
2068  KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
2069  Handle<Object> receiver = args.at<Object>(0);
2070  Handle<Object> key = args.at<Object>(1);
2071  ic.UpdateState(receiver, key);
2072  Handle<Object> result;
2073  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
2074  return *result;
2075 }
2076 
2077 
2078 // Used from ic-<arch>.cc.
2079 RUNTIME_FUNCTION(StoreIC_Miss) {
2080  TimerEventScope<TimerEventIcMiss> timer(isolate);
2081  HandleScope scope(isolate);
2082  DCHECK(args.length() == 3);
2083  StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2084  Handle<Object> receiver = args.at<Object>(0);
2085  Handle<String> key = args.at<String>(1);
2086  ic.UpdateState(receiver, key);
2087  Handle<Object> result;
2089  isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
2090  return *result;
2091 }
2092 
2093 
2094 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) {
2095  TimerEventScope<TimerEventIcMiss> timer(isolate);
2096  HandleScope scope(isolate);
2097  DCHECK(args.length() == 3);
2098  StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2099  Handle<Object> receiver = args.at<Object>(0);
2100  Handle<String> key = args.at<String>(1);
2101  ic.UpdateState(receiver, key);
2102  Handle<Object> result;
2104  isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
2105  return *result;
2106 }
2107 
2108 
2109 // Extend storage is called in a store inline cache when
2110 // it is necessary to extend the properties array of a
2111 // JSObject.
2112 RUNTIME_FUNCTION(SharedStoreIC_ExtendStorage) {
2113  TimerEventScope<TimerEventIcMiss> timer(isolate);
2114  HandleScope shs(isolate);
2115  DCHECK(args.length() == 3);
2116 
2117  // Convert the parameters
2118  Handle<JSObject> object = args.at<JSObject>(0);
2119  Handle<Map> transition = args.at<Map>(1);
2120  Handle<Object> value = args.at<Object>(2);
2121 
2122  // Check the object has run out out property space.
2123  DCHECK(object->HasFastProperties());
2124  DCHECK(object->map()->unused_property_fields() == 0);
2125 
2126  JSObject::MigrateToNewProperty(object, transition, value);
2127 
2128  // Return the stored value.
2129  return *value;
2130 }
2131 
2132 
2133 // Used from ic-<arch>.cc.
2134 RUNTIME_FUNCTION(KeyedStoreIC_Miss) {
2135  TimerEventScope<TimerEventIcMiss> timer(isolate);
2136  HandleScope scope(isolate);
2137  DCHECK(args.length() == 3);
2138  KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2139  Handle<Object> receiver = args.at<Object>(0);
2140  Handle<Object> key = args.at<Object>(1);
2141  ic.UpdateState(receiver, key);
2142  Handle<Object> result;
2144  isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
2145  return *result;
2146 }
2147 
2148 
2149 RUNTIME_FUNCTION(KeyedStoreIC_MissFromStubFailure) {
2150  TimerEventScope<TimerEventIcMiss> timer(isolate);
2151  HandleScope scope(isolate);
2152  DCHECK(args.length() == 3);
2153  KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2154  Handle<Object> receiver = args.at<Object>(0);
2155  Handle<Object> key = args.at<Object>(1);
2156  ic.UpdateState(receiver, key);
2157  Handle<Object> result;
2159  isolate, result, ic.Store(receiver, key, args.at<Object>(2)));
2160  return *result;
2161 }
2162 
2163 
2164 RUNTIME_FUNCTION(StoreIC_Slow) {
2165  HandleScope scope(isolate);
2166  DCHECK(args.length() == 3);
2167  StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2168  Handle<Object> object = args.at<Object>(0);
2169  Handle<Object> key = args.at<Object>(1);
2170  Handle<Object> value = args.at<Object>(2);
2171  StrictMode strict_mode = ic.strict_mode();
2172  Handle<Object> result;
2174  isolate, result,
2175  Runtime::SetObjectProperty(isolate, object, key, value, strict_mode));
2176  return *result;
2177 }
2178 
2179 
2180 RUNTIME_FUNCTION(KeyedStoreIC_Slow) {
2181  HandleScope scope(isolate);
2182  DCHECK(args.length() == 3);
2183  KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2184  Handle<Object> object = args.at<Object>(0);
2185  Handle<Object> key = args.at<Object>(1);
2186  Handle<Object> value = args.at<Object>(2);
2187  StrictMode strict_mode = ic.strict_mode();
2188  Handle<Object> result;
2190  isolate, result,
2191  Runtime::SetObjectProperty(isolate, object, key, value, strict_mode));
2192  return *result;
2193 }
2194 
2195 
2196 RUNTIME_FUNCTION(ElementsTransitionAndStoreIC_Miss) {
2197  TimerEventScope<TimerEventIcMiss> timer(isolate);
2198  HandleScope scope(isolate);
2199  DCHECK(args.length() == 4);
2200  KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2201  Handle<Object> value = args.at<Object>(0);
2202  Handle<Map> map = args.at<Map>(1);
2203  Handle<Object> key = args.at<Object>(2);
2204  Handle<Object> object = args.at<Object>(3);
2205  StrictMode strict_mode = ic.strict_mode();
2206  if (object->IsJSObject()) {
2208  map->elements_kind());
2209  }
2210  Handle<Object> result;
2212  isolate, result,
2213  Runtime::SetObjectProperty(isolate, object, key, value, strict_mode));
2214  return *result;
2215 }
2216 
2217 
2219  Handle<AllocationSite> allocation_site, Handle<Object> left,
2220  Handle<Object> right) {
2221  BinaryOpICState state(isolate(), target()->extra_ic_state());
2222 
2223  // Compute the actual result using the builtin for the binary operation.
2224  Object* builtin = isolate()->js_builtins_object()->javascript_builtin(
2225  TokenToJSBuiltin(state.op()));
2226  Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate());
2227  Handle<Object> result;
2229  isolate(), result, Execution::Call(isolate(), function, left, 1, &right),
2230  Object);
2231 
2232  // Execution::Call can execute arbitrary JavaScript, hence potentially
2233  // update the state of this very IC, so we must update the stored state.
2234  UpdateTarget();
2235  // Compute the new state.
2236  BinaryOpICState old_state(isolate(), target()->extra_ic_state());
2237  state.Update(left, right, result);
2238 
2239  // Check if we have a string operation here.
2241  if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) {
2242  // Setup the allocation site on-demand.
2243  if (allocation_site.is_null()) {
2244  allocation_site = isolate()->factory()->NewAllocationSite();
2245  }
2246 
2247  // Install the stub with an allocation site.
2248  BinaryOpICWithAllocationSiteStub stub(isolate(), state);
2249  target = stub.GetCodeCopyFromTemplate(allocation_site);
2250 
2251  // Sanity check the trampoline stub.
2252  DCHECK_EQ(*allocation_site, target->FindFirstAllocationSite());
2253  } else {
2254  // Install the generic stub.
2255  BinaryOpICStub stub(isolate(), state);
2256  target = stub.GetCode();
2257 
2258  // Sanity check the generic stub.
2259  DCHECK_EQ(NULL, target->FindFirstAllocationSite());
2260  }
2261  set_target(*target);
2262 
2263  if (FLAG_trace_ic) {
2264  OFStream os(stdout);
2265  os << "[BinaryOpIC" << old_state << " => " << state << " @ "
2266  << static_cast<void*>(*target) << " <- ";
2267  JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2268  if (!allocation_site.is_null()) {
2269  os << " using allocation site " << static_cast<void*>(*allocation_site);
2270  }
2271  os << "]" << endl;
2272  }
2273 
2274  // Patch the inlined smi code as necessary.
2275  if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) {
2277  } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) {
2279  }
2280 
2281  return result;
2282 }
2283 
2284 
2285 RUNTIME_FUNCTION(BinaryOpIC_Miss) {
2286  TimerEventScope<TimerEventIcMiss> timer(isolate);
2287  HandleScope scope(isolate);
2288  DCHECK_EQ(2, args.length());
2289  Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft);
2290  Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight);
2291  BinaryOpIC ic(isolate);
2292  Handle<Object> result;
2294  isolate, result,
2295  ic.Transition(Handle<AllocationSite>::null(), left, right));
2296  return *result;
2297 }
2298 
2299 
2300 RUNTIME_FUNCTION(BinaryOpIC_MissWithAllocationSite) {
2301  TimerEventScope<TimerEventIcMiss> timer(isolate);
2302  HandleScope scope(isolate);
2303  DCHECK_EQ(3, args.length());
2304  Handle<AllocationSite> allocation_site =
2305  args.at<AllocationSite>(BinaryOpWithAllocationSiteStub::kAllocationSite);
2306  Handle<Object> left = args.at<Object>(BinaryOpWithAllocationSiteStub::kLeft);
2307  Handle<Object> right =
2308  args.at<Object>(BinaryOpWithAllocationSiteStub::kRight);
2309  BinaryOpIC ic(isolate);
2310  Handle<Object> result;
2312  isolate, result, ic.Transition(allocation_site, left, right));
2313  return *result;
2314 }
2315 
2316 
2321  Code* code = NULL;
2322  CHECK(stub.FindCodeInCache(&code));
2323  return code;
2324 }
2325 
2326 
2331  return stub.GetCode();
2332 }
2333 
2334 
2336  HandleScope scope(isolate());
2337  CompareICStub old_stub(target()->stub_key(), isolate());
2338  CompareICState::State new_left =
2339  CompareICState::NewInputState(old_stub.left(), x);
2340  CompareICState::State new_right =
2341  CompareICState::NewInputState(old_stub.right(), y);
2343  old_stub.state(), old_stub.left(), old_stub.right(), op_,
2344  HasInlinedSmiCode(address()), x, y);
2345  CompareICStub stub(isolate(), op_, new_left, new_right, state);
2347  stub.set_known_map(
2349  }
2350  Handle<Code> new_target = stub.GetCode();
2351  set_target(*new_target);
2352 
2353  if (FLAG_trace_ic) {
2354  PrintF("[CompareIC in ");
2355  JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2356  PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
2357  CompareICState::GetStateName(old_stub.left()),
2358  CompareICState::GetStateName(old_stub.right()),
2359  CompareICState::GetStateName(old_stub.state()),
2360  CompareICState::GetStateName(new_left),
2361  CompareICState::GetStateName(new_right),
2363  static_cast<void*>(*stub.GetCode()));
2364  }
2365 
2366  // Activate inlined smi code.
2367  if (old_stub.state() == CompareICState::UNINITIALIZED) {
2369  }
2370 
2371  return *new_target;
2372 }
2373 
2374 
2375 // Used from CompareICStub::GenerateMiss in code-stubs-<arch>.cc.
2376 RUNTIME_FUNCTION(CompareIC_Miss) {
2377  TimerEventScope<TimerEventIcMiss> timer(isolate);
2378  HandleScope scope(isolate);
2379  DCHECK(args.length() == 3);
2380  CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2381  return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2382 }
2383 
2384 
2385 void CompareNilIC::Clear(Address address, Code* target,
2386  ConstantPoolArray* constant_pool) {
2387  if (IsCleared(target)) return;
2388  ExtraICState state = target->extra_ic_state();
2389 
2390  CompareNilICStub stub(target->GetIsolate(), state,
2392  stub.ClearState();
2393 
2394  Code* code = NULL;
2395  CHECK(stub.FindCodeInCache(&code));
2396 
2398 }
2399 
2400 
2402  Handle<Object> object) {
2403  if (object->IsNull() || object->IsUndefined()) {
2404  return handle(Smi::FromInt(true), isolate);
2405  }
2406  return handle(Smi::FromInt(object->IsUndetectableObject()), isolate);
2407 }
2408 
2409 
2411  ExtraICState extra_ic_state = target()->extra_ic_state();
2412 
2414 
2415  // Extract the current supported types from the patched IC and calculate what
2416  // types must be supported as a result of the miss.
2417  bool already_monomorphic = stub.IsMonomorphic();
2418 
2419  stub.UpdateStatus(object);
2420 
2421  NilValue nil = stub.nil_value();
2422 
2423  // Find or create the specialized stub to support the new set of types.
2424  Handle<Code> code;
2425  if (stub.IsMonomorphic()) {
2426  Handle<Map> monomorphic_map(already_monomorphic && FirstTargetMap() != NULL
2427  ? FirstTargetMap()
2428  : HeapObject::cast(*object)->map());
2429  code = PropertyICCompiler::ComputeCompareNil(monomorphic_map, &stub);
2430  } else {
2431  code = stub.GetCode();
2432  }
2433  set_target(*code);
2434  return DoCompareNilSlow(isolate(), nil, object);
2435 }
2436 
2437 
2438 RUNTIME_FUNCTION(CompareNilIC_Miss) {
2439  TimerEventScope<TimerEventIcMiss> timer(isolate);
2440  HandleScope scope(isolate);
2441  Handle<Object> object = args.at<Object>(0);
2442  CompareNilIC ic(isolate);
2443  return *ic.CompareNil(object);
2444 }
2445 
2446 
2447 RUNTIME_FUNCTION(Unreachable) {
2448  UNREACHABLE();
2449  CHECK(false);
2450  return isolate->heap()->undefined_value();
2451 }
2452 
2453 
2455  switch (op) {
2456  default:
2457  UNREACHABLE();
2458  case Token::ADD:
2459  return Builtins::ADD;
2460  break;
2461  case Token::SUB:
2462  return Builtins::SUB;
2463  break;
2464  case Token::MUL:
2465  return Builtins::MUL;
2466  break;
2467  case Token::DIV:
2468  return Builtins::DIV;
2469  break;
2470  case Token::MOD:
2471  return Builtins::MOD;
2472  break;
2473  case Token::BIT_OR:
2474  return Builtins::BIT_OR;
2475  break;
2476  case Token::BIT_AND:
2477  return Builtins::BIT_AND;
2478  break;
2479  case Token::BIT_XOR:
2480  return Builtins::BIT_XOR;
2481  break;
2482  case Token::SAR:
2483  return Builtins::SAR;
2484  break;
2485  case Token::SHR:
2486  return Builtins::SHR;
2487  break;
2488  case Token::SHL:
2489  return Builtins::SHL;
2490  break;
2491  }
2492 }
2493 
2494 
2497  bool to_boolean_value = stub.UpdateStatus(object);
2498  Handle<Code> code = stub.GetCode();
2499  set_target(*code);
2500  return handle(Smi::FromInt(to_boolean_value ? 1 : 0), isolate());
2501 }
2502 
2503 
2504 RUNTIME_FUNCTION(ToBooleanIC_Miss) {
2505  TimerEventScope<TimerEventIcMiss> timer(isolate);
2506  DCHECK(args.length() == 1);
2507  HandleScope scope(isolate);
2508  Handle<Object> object = args.at<Object>(0);
2509  ToBooleanIC ic(isolate);
2510  return *ic.ToBoolean(object);
2511 }
2512 
2513 
2514 RUNTIME_FUNCTION(StoreCallbackProperty) {
2515  Handle<JSObject> receiver = args.at<JSObject>(0);
2516  Handle<JSObject> holder = args.at<JSObject>(1);
2518  Handle<Name> name = args.at<Name>(3);
2519  Handle<Object> value = args.at<Object>(4);
2520  HandleScope scope(isolate);
2521 
2522  DCHECK(callback->IsCompatibleReceiver(*receiver));
2523 
2524  Address setter_address = v8::ToCData<Address>(callback->setter());
2526  FUNCTION_CAST<v8::AccessorNameSetterCallback>(setter_address);
2527  DCHECK(fun != NULL);
2528 
2529  LOG(isolate, ApiNamedPropertyAccess("store", *receiver, *name));
2530  PropertyCallbackArguments custom_args(isolate, callback->data(), *receiver,
2531  *holder);
2532  custom_args.Call(fun, v8::Utils::ToLocal(name), v8::Utils::ToLocal(value));
2534  return *value;
2535 }
2536 
2537 
2538 /**
2539  * Attempts to load a property with an interceptor (which must be present),
2540  * but doesn't search the prototype chain.
2541  *
2542  * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't
2543  * provide any value for the given name.
2544  */
2545 RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) {
2547  Handle<Name> name_handle =
2549  Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(
2551 
2552  // TODO(rossberg): Support symbols in the API.
2553  if (name_handle->IsSymbol())
2554  return isolate->heap()->no_interceptor_result_sentinel();
2555  Handle<String> name = Handle<String>::cast(name_handle);
2556 
2557  Address getter_address = v8::ToCData<Address>(interceptor_info->getter());
2559  FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address);
2560  DCHECK(getter != NULL);
2561 
2562  Handle<JSObject> receiver =
2564  Handle<JSObject> holder =
2566  PropertyCallbackArguments callback_args(isolate, interceptor_info->data(),
2567  *receiver, *holder);
2568  {
2569  // Use the interceptor getter.
2570  HandleScope scope(isolate);
2572  callback_args.Call(getter, v8::Utils::ToLocal(name));
2574  if (!r.IsEmpty()) {
2576  result->VerifyApiCallResultType();
2577  return *v8::Utils::OpenHandle(*r);
2578  }
2579  }
2580 
2581  return isolate->heap()->no_interceptor_result_sentinel();
2582 }
2583 
2584 
2586  // If the load is non-contextual, just return the undefined result.
2587  // Note that both keyed and non-keyed loads may end up here.
2588  HandleScope scope(isolate);
2589  LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
2590  if (ic.contextual_mode() != CONTEXTUAL) {
2591  return isolate->heap()->undefined_value();
2592  }
2593 
2594  // Throw a reference error.
2595  Handle<Name> name_handle(name);
2597  isolate, NewReferenceError("not_defined", HandleVector(&name_handle, 1)));
2598 }
2599 
2600 
2601 /**
2602  * Loads a property with an interceptor performing post interceptor
2603  * lookup if interceptor failed.
2604  */
2605 RUNTIME_FUNCTION(LoadPropertyWithInterceptor) {
2606  HandleScope scope(isolate);
2608  Handle<Name> name =
2610  Handle<JSObject> receiver =
2612  Handle<JSObject> holder =
2614 
2615  Handle<Object> result;
2616  LookupIterator it(receiver, name, holder);
2617  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2618  JSObject::GetProperty(&it));
2619 
2620  if (it.IsFound()) return *result;
2621 
2622  return ThrowReferenceError(isolate, Name::cast(args[0]));
2623 }
2624 
2625 
2626 RUNTIME_FUNCTION(StorePropertyWithInterceptor) {
2627  HandleScope scope(isolate);
2628  DCHECK(args.length() == 3);
2629  StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2630  Handle<JSObject> receiver = args.at<JSObject>(0);
2631  Handle<Name> name = args.at<Name>(1);
2632  Handle<Object> value = args.at<Object>(2);
2633 #ifdef DEBUG
2634  PrototypeIterator iter(isolate, receiver,
2636  bool found = false;
2637  while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
2639  if (current->IsJSObject() &&
2640  Handle<JSObject>::cast(current)->HasNamedInterceptor()) {
2641  found = true;
2642  break;
2643  }
2644  }
2645  DCHECK(found);
2646 #endif
2647  Handle<Object> result;
2649  isolate, result,
2650  JSObject::SetProperty(receiver, name, value, ic.strict_mode()));
2651  return *result;
2652 }
2653 
2654 
2655 RUNTIME_FUNCTION(LoadElementWithInterceptor) {
2656  HandleScope scope(isolate);
2657  Handle<JSObject> receiver = args.at<JSObject>(0);
2658  DCHECK(args.smi_at(1) >= 0);
2659  uint32_t index = args.smi_at(1);
2660  Handle<Object> result;
2662  isolate, result,
2663  JSObject::GetElementWithInterceptor(receiver, receiver, index));
2664  return *result;
2665 }
2666 
2667 
2668 RUNTIME_FUNCTION(VectorLoadIC_MissFromStubFailure) {
2669  // TODO(mvstanton): To be enabled when ICs can accept a vector and slot
2670  return NULL;
2671 }
2672 
2673 
2674 RUNTIME_FUNCTION(VectorKeyedLoadIC_MissFromStubFailure) {
2675  // TODO(mvstanton): To be enabled when ICs can accept a vector and slot
2676  return NULL;
2677 }
2678 
2679 
2680 static const Address IC_utilities[] = {
2681 #define ADDR(name) FUNCTION_ADDR(name),
2683 #undef ADDR
2684 };
2685 
2686 
2688 }
2689 } // namespace v8::internal
bool IsEmpty() const
Returns true if the handle is empty.
Definition: v8.h:228
A single JavaScript stack frame.
Definition: v8.h:1358
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition: api.h:288
static bool IsCompatibleReceiverType(Isolate *isolate, Handle< AccessorInfo > info, Handle< HeapType > type)
Definition: objects.cc:467
MaybeHandle< Object > Transition(Handle< AllocationSite > allocation_site, Handle< Object > left, Handle< Object > right) WARN_UNUSED_RESULT
Definition: ic.cc:2218
static Builtins::JavaScript TokenToJSBuiltin(Token::Value op)
Definition: ic.cc:2454
void PatchMegamorphic(Handle< Object > function, Handle< TypeFeedbackVector > vector, Handle< Smi > slot)
Definition: ic.cc:1926
bool DoCustomHandler(Handle< Object > receiver, Handle< Object > function, Handle< TypeFeedbackVector > vector, Handle< Smi > slot, const CallICState &state)
Definition: ic.cc:1891
static void Clear(Isolate *isolate, Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic.cc:521
static Handle< Code > initialize_stub(Isolate *isolate, int argc, CallICState::CallType call_type)
Definition: ic.cc:1338
IC::State FeedbackToState(Handle< TypeFeedbackVector > vector, Handle< Smi > slot) const
Definition: ic-inl.h:211
void HandleMiss(Handle< Object > receiver, Handle< Object > function, Handle< TypeFeedbackVector > vector, Handle< Smi > slot)
Definition: ic.cc:1953
void set_profiler_ticks(int ticks)
Definition: objects-inl.h:4781
ExtraICState extra_ic_state()
Definition: objects-inl.h:4647
bool is_inline_cache_stub()
Definition: objects-inl.h:4921
int instruction_size() const
byte * instruction_start()
Definition: objects-inl.h:6176
void mark_as_invalidated_weak_stub()
Definition: objects-inl.h:4913
InlineCacheState ic_state()
Definition: objects-inl.h:4635
static CacheHolderFlag ExtractCacheHolderFromFlags(Flags flags)
Definition: objects-inl.h:5001
Object * type_feedback_info()
Definition: objects-inl.h:6145
static const char * GetStateName(CompareICState::State state)
Definition: ic-state.cc:457
static State NewInputState(State old_state, Handle< Object > value)
Definition: ic-state.cc:509
static State TargetState(State old_state, State old_left, State old_right, Token::Value op, bool has_inlined_smi_code, Handle< Object > x, Handle< Object > y)
Definition: ic-state.cc:552
void set_known_map(Handle< Map > map)
Definition: code-stubs.h:1264
CompareICState::State state() const
Definition: code-stubs.h:1278
Token::Value op() const
Definition: code-stubs.h:1268
CompareICState::State left() const
Definition: code-stubs.h:1272
CompareICState::State right() const
Definition: code-stubs.h:1275
static bool HasInlinedSmiCode(Address address)
Code * UpdateCaches(Handle< Object > x, Handle< Object > y)
Definition: ic.cc:2335
static Handle< Code > GetUninitialized(Isolate *isolate, Token::Value op)
Definition: ic.cc:2327
Token::Value op_
Definition: ic.h:641
static void Clear(Isolate *isolate, Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic.cc:555
static Code * GetRawUninitialized(Isolate *isolate, Token::Value op)
Definition: ic.cc:2317
void UpdateStatus(Handle< Object > object)
Definition: code-stubs.cc:433
static Handle< Object > DoCompareNilSlow(Isolate *isolate, NilValue nil, Handle< Object > object)
Definition: ic.cc:2401
Handle< Object > CompareNil(Handle< Object > object)
Definition: ic.cc:2410
static void Clear(Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic.cc:2385
static void FlushICache(void *start, size_t size)
static bool HasDebugInfo(Handle< SharedFunctionInfo > shared)
Definition: debug.cc:1062
static Handle< DebugInfo > GetDebugInfo(Handle< SharedFunctionInfo > shared)
Definition: debug.cc:1069
static const int kCallerPCOffset
Definition: frames-arm.h:98
static const int kConstantPoolOffset
Definition: frames-arm.h:90
static const int kCallerFPOffset
Definition: frames-arm.h:96
static Handle< T > cast(Handle< S > that)
Definition: handles.h:116
bool is_null() const
Definition: handles.h:124
static void UpdateMapCodeCache(Handle< HeapObject > object, Handle< Name > name, Handle< Code > code)
Definition: objects.cc:4158
Isolate * GetIsolate() const
Definition: objects-inl.h:1387
static void PostPatching(Address address, Code *target, Code *old_target)
Definition: ic.cc:422
MaybeHandle< Object > TypeError(const char *type, Handle< Object > object, Handle< Object > key)
Definition: ic.cc:340
State state_
Definition: ic.h:264
MaybeHandle< Code > maybe_handler_
Definition: ic.h:267
void update_receiver_type(Handle< Object > receiver)
Definition: ic.h:204
Code * GetOriginalCode() const
Definition: ic.cc:209
static Address AddressFromUtilityId(UtilityId id)
Definition: ic.cc:2687
static void SetTargetAtAddress(Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic-inl.h:96
static Handle< Map > TypeToMap(HeapType *type, Isolate *isolate)
Definition: ic.cc:719
Handle< HeapType > receiver_type()
Definition: ic.h:203
Code::Kind kind() const
Definition: ic.h:185
void UpdateTarget()
Definition: ic-inl.h:158
bool IsNameCompatibleWithPrototypeFailure(Handle< Object > name)
Definition: ic.cc:303
static Code * GetTargetAtAddress(Address address, ConstantPoolArray *constant_pool)
Definition: ic-inl.h:84
bool is_target_set()
Definition: ic.h:147
State state() const
Definition: ic.h:66
void UpdateState(Handle< Object > receiver, Handle< Object > name)
Definition: ic.cc:315
Handle< Code > target_
Definition: ic.h:262
ConstantPoolArray * constant_pool() const
Definition: ic-inl.h:51
MaybeHandle< Object > ReferenceError(const char *type, Handle< Name > name)
Definition: ic.cc:348
Handle< ConstantPoolArray > raw_constant_pool_
Definition: ic.h:259
void TargetTypes(TypeHandleList *list)
Definition: ic.h:215
void MarkPrototypeFailure(Handle< Object > name)
Definition: ic.h:73
static T::TypeHandle MapToType(Handle< Map > map, typename T::Region *region)
Definition: ic.cc:733
Isolate * isolate() const
Definition: ic.h:136
ExtraICState extra_ic_state_
Definition: ic.h:269
SharedFunctionInfo * GetSharedFunctionInfo() const
Definition: ic.cc:187
bool IsTransitionOfMonomorphicTarget(Map *source_map, Map *target_map)
Definition: ic.cc:772
IC(FrameDepth depth, Isolate *isolate)
Definition: ic.cc:141
void TargetMaps(MapHandleList *list)
Definition: ic.h:208
static void Clear(Isolate *isolate, Address address, ConstantPoolArray *constant_pool)
Definition: ic.cc:478
virtual Handle< Code > CompileHandler(LookupIterator *lookup, Handle< Object > value, CacheHolderFlag cache_holder)
Definition: ic.h:171
void UpdateMonomorphicIC(Handle< Code > handler, Handle< Name > name)
Definition: ic.cc:753
Code * raw_target() const
Definition: ic-inl.h:154
Code::Kind kind_
Definition: ic.h:265
void PatchCache(Handle< Name > name, Handle< Code > code)
Definition: ic.cc:787
void CopyICToMegamorphicCache(Handle< Name > name)
Definition: ic.cc:761
Address fp_
Definition: ic.h:247
Map * FirstTargetMap()
Definition: ic.h:222
Address * pc_address_
Definition: ic.h:253
ExtraICState extra_ic_state() const
Definition: ic.h:200
Address address() const
Definition: ic-inl.h:19
char TransitionMarkFromState(IC::State state)
Definition: ic.cc:25
@ NO_EXTRA_FRAME
Definition: ic.h:59
@ EXTRA_CALL_FRAME
Definition: ic.h:59
Handle< Code > target() const
Definition: ic.h:132
void set_target(Code *code)
Definition: ic-inl.h:121
static void OnTypeFeedbackChanged(Isolate *isolate, Address address, State old_state, State new_state, bool target_remains_ic_stub)
Definition: ic.cc:392
bool UpdatePolymorphicIC(Handle< Name > name, Handle< Code > code)
Definition: ic.cc:649
static Handle< HeapType > CurrentTypeOf(Handle< Object > object, Isolate *isolate)
Definition: ic.cc:712
static bool IsCleared(Code *code)
Definition: ic.h:112
static Handle< Map > GetHandlerCacheHolder(HeapType *type, bool receiver_is_holder, Isolate *isolate, CacheHolderFlag *flag)
Definition: ic-inl.h:177
Address pc() const
Definition: ic.h:135
void UpdateMegamorphicCache(HeapType *type, Name *name, Code *code)
Definition: ic.cc:890
bool TryRemoveInvalidPrototypeDependentStub(Handle< Object > receiver, Handle< String > name)
Definition: ic.cc:251
static Handle< Map > GetICCacheHolder(HeapType *type, Isolate *isolate, CacheHolderFlag *flag)
Definition: ic-inl.h:198
static void RegisterWeakMapDependency(Handle< Code > stub)
Definition: ic.cc:442
Code * GetCode() const
Definition: ic.cc:201
virtual Handle< Code > megamorphic_stub()
Definition: ic.h:192
void TraceIC(const char *type, Handle< Object > name)
Definition: ic.cc:90
static void InvalidateMaps(Code *stub)
Definition: ic.cc:460
Address fp() const
Definition: ic.h:134
Handle< Code > ComputeHandler(LookupIterator *lookup, Handle< Object > value=Handle< Code >::null())
Definition: ic.cc:897
InnerPointerToCodeCacheEntry * GetCacheEntry(Address inner_pointer)
Definition: frames.cc:1502
StubCache * stub_cache()
Definition: isolate.h:875
static Address c_entry_fp(ThreadLocalTop *thread)
Definition: isolate.h:647
RuntimeProfiler * runtime_profiler()
Definition: isolate.h:864
Builtins * builtins()
Definition: isolate.h:947
Handle< JSBuiltinsObject > js_builtins_object()
Definition: isolate.h:679
InnerPointerToCodeCache * inner_pointer_to_code_cache()
Definition: isolate.h:911
ThreadLocalTop * thread_local_top()
Definition: isolate.h:878
Factory * factory()
Definition: isolate.h:982
static MUST_USE_RESULT MaybeHandle< Object > GetElementWithInterceptor(Handle< JSObject > object, Handle< Object > receiver, uint32_t index)
Definition: objects.cc:12839
static void MigrateToNewProperty(Handle< JSObject > object, Handle< Map > transition, Handle< Object > value)
Definition: objects.cc:3756
static void TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:12706
static MUST_USE_RESULT MaybeHandle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, bool check_prototype=true, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:12336
static void MigrateInstance(Handle< JSObject > instance)
Definition: objects.cc:3728
static void PrintTop(Isolate *isolate, FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:811
static JavaScriptFrame * cast(StackFrame *frame)
Definition: frames.h:612
JSFunction * function() const
Definition: frames-inl.h:265
static void PrintFunctionAndOffset(JSFunction *function, Code *code, Address pc, FILE *file, bool print_line_number)
Definition: frames.cc:781
MUST_USE_RESULT MaybeHandle< Object > Load(Handle< Object > object, Handle< Object > key)
Definition: ic.cc:1171
static void Clear(Isolate *isolate, Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic.cc:511
Handle< Code > LoadElementStub(Handle< JSObject > receiver)
Definition: ic.cc:1124
Handle< Code > string_stub()
Definition: ic.h:436
Handle< Code > generic_stub() const
Definition: ic.h:435
virtual Handle< Code > pre_monomorphic_stub() const
Definition: ic.h:430
MUST_USE_RESULT MaybeHandle< Object > Store(Handle< Object > object, Handle< Object > name, Handle< Object > value)
Definition: ic.cc:1783
static KeyedAccessStoreMode GetKeyedAccessStoreMode(ExtraICState extra_state)
Definition: ic.h:543
void set_target(Code *code)
Definition: ic-inl.h:147
Handle< Code > sloppy_arguments_stub()
Definition: ic.h:586
KeyedAccessStoreMode GetStoreMode(Handle< JSObject > receiver, Handle< Object > key, Handle< Object > value)
Definition: ic.cc:1707
Handle< Map > ComputeTransitionedMap(Handle< Map > map, KeyedAccessStoreMode store_mode)
Definition: ic.cc:1666
virtual Handle< Code > pre_monomorphic_stub() const
Definition: ic.h:567
Handle< Code > StoreElementStub(Handle< JSObject > receiver, KeyedAccessStoreMode store_mode)
Definition: ic.cc:1547
static void Clear(Isolate *isolate, Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic.cc:545
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:17
void Set(int index, const T &element)
Definition: list-inl.h:85
T & at(int i) const
Definition: list.h:69
void UpdateCaches(LookupIterator *lookup)
Definition: ic.cc:859
void set_target(Code *code)
Definition: ic-inl.h:130
static Handle< Code > initialize_stub(Isolate *isolate, ExtraICState extra_state)
Definition: ic.cc:815
MUST_USE_RESULT MaybeHandle< Object > Load(Handle< Object > object, Handle< Name > name)
Definition: ic.cc:586
Handle< Code > SimpleFieldLoad(FieldIndex index)
Definition: ic.cc:853
Handle< Code > slow_stub() const
Definition: ic.h:365
virtual Handle< Code > megamorphic_stub() OVERRIDE
Definition: ic.cc:821
ContextualMode contextual_mode() const
Definition: ic.h:328
virtual Handle< Code > CompileHandler(LookupIterator *lookup, Handle< Object > unused, CacheHolderFlag cache_holder)
Definition: ic.cc:947
static void Clear(Isolate *isolate, Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic.cc:527
virtual Handle< Code > pre_monomorphic_stub() const
Definition: ic.cc:843
bool IsUndeclaredGlobal(Handle< Object > receiver)
Definition: ic.h:338
ElementsKind elements_kind()
Definition: objects.h:5730
static void UpdateCodeCache(Handle< Map > map, Handle< Name > name, Handle< Code > code)
Definition: objects.cc:7030
Map * LookupElementsTransitionMap(ElementsKind elements_kind)
Definition: objects.cc:3273
static Handle< Map > TransitionElementsTo(Handle< Map > map, ElementsKind to_kind)
Definition: objects.cc:3321
static void AddDependentIC(Handle< Map > map, Handle< Code > stub)
Definition: objects.cc:11367
static Object *& Object_at(Address addr)
Definition: v8memory.h:60
static Address & Address_at(Address addr)
Definition: v8memory.h:56
bool Equals(Name *other)
Definition: objects-inl.h:3309
static Handle< Code > ComputeLoadNonexistent(Handle< Name > name, Handle< HeapType > type)
Handle< Code > CompileLoadCallback(Handle< Name > name, Handle< ExecutableAccessorInfo > callback)
Handle< Code > CompileLoadGlobal(Handle< PropertyCell > cell, Handle< Name > name, bool is_configurable)
Handle< Code > CompileLoadField(Handle< Name > name, FieldIndex index)
Handle< Code > CompileLoadInterceptor(LookupIterator *it)
Handle< Code > CompileLoadViaGetter(Handle< Name > name, Handle< JSFunction > getter)
Handle< Code > CompileLoadConstant(Handle< Name > name, int constant_index)
Handle< Code > CompileStoreInterceptor(Handle< Name > name)
Handle< Code > CompileStoreViaSetter(Handle< JSObject > object, Handle< Name > name, Handle< JSFunction > setter)
Handle< Code > CompileStoreCallback(Handle< JSObject > object, Handle< Name > name, Handle< ExecutableAccessorInfo > callback)
Handle< Code > CompileStoreField(LookupIterator *it)
Handle< Code > CompileStoreTransition(Handle< Map > transition, Handle< Name > name)
static MUST_USE_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it)
Definition: objects.cc:109
static MUST_USE_RESULT MaybeHandle< Smi > ToSmi(Isolate *isolate, Handle< Object > object)
Definition: objects-inl.h:1081
static MUST_USE_RESULT MaybeHandle< Object > SetProperty(Handle< Object > object, Handle< Name > key, Handle< Object > value, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:2798
static Handle< HeapType > UpdatedType(Handle< PropertyCell > cell, Handle< Object > value)
Definition: objects.cc:16348
static Handle< Code > Find(Handle< Name > name, Handle< Map > map, Code::Kind kind, CacheHolderFlag cache_holder, Code::StubType type)
static Handle< Code > ComputeKeyedLoadMonomorphic(Handle< Map > receiver_map)
Definition: ic-compiler.cc:86
static Handle< Code > ComputeMonomorphic(Code::Kind kind, Handle< Name > name, Handle< HeapType > type, Handle< Code > handler, ExtraICState extra_ic_state)
Definition: ic-compiler.cc:49
static Handle< Code > ComputePolymorphic(Code::Kind kind, TypeHandleList *types, CodeHandleList *handlers, int number_of_valid_maps, Handle< Name > name, ExtraICState extra_ic_state)
Definition: ic-compiler.cc:272
static Handle< Code > ComputeLoad(Isolate *isolate, InlineCacheState ic_state, ExtraICState extra_state)
Definition: ic-compiler.cc:170
static Handle< Code > ComputeKeyedStorePolymorphic(MapHandleList *receiver_maps, KeyedAccessStoreMode store_mode, StrictMode strict_mode)
Definition: ic-compiler.cc:283
static Handle< Code > ComputeCompareNil(Handle< Map > receiver_map, CompareNilICStub *stub)
Definition: ic-compiler.cc:221
static Handle< Code > ComputeStore(Isolate *isolate, InlineCacheState ic_state, ExtraICState extra_state)
Definition: ic-compiler.cc:193
static Code * FindPreMonomorphic(Isolate *isolate, Code::Kind kind, ExtraICState extra_ic_state)
Definition: ic-compiler.cc:149
static Handle< Code > ComputeKeyedLoadPolymorphic(MapHandleList *receiver_maps)
Definition: ic-compiler.cc:244
static Handle< Code > ComputeKeyedStoreMonomorphic(Handle< Map > receiver_map, StrictMode strict_mode, KeyedAccessStoreMode store_mode)
Definition: ic-compiler.cc:120
A class to uniformly access the prototype of any Object and walk its prototype chain.
Definition: prototype.h:25
Object * GetCurrent() const
Definition: prototype.h:62
static int ModeMask(Mode mode)
Definition: assembler.h:445
static MUST_USE_RESULT MaybeHandle< Object > SetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key, Handle< Object > value, StrictMode strict_mode)
Definition: runtime.cc:2181
static MUST_USE_RESULT MaybeHandle< Object > GetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key)
Definition: runtime.cc:1912
static MUST_USE_RESULT MaybeHandle< Object > GetElementOrCharAt(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: runtime.cc:1850
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
static bool IsValid(intptr_t value)
Definition: objects-inl.h:1334
StackFrame * frame() const
Definition: frames.h:842
static const int kConstantPoolOffset
Definition: frames.h:163
static const int kCallerPCOffset
Definition: frames.h:166
static const int kCallerFPOffset
Definition: frames.h:165
Handle< Code > GetCodeCopyFromTemplate(Handle< GlobalObject > global, Handle< PropertyCell > cell)
Definition: code-stubs.h:1013
void UpdateCaches(LookupIterator *lookup, Handle< Object > value, JSReceiver::StoreFromKeyed store_mode)
Definition: ic.cc:1402
Handle< Code > generic_stub() const
Definition: ic.cc:1370
void set_target(Code *code)
Definition: ic-inl.h:139
static StrictMode GetStrictMode(ExtraICState state)
Definition: ic.h:453
virtual Handle< Code > pre_monomorphic_stub() const
Definition: ic.h:499
StrictMode strict_mode() const
Definition: ic.h:465
static Handle< Code > initialize_stub(Isolate *isolate, StrictMode strict_mode)
Definition: ic.cc:1346
virtual Handle< Code > megamorphic_stub() OVERRIDE
Definition: ic.cc:1355
static ExtraICState ComputeExtraICState(StrictMode flag)
Definition: ic.h:450
Handle< Code > slow_stub() const
Definition: ic.cc:1385
bool LookupForWrite(LookupIterator *it, Handle< Object > value, JSReceiver::StoreFromKeyed store_mode)
Definition: ic.cc:1221
MUST_USE_RESULT MaybeHandle< Object > Store(Handle< Object > object, Handle< Name > name, Handle< Object > value, JSReceiver::StoreFromKeyed store_mode=JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED)
Definition: ic.cc:1280
static void Clear(Isolate *isolate, Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic.cc:536
virtual Handle< Code > CompileHandler(LookupIterator *lookup, Handle< Object > value, CacheHolderFlag cache_holder)
Definition: ic.cc:1423
static const int kLengthOffset
Definition: objects.h:8802
Code * Get(Name *name, Map *map, Code::Flags flags)
Definition: stub-cache.cc:77
Code * Set(Name *name, Map *map, Code *code)
Definition: stub-cache.cc:48
Handle< Object > ToBoolean(Handle< Object > object)
Definition: ic.cc:2495
bool UpdateStatus(Handle< Object > object)
Definition: code-stubs.cc:836
static const char * Name(Value tok)
Definition: token.h:180
void change_ic_generic_count(int delta)
Definition: objects-inl.h:7044
void change_ic_with_type_info_count(int delta)
Definition: objects-inl.h:7022
static Handle< Object > UninitializedSentinel(Isolate *isolate)
static Handle< Object > MegamorphicSentinel(Isolate *isolate)
i::Handle< i::Map > Map()
Definition: types.h:719
i::Handle< i::Object > Value()
Definition: types.h:750
static TypeHandle NowOf(i::Object *value, Region *region)
Definition: types-inl.h:30
ConstantType * AsConstant()
Definition: types.h:443
bool Is(TypeImpl *that)
Definition: types.h:390
static TypeHandle Constant(i::Handle< i::Object > value, Region *region)
Definition: types.h:330
ClassType * AsClass()
Definition: types.h:442
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in name
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define TRACE_GENERIC_IC(isolate, type, reason)
Definition: ic.cc:79
#define ADDR(name)
#define TRACE_IC(type, name)
Definition: ic.cc:137
#define TRACE_VECTOR_IC(type, name, old_state, new_state)
Definition: ic.cc:138
#define IC_UTIL_LIST(ICU)
Definition: ic.h:17
#define RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate)
Definition: isolate.h:101
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition: isolate.h:131
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
Definition: isolate.h:146
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call, T)
Definition: isolate.h:135
#define THROW_NEW_ERROR(isolate, call, T)
Definition: isolate.h:138
#define LOG(isolate, Call)
Definition: log.h:69
#define UNREACHABLE()
Definition: logging.h:30
#define CHECK(condition)
Definition: logging.h:36
#define DCHECK_NE(v1, v2)
Definition: logging.h:207
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
@ SKIP_WRITE_BARRIER
Definition: objects.h:235
static void LookupForRead(LookupIterator *it)
Definition: ic.cc:219
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
@ DISABLE_INLINED_SMI_CHECK
Definition: ic.h:672
@ ENABLE_INLINED_SMI_CHECK
Definition: ic.h:672
bool IsOutOfBoundsAccess(Handle< JSObject > receiver, int index)
Definition: ic.cc:1698
static KeyedAccessStoreMode GetNonTransitioningStoreMode(KeyedAccessStoreMode store_mode)
Definition: objects.h:216
KeyedAccessStoreMode
Definition: objects.h:153
@ STORE_AND_GROW_TRANSITION_HOLEY_DOUBLE_TO_OBJECT
Definition: objects.h:167
@ STORE_TRANSITION_HOLEY_SMI_TO_OBJECT
Definition: objects.h:158
@ STORE_TRANSITION_DOUBLE_TO_OBJECT
Definition: objects.h:157
@ STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE
Definition: objects.h:166
@ STORE_AND_GROW_NO_TRANSITION
Definition: objects.h:161
@ STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE
Definition: objects.h:163
@ STORE_AND_GROW_TRANSITION_DOUBLE_TO_OBJECT
Definition: objects.h:164
@ STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS
Definition: objects.h:168
@ STORE_NO_TRANSITION_HANDLE_COW
Definition: objects.h:169
@ STORE_TRANSITION_HOLEY_SMI_TO_DOUBLE
Definition: objects.h:159
@ STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT
Definition: objects.h:160
@ STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT
Definition: objects.h:162
@ STORE_TRANSITION_SMI_TO_DOUBLE
Definition: objects.h:156
@ STORE_TRANSITION_SMI_TO_OBJECT
Definition: objects.h:155
@ STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_OBJECT
Definition: objects.h:165
@ STANDARD_STORE
Definition: objects.h:154
static bool IsTransitionStoreMode(KeyedAccessStoreMode store_mode)
Definition: objects.h:209
OStream & endl(OStream &os)
Definition: ostreams.cc:112
@ ODDBALL_TYPE
Definition: objects.h:663
@ HEAP_NUMBER_TYPE
Definition: objects.h:669
@ FAST_HOLEY_DOUBLE_ELEMENTS
Definition: elements-kind.h:27
@ kCacheOnPrototype
Definition: globals.h:485
@ kCacheOnReceiver
Definition: globals.h:488
@ kCacheOnPrototypeReceiverIsDictionary
Definition: globals.h:486
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
static bool AddOneReceiverMapIfMissing(MapHandleList *receiver_maps, Handle< Map > new_receiver_map)
Definition: ic.cc:635
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check)
static bool IsGrowStoreMode(KeyedAccessStoreMode store_mode)
Definition: objects.h:228
static Object * ThrowReferenceError(Isolate *isolate, Name *name)
Definition: ic.cc:2585
static const Address IC_utilities[]
Definition: ic.cc:2680
static bool MigrateDeprecated(Handle< Object > object)
Definition: ic.cc:577
byte * Address
Definition: globals.h:101
NilValue
Definition: v8.h:97
void PrintF(const char *format,...)
Definition: utils.cc:80
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: utils.h:1100
int FastD2I(double x)
Definition: conversions.h:57
kFeedbackVectorOffset flag
Definition: objects-inl.h:5418
const int kMaxKeyedPolymorphism
Definition: ic-state.h:14
static void ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state, int *polymorphic_delta, int *generic_delta)
Definition: ic.cc:355
const char * GetTransitionMarkModifier(KeyedAccessStoreMode mode)
Definition: ic.cc:56
@ UNINITIALIZED
Definition: globals.h:446
@ PROTOTYPE_FAILURE
Definition: globals.h:452
@ PREMONOMORPHIC
Definition: globals.h:448
static Handle< Object > TryConvertKey(Handle< Object > key, Isolate *isolate)
Definition: ic.cc:1104
@ RUNTIME_FUNCTION
Definition: serialize.h:23
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
void(* AccessorNameSetterCallback)(Local< Name > property, Local< Value > value, const PropertyCallbackInfo< void > &info)
Definition: v8.h:2257
void(* NamedPropertyGetterCallback)(Local< String > property, const PropertyCallbackInfo< Value > &info)
NamedProperty[Getter|Setter] are used as interceptors on object.
Definition: v8.h:3427
@ ACCESS_GET
Definition: v8.h:3520
@ NONE