v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ic.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "accessors.h"
31 #include "api.h"
32 #include "arguments.h"
33 #include "codegen.h"
34 #include "execution.h"
35 #include "ic-inl.h"
36 #include "runtime.h"
37 #include "stub-cache.h"
38 #include "v8conversions.h"
39 
40 namespace v8 {
41 namespace internal {
42 
43 #ifdef DEBUG
44 char IC::TransitionMarkFromState(IC::State state) {
45  switch (state) {
46  case UNINITIALIZED: return '0';
47  case PREMONOMORPHIC: return '.';
48  case MONOMORPHIC: return '1';
49  case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
50  case POLYMORPHIC: return 'P';
51  case MEGAMORPHIC: return 'N';
52  case GENERIC: return 'G';
53 
54  // We never see the debugger states here, because the state is
55  // computed from the original code - not the patched code. Let
56  // these cases fall through to the unreachable code below.
57  case DEBUG_STUB: break;
58  }
59  UNREACHABLE();
60  return 0;
61 }
62 
63 
64 const char* GetTransitionMarkModifier(KeyedAccessStoreMode mode) {
65  if (mode == STORE_NO_TRANSITION_HANDLE_COW) return ".COW";
67  return ".IGNORE_OOB";
68  }
69  if (IsGrowStoreMode(mode)) return ".GROW";
70  return "";
71 }
72 
73 
74 void IC::TraceIC(const char* type,
75  Handle<Object> name) {
76  if (FLAG_trace_ic) {
77  Code* new_target = raw_target();
78  State new_state = new_target->ic_state();
79  PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
80  StackFrameIterator it(isolate());
81  while (it.frame()->fp() != this->fp()) it.Advance();
82  StackFrame* raw_frame = it.frame();
83  if (raw_frame->is_internal()) {
84  Code* apply_builtin = isolate()->builtins()->builtin(
85  Builtins::kFunctionApply);
86  if (raw_frame->unchecked_code() == apply_builtin) {
87  PrintF("apply from ");
88  it.Advance();
89  raw_frame = it.frame();
90  }
91  }
92  JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
93  ExtraICState extra_state = new_target->extra_ic_state();
94  const char* modifier =
95  GetTransitionMarkModifier(
97  PrintF(" (%c->%c%s)",
98  TransitionMarkFromState(state()),
99  TransitionMarkFromState(new_state),
100  modifier);
101  name->Print();
102  PrintF("]\n");
103  }
104 }
105 
106 #define TRACE_GENERIC_IC(isolate, type, reason) \
107  do { \
108  if (FLAG_trace_ic) { \
109  PrintF("[%s patching generic stub in ", type); \
110  JavaScriptFrame::PrintTop(isolate, stdout, false, true); \
111  PrintF(" (%s)]\n", reason); \
112  } \
113  } while (false)
114 
115 #else
116 #define TRACE_GENERIC_IC(isolate, type, reason)
117 #endif // DEBUG
118 
119 #define TRACE_IC(type, name) \
120  ASSERT((TraceIC(type, name), true))
121 
122 IC::IC(FrameDepth depth, Isolate* isolate)
123  : isolate_(isolate),
124  target_set_(false) {
125  // To improve the performance of the (much used) IC code, we unfold a few
126  // levels of the stack frame iteration code. This yields a ~35% speedup when
127  // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
128  const Address entry =
130  Address constant_pool = NULL;
131  if (FLAG_enable_ool_constant_pool) {
132  constant_pool = Memory::Address_at(
134  }
135  Address* pc_address =
136  reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
138  // If there's another JavaScript frame on the stack or a
139  // StubFailureTrampoline, we need to look one frame further down the stack to
140  // find the frame pointer and the return address stack slot.
141  if (depth == EXTRA_CALL_FRAME) {
142  if (FLAG_enable_ool_constant_pool) {
143  constant_pool = Memory::Address_at(
145  }
146  const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
147  pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
149  }
150 #ifdef DEBUG
151  StackFrameIterator it(isolate);
152  for (int i = 0; i < depth + 1; i++) it.Advance();
153  StackFrame* frame = it.frame();
154  ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
155 #endif
156  fp_ = fp;
157  if (FLAG_enable_ool_constant_pool) {
158  raw_constant_pool_ = handle(
159  ConstantPoolArray::cast(reinterpret_cast<Object*>(constant_pool)),
160  isolate);
161  }
162  pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
163  target_ = handle(raw_target(), isolate);
164  state_ = target_->ic_state();
165  extra_ic_state_ = target_->extra_ic_state();
166 }
167 
168 
169 #ifdef ENABLE_DEBUGGER_SUPPORT
170 SharedFunctionInfo* IC::GetSharedFunctionInfo() const {
171  // Compute the JavaScript frame for the frame pointer of this IC
172  // structure. We need this to be able to find the function
173  // corresponding to the frame.
175  while (it.frame()->fp() != this->fp()) it.Advance();
176  JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
177  // Find the function on the stack and both the active code for the
178  // function and the original code.
179  JSFunction* function = frame->function();
180  return function->shared();
181 }
182 
183 
184 Code* IC::GetCode() const {
185  HandleScope scope(isolate());
186  Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate());
187  Code* code = shared->code();
188  return code;
189 }
190 
191 
192 Code* IC::GetOriginalCode() const {
193  HandleScope scope(isolate());
194  Handle<SharedFunctionInfo> shared(GetSharedFunctionInfo(), isolate());
195  ASSERT(Debug::HasDebugInfo(shared));
196  Code* original_code = Debug::GetDebugInfo(shared)->original_code();
197  ASSERT(original_code->IsCode());
198  return original_code;
199 }
200 #endif
201 
202 
203 static bool HasInterceptorGetter(JSObject* object) {
204  return !object->GetNamedInterceptor()->getter()->IsUndefined();
205 }
206 
207 
208 static bool HasInterceptorSetter(JSObject* object) {
209  return !object->GetNamedInterceptor()->setter()->IsUndefined();
210 }
211 
212 
213 static void LookupForRead(Handle<Object> object,
214  Handle<String> name,
215  LookupResult* lookup) {
216  // Skip all the objects with named interceptors, but
217  // without actual getter.
218  while (true) {
219  object->Lookup(*name, lookup);
220  // Besides normal conditions (property not found or it's not
221  // an interceptor), bail out if lookup is not cacheable: we won't
222  // be able to IC it anyway and regular lookup should work fine.
223  if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
224  return;
225  }
226 
227  Handle<JSObject> holder(lookup->holder(), lookup->isolate());
228  if (HasInterceptorGetter(*holder)) {
229  return;
230  }
231 
232  holder->LocalLookupRealNamedProperty(*name, lookup);
233  if (lookup->IsFound()) {
234  ASSERT(!lookup->IsInterceptor());
235  return;
236  }
237 
238  Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
239  if (proto->IsNull()) {
240  ASSERT(!lookup->IsFound());
241  return;
242  }
243 
244  object = proto;
245  }
246 }
247 
248 
250  Handle<String> name) {
251  if (target()->is_keyed_stub()) {
252  // Determine whether the failure is due to a name failure.
253  if (!name->IsName()) return false;
254  Name* stub_name = target()->FindFirstName();
255  if (*name != stub_name) return false;
256  }
257 
258  InlineCacheHolderFlag cache_holder =
260 
261  switch (cache_holder) {
262  case OWN_MAP:
263  // The stub was generated for JSObject but called for non-JSObject.
264  // IC::GetCodeCacheHolder is not applicable.
265  if (!receiver->IsJSObject()) return false;
266  break;
267  case PROTOTYPE_MAP:
268  // IC::GetCodeCacheHolder is not applicable.
269  if (receiver->GetPrototype(isolate())->IsNull()) return false;
270  break;
271  }
272 
274  IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map());
275 
276  // Decide whether the inline cache failed because of changes to the
277  // receiver itself or changes to one of its prototypes.
278  //
279  // If there are changes to the receiver itself, the map of the
280  // receiver will have changed and the current target will not be in
281  // the receiver map's code cache. Therefore, if the current target
282  // is in the receiver map's code cache, the inline cache failed due
283  // to prototype check failure.
284  int index = map->IndexInCodeCache(*name, *target());
285  if (index >= 0) {
286  map->RemoveFromCodeCache(*name, *target(), index);
287  // Handlers are stored in addition to the ICs on the map. Remove those, too.
288  TryRemoveInvalidHandlers(map, name);
289  return true;
290  }
291 
292  // The stub is not in the cache. We've ruled out all other kinds of failure
293  // except for proptotype chain changes, a deprecated map, a map that's
294  // different from the one that the stub expects, elements kind changes, or a
295  // constant global property that will become mutable. Threat all those
296  // situations as prototype failures (stay monomorphic if possible).
297 
298  // If the IC is shared between multiple receivers (slow dictionary mode), then
299  // the map cannot be deprecated and the stub invalidated.
300  if (cache_holder == OWN_MAP) {
301  Map* old_map = target()->FindFirstMap();
302  if (old_map == *map) return true;
303  if (old_map != NULL) {
304  if (old_map->is_deprecated()) return true;
306  map->elements_kind())) {
307  return true;
308  }
309  }
310  }
311 
312  if (receiver->IsGlobalObject()) {
313  LookupResult lookup(isolate());
314  GlobalObject* global = GlobalObject::cast(*receiver);
315  global->LocalLookupRealNamedProperty(*name, &lookup);
316  if (!lookup.IsFound()) return false;
317  PropertyCell* cell = global->GetPropertyCell(&lookup);
318  return cell->type()->IsConstant();
319  }
320 
321  return false;
322 }
323 
324 
326  CodeHandleList handlers;
327  target()->FindHandlers(&handlers);
328  for (int i = 0; i < handlers.length(); i++) {
329  Handle<Code> handler = handlers.at(i);
330  int index = map->IndexInCodeCache(*name, *handler);
331  if (index >= 0) {
332  map->RemoveFromCodeCache(*name, *handler, index);
333  return;
334  }
335  }
336 }
337 
338 
340  if (!name->IsString()) return;
341  if (state() != MONOMORPHIC) {
342  if (state() == POLYMORPHIC && receiver->IsHeapObject()) {
344  handle(Handle<HeapObject>::cast(receiver)->map()),
345  Handle<String>::cast(name));
346  }
347  return;
348  }
349  if (receiver->IsUndefined() || receiver->IsNull()) return;
350 
351  // Remove the target from the code cache if it became invalid
352  // because of changes in the prototype chain to avoid hitting it
353  // again.
355  receiver, Handle<String>::cast(name))) {
357  }
358 
359  // The builtins object is special. It only changes when JavaScript
360  // builtins are loaded lazily. It is important to keep inline
361  // caches for the builtins object monomorphic. Therefore, if we get
362  // an inline cache miss for the builtins object after lazily loading
363  // JavaScript builtins, we return uninitialized as the state to
364  // force the inline cache back to monomorphic state.
365  if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED;
366 }
367 
368 
369 Failure* IC::TypeError(const char* type,
370  Handle<Object> object,
371  Handle<Object> key) {
372  HandleScope scope(isolate());
373  Handle<Object> args[2] = { key, object };
375  type, HandleVector(args, 2));
376  return isolate()->Throw(*error);
377 }
378 
379 
380 Failure* IC::ReferenceError(const char* type, Handle<String> name) {
381  HandleScope scope(isolate());
383  type, HandleVector(&name, 1));
384  return isolate()->Throw(*error);
385 }
386 
387 
388 static int ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state) {
389  bool was_uninitialized =
390  old_state == UNINITIALIZED || old_state == PREMONOMORPHIC;
391  bool is_uninitialized =
392  new_state == UNINITIALIZED || new_state == PREMONOMORPHIC;
393  return (was_uninitialized && !is_uninitialized) ? 1 :
394  (!was_uninitialized && is_uninitialized) ? -1 : 0;
395 }
396 
397 
398 void IC::PostPatching(Address address, Code* target, Code* old_target) {
399  Isolate* isolate = target->GetHeap()->isolate();
400  Code* host = isolate->
401  inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
402  if (host->kind() != Code::FUNCTION) return;
403 
404  if (FLAG_type_info_threshold > 0 &&
405  old_target->is_inline_cache_stub() &&
406  target->is_inline_cache_stub()) {
407  int delta = ComputeTypeInfoCountDelta(old_target->ic_state(),
408  target->ic_state());
409  // Not all Code objects have TypeFeedbackInfo.
410  if (host->type_feedback_info()->IsTypeFeedbackInfo() && delta != 0) {
413  info->change_ic_with_type_info_count(delta);
414  }
415  }
416  if (host->type_feedback_info()->IsTypeFeedbackInfo()) {
420  }
421  host->set_profiler_ticks(0);
422  isolate->runtime_profiler()->NotifyICChanged();
423  // TODO(2029): When an optimized function is patched, it would
424  // be nice to propagate the corresponding type information to its
425  // unoptimized version for the benefit of later inlining.
426 }
427 
428 
429 void IC::Clear(Isolate* isolate, Address address,
430  ConstantPoolArray* constant_pool) {
431  Code* target = GetTargetAtAddress(address, constant_pool);
432 
433  // Don't clear debug break inline cache as it will remove the break point.
434  if (target->is_debug_stub()) return;
435 
436  switch (target->kind()) {
437  case Code::LOAD_IC:
438  return LoadIC::Clear(isolate, address, target, constant_pool);
439  case Code::KEYED_LOAD_IC:
440  return KeyedLoadIC::Clear(isolate, address, target, constant_pool);
441  case Code::STORE_IC:
442  return StoreIC::Clear(isolate, address, target, constant_pool);
443  case Code::KEYED_STORE_IC:
444  return KeyedStoreIC::Clear(isolate, address, target, constant_pool);
445  case Code::COMPARE_IC:
446  return CompareIC::Clear(isolate, address, target, constant_pool);
447  case Code::COMPARE_NIL_IC:
448  return CompareNilIC::Clear(address, target, constant_pool);
449  case Code::BINARY_OP_IC:
450  case Code::TO_BOOLEAN_IC:
451  // Clearing these is tricky and does not
452  // make any performance difference.
453  return;
454  default: UNREACHABLE();
455  }
456 }
457 
458 
459 void KeyedLoadIC::Clear(Isolate* isolate,
460  Address address,
461  Code* target,
462  ConstantPoolArray* constant_pool) {
463  if (IsCleared(target)) return;
464  // Make sure to also clear the map used in inline fast cases. If we
465  // do not clear these maps, cached code can keep objects alive
466  // through the embedded maps.
467  SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool);
468 }
469 
470 
471 void LoadIC::Clear(Isolate* isolate,
472  Address address,
473  Code* target,
474  ConstantPoolArray* constant_pool) {
475  if (IsCleared(target)) return;
476  Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC(
477  Code::LOAD_IC, target->extra_ic_state());
478  SetTargetAtAddress(address, code, constant_pool);
479 }
480 
481 
482 void StoreIC::Clear(Isolate* isolate,
483  Address address,
484  Code* target,
485  ConstantPoolArray* constant_pool) {
486  if (IsCleared(target)) return;
487  Code* code = target->GetIsolate()->stub_cache()->FindPreMonomorphicIC(
488  Code::STORE_IC, target->extra_ic_state());
489  SetTargetAtAddress(address, code, constant_pool);
490 }
491 
492 
493 void KeyedStoreIC::Clear(Isolate* isolate,
494  Address address,
495  Code* target,
496  ConstantPoolArray* constant_pool) {
497  if (IsCleared(target)) return;
498  SetTargetAtAddress(address,
500  isolate, StoreIC::GetStrictMode(target->extra_ic_state())),
501  constant_pool);
502 }
503 
504 
505 void CompareIC::Clear(Isolate* isolate,
506  Address address,
507  Code* target,
508  ConstantPoolArray* constant_pool) {
509  ASSERT(target->major_key() == CodeStub::CompareIC);
510  CompareIC::State handler_state;
511  Token::Value op;
512  ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL,
513  &handler_state, &op);
514  // Only clear CompareICs that can retain objects.
515  if (handler_state != KNOWN_OBJECT) return;
516  SetTargetAtAddress(address, GetRawUninitialized(isolate, op), constant_pool);
518 }
519 
520 
521 static bool MigrateDeprecated(Handle<Object> object) {
522  if (!object->IsJSObject()) return false;
523  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
524  if (!receiver->map()->is_deprecated()) return false;
525  JSObject::MigrateInstance(Handle<JSObject>::cast(object));
526  return true;
527 }
528 
529 
530 MaybeObject* LoadIC::Load(Handle<Object> object,
531  Handle<String> name) {
532  // If the object is undefined or null it's illegal to try to get any
533  // of its properties; throw a TypeError in that case.
534  if (object->IsUndefined() || object->IsNull()) {
535  return TypeError("non_object_property_load", object, name);
536  }
537 
538  if (FLAG_use_ic) {
539  // Use specialized code for getting prototype of functions.
540  if (object->IsJSFunction() &&
541  name->Equals(isolate()->heap()->prototype_string()) &&
542  Handle<JSFunction>::cast(object)->should_have_prototype()) {
543  Handle<Code> stub;
544  if (state() == UNINITIALIZED) {
545  stub = pre_monomorphic_stub();
546  } else if (state() == PREMONOMORPHIC) {
547  FunctionPrototypeStub function_prototype_stub(kind());
548  stub = function_prototype_stub.GetCode(isolate());
549  } else if (state() != MEGAMORPHIC) {
550  ASSERT(state() != GENERIC);
551  stub = megamorphic_stub();
552  }
553  if (!stub.is_null()) {
554  set_target(*stub);
555  if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
556  }
558  }
559  }
560 
561  // Check if the name is trivially convertible to an index and get
562  // the element or char if so.
563  uint32_t index;
564  if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
565  // Rewrite to the generic keyed load stub.
566  if (FLAG_use_ic) set_target(*generic_stub());
567  Handle<Object> result =
568  Runtime::GetElementOrCharAt(isolate(), object, index);
569  RETURN_IF_EMPTY_HANDLE(isolate(), result);
570  return *result;
571  }
572 
573  bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
574 
575  // Named lookup in the object.
576  LookupResult lookup(isolate());
577  LookupForRead(object, name, &lookup);
578 
579  // If we did not find a property, check if we need to throw an exception.
580  if (!lookup.IsFound()) {
581  if (IsUndeclaredGlobal(object)) {
582  return ReferenceError("not_defined", name);
583  }
584  LOG(isolate(), SuspectReadEvent(*name, *object));
585  }
586 
587  // Update inline cache and stub cache.
588  if (use_ic) UpdateCaches(&lookup, object, name);
589 
590  PropertyAttributes attr;
591  // Get the property.
592  Handle<Object> result =
593  Object::GetProperty(object, object, &lookup, name, &attr);
594  RETURN_IF_EMPTY_HANDLE(isolate(), result);
595  // If the property is not present, check if we need to throw an
596  // exception.
597  if ((lookup.IsInterceptor() || lookup.IsHandler()) &&
598  attr == ABSENT && IsUndeclaredGlobal(object)) {
599  return ReferenceError("not_defined", name);
600  }
601 
602  return *result;
603 }
604 
605 
606 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
607  Handle<Map> new_receiver_map) {
608  ASSERT(!new_receiver_map.is_null());
609  for (int current = 0; current < receiver_maps->length(); ++current) {
610  if (!receiver_maps->at(current).is_null() &&
611  receiver_maps->at(current).is_identical_to(new_receiver_map)) {
612  return false;
613  }
614  }
615  receiver_maps->Add(new_receiver_map);
616  return true;
617 }
618 
619 
621  Handle<String> name,
622  Handle<Code> code) {
623  if (!code->is_handler()) return false;
624  TypeHandleList types;
625  CodeHandleList handlers;
626 
627  target()->FindAllTypes(&types);
628  int number_of_types = types.length();
629  int deprecated_types = 0;
630  int handler_to_overwrite = -1;
631 
632  for (int i = 0; i < number_of_types; i++) {
633  Handle<HeapType> current_type = types.at(i);
634  if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) {
635  // Filter out deprecated maps to ensure their instances get migrated.
636  ++deprecated_types;
637  } else if (type->IsCurrently(current_type)) {
638  // If the receiver type is already in the polymorphic IC, this indicates
639  // there was a prototoype chain failure. In that case, just overwrite the
640  // handler.
641  handler_to_overwrite = i;
642  } else if (handler_to_overwrite == -1 &&
643  current_type->IsClass() &&
644  type->IsClass() &&
645  IsTransitionOfMonomorphicTarget(*current_type->AsClass(),
646  *type->AsClass())) {
647  handler_to_overwrite = i;
648  }
649  }
650 
651  int number_of_valid_types =
652  number_of_types - deprecated_types - (handler_to_overwrite != -1);
653 
654  if (number_of_valid_types >= 4) return false;
655  if (number_of_types == 0) return false;
656  if (!target()->FindHandlers(&handlers, types.length())) return false;
657 
658  number_of_valid_types++;
659  if (handler_to_overwrite >= 0) {
660  handlers.Set(handler_to_overwrite, code);
661  if (!type->IsCurrently(types.at(handler_to_overwrite))) {
662  types.Set(handler_to_overwrite, type);
663  }
664  } else {
665  types.Add(type);
666  handlers.Add(code);
667  }
668 
670  kind(), &types, &handlers, number_of_valid_types, name, extra_ic_state());
671  set_target(*ic);
672  return true;
673 }
674 
675 
677  return object->IsJSGlobalObject()
679  : HeapType::OfCurrently(object, isolate);
680 }
681 
682 
684  if (type->Is(HeapType::Number()))
685  return isolate->factory()->heap_number_map();
686  if (type->Is(HeapType::Boolean())) return isolate->factory()->oddball_map();
687  if (type->IsConstant()) {
689  }
690  ASSERT(type->IsClass());
691  return type->AsClass();
692 }
693 
694 
695 template <class T>
696 typename T::TypeHandle IC::MapToType(Handle<Map> map,
697  typename T::Region* region) {
698  if (map->instance_type() == HEAP_NUMBER_TYPE) {
699  return T::Number(region);
700  } else if (map->instance_type() == ODDBALL_TYPE) {
701  // The only oddballs that can be recorded in ICs are booleans.
702  return T::Boolean(region);
703  } else {
704  return T::Class(map, region);
705  }
706 }
707 
708 
709 template
710 Type* IC::MapToType<Type>(Handle<Map> map, Zone* zone);
711 
712 
713 template
714 Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, Isolate* region);
715 
716 
718  Handle<Code> handler,
719  Handle<String> name) {
720  if (!handler->is_handler()) return set_target(*handler);
722  kind(), name, type, handler, extra_ic_state());
723  set_target(*ic);
724 }
725 
726 
728  TypeHandleList types;
729  CodeHandleList handlers;
730  target()->FindAllTypes(&types);
731  if (!target()->FindHandlers(&handlers, types.length())) return;
732  for (int i = 0; i < types.length(); i++) {
733  UpdateMegamorphicCache(*types.at(i), *name, *handlers.at(i));
734  }
735 }
736 
737 
738 bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
739  if (source_map == NULL) return true;
740  if (target_map == NULL) return false;
741  ElementsKind target_elements_kind = target_map->elements_kind();
742  bool more_general_transition =
744  source_map->elements_kind(), target_elements_kind);
745  Map* transitioned_map = more_general_transition
746  ? source_map->LookupElementsTransitionMap(target_elements_kind)
747  : NULL;
748 
749  return transitioned_map == target_map;
750 }
751 
752 
754  Handle<String> name,
755  Handle<Code> code) {
756  switch (state()) {
757  case UNINITIALIZED:
758  case PREMONOMORPHIC:
760  UpdateMonomorphicIC(type, code, name);
761  break;
762  case MONOMORPHIC: // Fall through.
763  case POLYMORPHIC:
764  if (!target()->is_keyed_stub()) {
765  if (UpdatePolymorphicIC(type, name, code)) break;
767  }
769  // Fall through.
770  case MEGAMORPHIC:
771  UpdateMegamorphicCache(*type, *name, *code);
772  break;
773  case DEBUG_STUB:
774  break;
775  case GENERIC:
776  UNREACHABLE();
777  break;
778  }
779 }
780 
781 
783  ExtraICState extra_state) {
784  return isolate->stub_cache()->ComputeLoad(UNINITIALIZED, extra_state);
785 }
786 
787 
788 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate,
789  ExtraICState extra_state) {
790  return isolate->stub_cache()->ComputeLoad(PREMONOMORPHIC, extra_state);
791 }
792 
793 
796 }
797 
798 
799 Handle<Code> LoadIC::SimpleFieldLoad(int offset,
800  bool inobject,
801  Representation representation) {
802  if (kind() == Code::LOAD_IC) {
803  LoadFieldStub stub(inobject, offset, representation);
804  return stub.GetCode(isolate());
805  } else {
806  KeyedLoadFieldStub stub(inobject, offset, representation);
807  return stub.GetCode(isolate());
808  }
809 }
810 
811 
812 void LoadIC::UpdateCaches(LookupResult* lookup,
813  Handle<Object> object,
814  Handle<String> name) {
815  if (state() == UNINITIALIZED) {
816  // This is the first time we execute this inline cache.
817  // Set the target to the pre monomorphic stub to delay
818  // setting the monomorphic state.
819  set_target(*pre_monomorphic_stub());
820  TRACE_IC("LoadIC", name);
821  return;
822  }
823 
824  Handle<HeapType> type = CurrentTypeOf(object, isolate());
826  if (!lookup->IsCacheable()) {
827  // Bail out if the result is not cacheable.
828  code = slow_stub();
829  } else if (!lookup->IsProperty()) {
830  if (kind() == Code::LOAD_IC) {
831  code = isolate()->stub_cache()->ComputeLoadNonexistent(name, type);
832  } else {
833  code = slow_stub();
834  }
835  } else {
836  code = ComputeHandler(lookup, object, name);
837  }
838 
839  PatchCache(type, name, code);
840  TRACE_IC("LoadIC", name);
841 }
842 
843 
844 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {
845  // Cache code holding map should be consistent with
846  // GenerateMonomorphicCacheProbe.
847  Map* map = *TypeToMap(type, isolate());
848  isolate()->stub_cache()->Set(name, map, code);
849 }
850 
851 
852 Handle<Code> IC::ComputeHandler(LookupResult* lookup,
853  Handle<Object> object,
854  Handle<String> name,
855  Handle<Object> value) {
856  InlineCacheHolderFlag cache_holder = GetCodeCacheForObject(*object);
858  isolate(), *object, cache_holder));
859 
861  name, handle(stub_holder->map()), kind(), cache_holder,
862  lookup->holder()->HasFastProperties() ? Code::FAST : Code::NORMAL);
863  if (!code.is_null()) {
864  return code;
865  }
866 
867  code = CompileHandler(lookup, object, name, value, cache_holder);
868  ASSERT(code->is_handler());
869 
870  if (code->type() != Code::NORMAL) {
871  HeapObject::UpdateMapCodeCache(stub_holder, name, code);
872  }
873 
874  return code;
875 }
876 
877 
879  Handle<Object> object,
880  Handle<String> name,
881  Handle<Object> unused,
882  InlineCacheHolderFlag cache_holder) {
883  if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
884  int length_index = String::kLengthOffset / kPointerSize;
885  return SimpleFieldLoad(length_index);
886  }
887 
888  if (object->IsStringWrapper() &&
889  name->Equals(isolate()->heap()->length_string())) {
890  if (kind() == Code::LOAD_IC) {
891  StringLengthStub string_length_stub;
892  return string_length_stub.GetCode(isolate());
893  } else {
894  KeyedStringLengthStub string_length_stub;
895  return string_length_stub.GetCode(isolate());
896  }
897  }
898 
899  Handle<HeapType> type = CurrentTypeOf(object, isolate());
900  Handle<JSObject> holder(lookup->holder());
901  LoadStubCompiler compiler(isolate(), kNoExtraICState, cache_holder, kind());
902 
903  switch (lookup->type()) {
904  case FIELD: {
905  PropertyIndex field = lookup->GetFieldIndex();
906  if (object.is_identical_to(holder)) {
907  return SimpleFieldLoad(field.translate(holder),
908  field.is_inobject(holder),
909  lookup->representation());
910  }
911  return compiler.CompileLoadField(
912  type, holder, name, field, lookup->representation());
913  }
914  case CONSTANT: {
915  Handle<Object> constant(lookup->GetConstant(), isolate());
916  // TODO(2803): Don't compute a stub for cons strings because they cannot
917  // be embedded into code.
918  if (constant->IsConsString()) break;
919  return compiler.CompileLoadConstant(type, holder, name, constant);
920  }
921  case NORMAL:
922  if (kind() != Code::LOAD_IC) break;
923  if (holder->IsGlobalObject()) {
926  global->GetPropertyCell(lookup), isolate());
927  Handle<Code> code = compiler.CompileLoadGlobal(
928  type, global, cell, name, lookup->IsDontDelete());
929  // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
931  isolate(), *object, cache_holder));
932  HeapObject::UpdateMapCodeCache(stub_holder, name, code);
933  return code;
934  }
935  // There is only one shared stub for loading normalized
936  // properties. It does not traverse the prototype chain, so the
937  // property must be found in the object for the stub to be
938  // applicable.
939  if (!object.is_identical_to(holder)) break;
940  return isolate()->builtins()->LoadIC_Normal();
941  case CALLBACKS: {
942  // Use simple field loads for some well-known callback properties.
943  if (object->IsJSObject()) {
944  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
945  Handle<HeapType> type = IC::MapToType<HeapType>(
946  handle(receiver->map()), isolate());
947  int object_offset;
948  if (Accessors::IsJSObjectFieldAccessor<HeapType>(
949  type, name, &object_offset)) {
950  return SimpleFieldLoad(object_offset / kPointerSize);
951  }
952  }
953 
954  Handle<Object> callback(lookup->GetCallbackObject(), isolate());
955  if (callback->IsExecutableAccessorInfo()) {
958  if (v8::ToCData<Address>(info->getter()) == 0) break;
959  if (!info->IsCompatibleReceiver(*object)) break;
960  return compiler.CompileLoadCallback(type, holder, name, info);
961  } else if (callback->IsAccessorPair()) {
962  Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
963  isolate());
964  if (!getter->IsJSFunction()) break;
965  if (holder->IsGlobalObject()) break;
966  if (!holder->HasFastProperties()) break;
967  Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
968  if (!object->IsJSObject() &&
969  !function->IsBuiltin() &&
970  function->shared()->strict_mode() == SLOPPY) {
971  // Calling sloppy non-builtins with a value as the receiver
972  // requires boxing.
973  break;
974  }
975  CallOptimization call_optimization(function);
976  if (call_optimization.is_simple_api_call() &&
977  call_optimization.IsCompatibleReceiver(object, holder)) {
978  return compiler.CompileLoadCallback(
979  type, holder, name, call_optimization);
980  }
981  return compiler.CompileLoadViaGetter(type, holder, name, function);
982  }
983  // TODO(dcarney): Handle correctly.
984  if (callback->IsDeclaredAccessorInfo()) break;
985  ASSERT(callback->IsForeign());
986  // No IC support for old-style native accessors.
987  break;
988  }
989  case INTERCEPTOR:
990  ASSERT(HasInterceptorGetter(*holder));
991  return compiler.CompileLoadInterceptor(type, holder, name);
992  default:
993  break;
994  }
995 
996  return slow_stub();
997 }
998 
999 
1000 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1001  // This helper implements a few common fast cases for converting
1002  // non-smi keys of keyed loads/stores to a smi or a string.
1003  if (key->IsHeapNumber()) {
1004  double value = Handle<HeapNumber>::cast(key)->value();
1005  if (std::isnan(value)) {
1006  key = isolate->factory()->nan_string();
1007  } else {
1008  int int_value = FastD2I(value);
1009  if (value == int_value && Smi::IsValid(int_value)) {
1010  key = Handle<Smi>(Smi::FromInt(int_value), isolate);
1011  }
1012  }
1013  } else if (key->IsUndefined()) {
1014  key = isolate->factory()->undefined_string();
1015  }
1016  return key;
1017 }
1018 
1019 
1021  // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1022  // via megamorphic stubs, since they don't have a map in their relocation info
1023  // and so the stubs can't be harvested for the object needed for a map check.
1024  if (target()->type() != Code::NORMAL) {
1025  TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
1026  return generic_stub();
1027  }
1028 
1029  Handle<Map> receiver_map(receiver->map(), isolate());
1030  MapHandleList target_receiver_maps;
1031  if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
1032  // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1033  // yet will do so and stay there.
1034  return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1035  }
1036 
1037  if (target().is_identical_to(string_stub())) {
1038  target_receiver_maps.Add(isolate()->factory()->string_map());
1039  } else {
1040  target()->FindAllMaps(&target_receiver_maps);
1041  if (target_receiver_maps.length() == 0) {
1042  return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1043  }
1044  }
1045 
1046  // The first time a receiver is seen that is a transitioned version of the
1047  // previous monomorphic receiver type, assume the new ElementsKind is the
1048  // monomorphic type. This benefits global arrays that only transition
1049  // once, and all call sites accessing them are faster if they remain
1050  // monomorphic. If this optimistic assumption is not true, the IC will
1051  // miss again and it will become polymorphic and support both the
1052  // untransitioned and transitioned maps.
1053  if (state() == MONOMORPHIC &&
1055  target_receiver_maps.at(0)->elements_kind(),
1056  receiver->GetElementsKind())) {
1057  return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1058  }
1059 
1060  ASSERT(state() != GENERIC);
1061 
1062  // Determine the list of receiver maps that this call site has seen,
1063  // adding the map that was just encountered.
1064  if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map)) {
1065  // If the miss wasn't due to an unseen map, a polymorphic stub
1066  // won't help, use the generic stub.
1067  TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice");
1068  return generic_stub();
1069  }
1070 
1071  // If the maximum number of receiver maps has been exceeded, use the generic
1072  // version of the IC.
1073  if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1074  TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded");
1075  return generic_stub();
1076  }
1077 
1079  &target_receiver_maps);
1080 }
1081 
1082 
1084  if (MigrateDeprecated(object)) {
1085  return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1086  }
1087 
1088  MaybeObject* maybe_object = NULL;
1089  Handle<Code> stub = generic_stub();
1090 
1091  // Check for non-string values that can be converted into an
1092  // internalized string directly or is representable as a smi.
1093  key = TryConvertKey(key, isolate());
1094 
1095  if (key->IsInternalizedString()) {
1096  maybe_object = LoadIC::Load(object, Handle<String>::cast(key));
1097  if (maybe_object->IsFailure()) return maybe_object;
1098  } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
1099  if (object->IsString() && key->IsNumber()) {
1100  if (state() == UNINITIALIZED) stub = string_stub();
1101  } else if (object->IsJSObject()) {
1102  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1103  if (receiver->elements()->map() ==
1104  isolate()->heap()->sloppy_arguments_elements_map()) {
1105  stub = sloppy_arguments_stub();
1106  } else if (receiver->HasIndexedInterceptor()) {
1107  stub = indexed_interceptor_stub();
1108  } else if (!key->ToSmi()->IsFailure() &&
1109  (!target().is_identical_to(sloppy_arguments_stub()))) {
1110  stub = LoadElementStub(receiver);
1111  }
1112  }
1113  }
1114 
1115  if (!is_target_set()) {
1116  if (*stub == *generic_stub()) {
1117  TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
1118  }
1119  set_target(*stub);
1120  TRACE_IC("LoadIC", key);
1121  }
1122 
1123  if (maybe_object != NULL) return maybe_object;
1124  return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1125 }
1126 
1127 
1128 static bool LookupForWrite(Handle<JSObject> receiver,
1129  Handle<String> name,
1130  Handle<Object> value,
1131  LookupResult* lookup,
1132  IC* ic) {
1133  Handle<JSObject> holder = receiver;
1134  receiver->Lookup(*name, lookup);
1135  if (lookup->IsFound()) {
1136  if (lookup->IsInterceptor() && !HasInterceptorSetter(lookup->holder())) {
1137  receiver->LocalLookupRealNamedProperty(*name, lookup);
1138  if (!lookup->IsFound()) return false;
1139  }
1140 
1141  if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false;
1142  if (lookup->holder() == *receiver) return lookup->CanHoldValue(value);
1143  if (lookup->IsPropertyCallbacks()) return true;
1144  // JSGlobalProxy either stores on the global object in the prototype, or
1145  // goes into the runtime if access checks are needed, so this is always
1146  // safe.
1147  if (receiver->IsJSGlobalProxy()) {
1148  return lookup->holder() == receiver->GetPrototype();
1149  }
1150  // Currently normal holders in the prototype chain are not supported. They
1151  // would require a runtime positive lookup and verification that the details
1152  // have not changed.
1153  if (lookup->IsInterceptor() || lookup->IsNormal()) return false;
1154  holder = Handle<JSObject>(lookup->holder(), lookup->isolate());
1155  }
1156 
1157  // While normally LookupTransition gets passed the receiver, in this case we
1158  // pass the holder of the property that we overwrite. This keeps the holder in
1159  // the LookupResult intact so we can later use it to generate a prototype
1160  // chain check. This avoids a double lookup, but requires us to pass in the
1161  // receiver when trying to fetch extra information from the transition.
1162  receiver->map()->LookupTransition(*holder, *name, lookup);
1163  if (!lookup->IsTransition()) return false;
1164  PropertyDetails target_details = lookup->GetTransitionDetails();
1165  if (target_details.IsReadOnly()) return false;
1166 
1167  // If the value that's being stored does not fit in the field that the
1168  // instance would transition to, create a new transition that fits the value.
1169  // This has to be done before generating the IC, since that IC will embed the
1170  // transition target.
1171  // Ensure the instance and its map were migrated before trying to update the
1172  // transition target.
1173  ASSERT(!receiver->map()->is_deprecated());
1174  if (!value->FitsRepresentation(target_details.representation())) {
1175  Handle<Map> target(lookup->GetTransitionTarget());
1177  target, target->LastAdded(),
1179  // Lookup the transition again since the transition tree may have changed
1180  // entirely by the migration above.
1181  receiver->map()->LookupTransition(*holder, *name, lookup);
1182  if (!lookup->IsTransition()) return false;
1184  }
1185  return true;
1186 }
1187 
1188 
1189 MaybeObject* StoreIC::Store(Handle<Object> object,
1190  Handle<String> name,
1191  Handle<Object> value,
1192  JSReceiver::StoreFromKeyed store_mode) {
1193  if (MigrateDeprecated(object) || object->IsJSProxy()) {
1195  Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode());
1196  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1197  return *result;
1198  }
1199 
1200  // If the object is undefined or null it's illegal to try to set any
1201  // properties on it; throw a TypeError in that case.
1202  if (object->IsUndefined() || object->IsNull()) {
1203  return TypeError("non_object_property_store", object, name);
1204  }
1205 
1206  // The length property of string values is read-only. Throw in strict mode.
1207  if (strict_mode() == STRICT && object->IsString() &&
1208  name->Equals(isolate()->heap()->length_string())) {
1209  return TypeError("strict_read_only_property", object, name);
1210  }
1211 
1212  // Ignore other stores where the receiver is not a JSObject.
1213  // TODO(1475): Must check prototype chains of object wrappers.
1214  if (!object->IsJSObject()) return *value;
1215 
1216  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1217 
1218  // Check if the given name is an array index.
1219  uint32_t index;
1220  if (name->AsArrayIndex(&index)) {
1221  Handle<Object> result =
1222  JSObject::SetElement(receiver, index, value, NONE, strict_mode());
1223  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1224  return *value;
1225  }
1226 
1227  // Observed objects are always modified through the runtime.
1228  if (receiver->map()->is_observed()) {
1230  receiver, name, value, NONE, strict_mode(), store_mode);
1231  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1232  return *result;
1233  }
1234 
1235  LookupResult lookup(isolate());
1236  bool can_store = LookupForWrite(receiver, name, value, &lookup, this);
1237  if (!can_store &&
1238  strict_mode() == STRICT &&
1239  !(lookup.IsProperty() && lookup.IsReadOnly()) &&
1240  object->IsGlobalObject()) {
1241  // Strict mode doesn't allow setting non-existent global property.
1242  return ReferenceError("not_defined", name);
1243  }
1244  if (FLAG_use_ic) {
1245  if (state() == UNINITIALIZED) {
1247  set_target(*stub);
1248  TRACE_IC("StoreIC", name);
1249  } else if (can_store) {
1250  UpdateCaches(&lookup, receiver, name, value);
1251  } else if (!name->IsCacheable(isolate()) ||
1252  lookup.IsNormal() ||
1253  (lookup.IsField() && lookup.CanHoldValue(value))) {
1254  Handle<Code> stub = generic_stub();
1255  set_target(*stub);
1256  }
1257  }
1258 
1259  // Set the property.
1261  receiver, name, value, NONE, strict_mode(), store_mode);
1262  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1263  return *result;
1264 }
1265 
1266 
1268  StrictMode strict_mode) {
1269  ExtraICState extra_state = ComputeExtraICState(strict_mode);
1270  Handle<Code> ic = isolate->stub_cache()->ComputeStore(
1271  UNINITIALIZED, extra_state);
1272  return ic;
1273 }
1274 
1275 
1278 }
1279 
1280 
1283 }
1284 
1285 
1287  StrictMode strict_mode) {
1288  ExtraICState state = ComputeExtraICState(strict_mode);
1289  return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state);
1290 }
1291 
1292 
1293 void StoreIC::UpdateCaches(LookupResult* lookup,
1294  Handle<JSObject> receiver,
1295  Handle<String> name,
1296  Handle<Object> value) {
1297  ASSERT(lookup->IsFound());
1298 
1299  // These are not cacheable, so we never see such LookupResults here.
1300  ASSERT(!lookup->IsHandler());
1301 
1302  Handle<Code> code = ComputeHandler(lookup, receiver, name, value);
1303 
1304  PatchCache(CurrentTypeOf(receiver, isolate()), name, code);
1305  TRACE_IC("StoreIC", name);
1306 }
1307 
1308 
1310  Handle<Object> object,
1311  Handle<String> name,
1312  Handle<Object> value,
1313  InlineCacheHolderFlag cache_holder) {
1314  if (object->IsAccessCheckNeeded()) return slow_stub();
1315  ASSERT(cache_holder == OWN_MAP);
1316  // This is currently guaranteed by checks in StoreIC::Store.
1317  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1318 
1319  Handle<JSObject> holder(lookup->holder());
1320  // Handlers do not use strict mode.
1321  StoreStubCompiler compiler(isolate(), SLOPPY, kind());
1322  switch (lookup->type()) {
1323  case FIELD:
1324  return compiler.CompileStoreField(receiver, lookup, name);
1325  case TRANSITION: {
1326  // Explicitly pass in the receiver map since LookupForWrite may have
1327  // stored something else than the receiver in the holder.
1328  Handle<Map> transition(lookup->GetTransitionTarget());
1329  PropertyDetails details = transition->GetLastDescriptorDetails();
1330 
1331  if (details.type() == CALLBACKS || details.attributes() != NONE) break;
1332 
1333  return compiler.CompileStoreTransition(
1334  receiver, lookup, transition, name);
1335  }
1336  case NORMAL:
1337  if (kind() == Code::KEYED_STORE_IC) break;
1338  if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) {
1339  // The stub generated for the global object picks the value directly
1340  // from the property cell. So the property must be directly on the
1341  // global object.
1342  Handle<GlobalObject> global = receiver->IsJSGlobalProxy()
1343  ? handle(GlobalObject::cast(receiver->GetPrototype()))
1344  : Handle<GlobalObject>::cast(receiver);
1345  Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate());
1346  Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value);
1347  StoreGlobalStub stub(
1348  union_type->IsConstant(), receiver->IsJSGlobalProxy());
1349  Handle<Code> code = stub.GetCodeCopyFromTemplate(
1350  isolate(), global, cell);
1351  // TODO(verwaest): Move caching of these NORMAL stubs outside as well.
1352  HeapObject::UpdateMapCodeCache(receiver, name, code);
1353  return code;
1354  }
1355  ASSERT(holder.is_identical_to(receiver));
1356  return isolate()->builtins()->StoreIC_Normal();
1357  case CALLBACKS: {
1358  Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1359  if (callback->IsExecutableAccessorInfo()) {
1362  if (v8::ToCData<Address>(info->setter()) == 0) break;
1363  if (!holder->HasFastProperties()) break;
1364  if (!info->IsCompatibleReceiver(*receiver)) break;
1365  return compiler.CompileStoreCallback(receiver, holder, name, info);
1366  } else if (callback->IsAccessorPair()) {
1367  Handle<Object> setter(
1368  Handle<AccessorPair>::cast(callback)->setter(), isolate());
1369  if (!setter->IsJSFunction()) break;
1370  if (holder->IsGlobalObject()) break;
1371  if (!holder->HasFastProperties()) break;
1372  Handle<JSFunction> function = Handle<JSFunction>::cast(setter);
1373  CallOptimization call_optimization(function);
1374  if (call_optimization.is_simple_api_call() &&
1375  call_optimization.IsCompatibleReceiver(receiver, holder)) {
1376  return compiler.CompileStoreCallback(
1377  receiver, holder, name, call_optimization);
1378  }
1379  return compiler.CompileStoreViaSetter(
1380  receiver, holder, name, Handle<JSFunction>::cast(setter));
1381  }
1382  // TODO(dcarney): Handle correctly.
1383  if (callback->IsDeclaredAccessorInfo()) break;
1384  ASSERT(callback->IsForeign());
1385 
1386  // Use specialized code for setting the length of arrays with fast
1387  // properties. Slow properties might indicate redefinition of the length
1388  // property.
1389  if (receiver->IsJSArray() &&
1390  name->Equals(isolate()->heap()->length_string()) &&
1391  Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
1392  receiver->HasFastProperties()) {
1393  return compiler.CompileStoreArrayLength(receiver, lookup, name);
1394  }
1395 
1396  // No IC support for old-style native accessors.
1397  break;
1398  }
1399  case INTERCEPTOR:
1400  if (kind() == Code::KEYED_STORE_IC) break;
1401  ASSERT(HasInterceptorSetter(*holder));
1402  return compiler.CompileStoreInterceptor(receiver, name);
1403  case CONSTANT:
1404  break;
1405  case NONEXISTENT:
1406  case HANDLER:
1407  UNREACHABLE();
1408  break;
1409  }
1410  return slow_stub();
1411 }
1412 
1413 
1415  KeyedAccessStoreMode store_mode) {
1416  // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1417  // via megamorphic stubs, since they don't have a map in their relocation info
1418  // and so the stubs can't be harvested for the object needed for a map check.
1419  if (target()->type() != Code::NORMAL) {
1420  TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
1421  return generic_stub();
1422  }
1423 
1424  Handle<Map> receiver_map(receiver->map(), isolate());
1425  if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
1426  // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1427  // yet will do so and stay there.
1428  Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode);
1429  store_mode = GetNonTransitioningStoreMode(store_mode);
1431  monomorphic_map, strict_mode(), store_mode);
1432  }
1433 
1434  MapHandleList target_receiver_maps;
1435  target()->FindAllMaps(&target_receiver_maps);
1436  if (target_receiver_maps.length() == 0) {
1437  // In the case that there is a non-map-specific IC is installed (e.g. keyed
1438  // stores into properties in dictionary mode), then there will be not
1439  // receiver maps in the target.
1440  return generic_stub();
1441  }
1442 
1443  // There are several special cases where an IC that is MONOMORPHIC can still
1444  // transition to a different GetNonTransitioningStoreMode IC that handles a
1445  // superset of the original IC. Handle those here if the receiver map hasn't
1446  // changed or it has transitioned to a more general kind.
1447  KeyedAccessStoreMode old_store_mode =
1449  Handle<Map> previous_receiver_map = target_receiver_maps.at(0);
1450  if (state() == MONOMORPHIC) {
1451  Handle<Map> transitioned_receiver_map = receiver_map;
1452  if (IsTransitionStoreMode(store_mode)) {
1453  transitioned_receiver_map = ComputeTransitionedMap(receiver, store_mode);
1454  }
1455  if ((receiver_map.is_identical_to(previous_receiver_map) &&
1456  IsTransitionStoreMode(store_mode)) ||
1457  IsTransitionOfMonomorphicTarget(*previous_receiver_map,
1458  *transitioned_receiver_map)) {
1459  // If the "old" and "new" maps are in the same elements map family, or
1460  // if they at least come from the same origin for a transitioning store,
1461  // stay MONOMORPHIC and use the map for the most generic ElementsKind.
1462  store_mode = GetNonTransitioningStoreMode(store_mode);
1464  transitioned_receiver_map, strict_mode(), store_mode);
1465  } else if (*previous_receiver_map == receiver->map() &&
1466  old_store_mode == STANDARD_STORE &&
1467  (store_mode == STORE_AND_GROW_NO_TRANSITION ||
1469  store_mode == STORE_NO_TRANSITION_HANDLE_COW)) {
1470  // A "normal" IC that handles stores can switch to a version that can
1471  // grow at the end of the array, handle OOB accesses or copy COW arrays
1472  // and still stay MONOMORPHIC.
1474  receiver_map, strict_mode(), store_mode);
1475  }
1476  }
1477 
1478  ASSERT(state() != GENERIC);
1479 
1480  bool map_added =
1481  AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1482 
1483  if (IsTransitionStoreMode(store_mode)) {
1484  Handle<Map> transitioned_receiver_map =
1485  ComputeTransitionedMap(receiver, store_mode);
1486  map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps,
1487  transitioned_receiver_map);
1488  }
1489 
1490  if (!map_added) {
1491  // If the miss wasn't due to an unseen map, a polymorphic stub
1492  // won't help, use the generic stub.
1493  TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice");
1494  return generic_stub();
1495  }
1496 
1497  // If the maximum number of receiver maps has been exceeded, use the generic
1498  // version of the IC.
1499  if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1500  TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded");
1501  return generic_stub();
1502  }
1503 
1504  // Make sure all polymorphic handlers have the same store mode, otherwise the
1505  // generic stub must be used.
1506  store_mode = GetNonTransitioningStoreMode(store_mode);
1507  if (old_store_mode != STANDARD_STORE) {
1508  if (store_mode == STANDARD_STORE) {
1509  store_mode = old_store_mode;
1510  } else if (store_mode != old_store_mode) {
1511  TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch");
1512  return generic_stub();
1513  }
1514  }
1515 
1516  // If the store mode isn't the standard mode, make sure that all polymorphic
1517  // receivers are either external arrays, or all "normal" arrays. Otherwise,
1518  // use the generic stub.
1519  if (store_mode != STANDARD_STORE) {
1520  int external_arrays = 0;
1521  for (int i = 0; i < target_receiver_maps.length(); ++i) {
1522  if (target_receiver_maps[i]->has_external_array_elements() ||
1523  target_receiver_maps[i]->has_fixed_typed_array_elements()) {
1524  external_arrays++;
1525  }
1526  }
1527  if (external_arrays != 0 &&
1528  external_arrays != target_receiver_maps.length()) {
1529  TRACE_GENERIC_IC(isolate(), "KeyedIC",
1530  "unsupported combination of external and normal arrays");
1531  return generic_stub();
1532  }
1533  }
1534 
1536  &target_receiver_maps, store_mode, strict_mode());
1537 }
1538 
1539 
1540 Handle<Map> KeyedStoreIC::ComputeTransitionedMap(
1541  Handle<JSObject> receiver,
1542  KeyedAccessStoreMode store_mode) {
1543  switch (store_mode) {
1556  return JSObject::GetElementsTransitionMap(receiver,
1560  return JSObject::GetElementsTransitionMap(receiver,
1563  ASSERT(receiver->map()->has_external_array_elements());
1564  // Fall through
1566  case STANDARD_STORE:
1568  return Handle<Map>(receiver->map(), isolate());
1569  }
1570  return Handle<Map>::null();
1571 }
1572 
1573 
1575  int index) {
1576  if (receiver->IsJSArray()) {
1577  return JSArray::cast(*receiver)->length()->IsSmi() &&
1578  index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
1579  }
1580  return index >= receiver->elements()->length();
1581 }
1582 
1583 
1584 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
1585  Handle<Object> key,
1586  Handle<Object> value) {
1587  ASSERT(!key->ToSmi()->IsFailure());
1588  Smi* smi_key = NULL;
1589  key->ToSmi()->To(&smi_key);
1590  int index = smi_key->value();
1591  bool oob_access = IsOutOfBoundsAccess(receiver, index);
1592  // Don't consider this a growing store if the store would send the receiver to
1593  // dictionary mode.
1594  bool allow_growth = receiver->IsJSArray() && oob_access &&
1595  !receiver->WouldConvertToSlowElements(key);
1596  if (allow_growth) {
1597  // Handle growing array in stub if necessary.
1598  if (receiver->HasFastSmiElements()) {
1599  if (value->IsHeapNumber()) {
1600  if (receiver->HasFastHoleyElements()) {
1602  } else {
1604  }
1605  }
1606  if (value->IsHeapObject()) {
1607  if (receiver->HasFastHoleyElements()) {
1609  } else {
1611  }
1612  }
1613  } else if (receiver->HasFastDoubleElements()) {
1614  if (!value->IsSmi() && !value->IsHeapNumber()) {
1615  if (receiver->HasFastHoleyElements()) {
1617  } else {
1619  }
1620  }
1621  }
1623  } else {
1624  // Handle only in-bounds elements accesses.
1625  if (receiver->HasFastSmiElements()) {
1626  if (value->IsHeapNumber()) {
1627  if (receiver->HasFastHoleyElements()) {
1629  } else {
1631  }
1632  } else if (value->IsHeapObject()) {
1633  if (receiver->HasFastHoleyElements()) {
1635  } else {
1637  }
1638  }
1639  } else if (receiver->HasFastDoubleElements()) {
1640  if (!value->IsSmi() && !value->IsHeapNumber()) {
1641  if (receiver->HasFastHoleyElements()) {
1643  } else {
1645  }
1646  }
1647  }
1648  if (!FLAG_trace_external_array_abuse &&
1649  receiver->map()->has_external_array_elements() && oob_access) {
1651  }
1652  Heap* heap = receiver->GetHeap();
1653  if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
1655  } else {
1656  return STANDARD_STORE;
1657  }
1658  }
1659 }
1660 
1661 
1663  Handle<Object> key,
1664  Handle<Object> value) {
1665  if (MigrateDeprecated(object)) {
1667  key,
1668  value,
1669  NONE,
1670  strict_mode());
1671  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1672  return *result;
1673  }
1674 
1675  // Check for non-string values that can be converted into an
1676  // internalized string directly or is representable as a smi.
1677  key = TryConvertKey(key, isolate());
1678 
1679  MaybeObject* maybe_object = NULL;
1680  Handle<Code> stub = generic_stub();
1681 
1682  if (key->IsInternalizedString()) {
1683  maybe_object = StoreIC::Store(object,
1684  Handle<String>::cast(key),
1685  value,
1687  if (maybe_object->IsFailure()) return maybe_object;
1688  } else {
1689  bool use_ic = FLAG_use_ic &&
1690  !object->IsAccessCheckNeeded() &&
1691  !object->IsJSGlobalProxy() &&
1692  !(object->IsJSObject() &&
1693  JSObject::cast(*object)->map()->is_observed());
1694  if (use_ic && !object->IsSmi()) {
1695  // Don't use ICs for maps of the objects in Array's prototype chain. We
1696  // expect to be able to trap element sets to objects with those maps in
1697  // the runtime to enable optimization of element hole access.
1698  Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object);
1699  if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false;
1700  }
1701 
1702  if (use_ic) {
1703  ASSERT(!object->IsAccessCheckNeeded());
1704 
1705  if (object->IsJSObject()) {
1706  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1707  bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure();
1708  if (receiver->elements()->map() ==
1709  isolate()->heap()->sloppy_arguments_elements_map()) {
1710  if (strict_mode() == SLOPPY) {
1711  stub = sloppy_arguments_stub();
1712  }
1713  } else if (key_is_smi_like &&
1714  !(target().is_identical_to(sloppy_arguments_stub()))) {
1715  // We should go generic if receiver isn't a dictionary, but our
1716  // prototype chain does have dictionary elements. This ensures that
1717  // other non-dictionary receivers in the polymorphic case benefit
1718  // from fast path keyed stores.
1719  if (!(receiver->map()->DictionaryElementsInPrototypeChainOnly())) {
1720  KeyedAccessStoreMode store_mode =
1721  GetStoreMode(receiver, key, value);
1722  stub = StoreElementStub(receiver, store_mode);
1723  }
1724  }
1725  }
1726  }
1727  }
1728 
1729  if (!is_target_set()) {
1730  if (*stub == *generic_stub()) {
1731  TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic");
1732  }
1733  ASSERT(!stub.is_null());
1734  set_target(*stub);
1735  TRACE_IC("StoreIC", key);
1736  }
1737 
1738  if (maybe_object) return maybe_object;
1739  Handle<Object> result = Runtime::SetObjectProperty(isolate(), object, key,
1740  value,
1741  NONE,
1742  strict_mode());
1743  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1744  return *result;
1745 }
1746 
1747 
1748 #undef TRACE_IC
1749 
1750 
1751 // ----------------------------------------------------------------------------
1752 // Static IC stub generators.
1753 //
1754 
1755 // Used from ic-<arch>.cc.
1756 // Used from ic-<arch>.cc.
1757 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
1758  HandleScope scope(isolate);
1759  ASSERT(args.length() == 2);
1760  LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
1761  Handle<Object> receiver = args.at<Object>(0);
1762  Handle<String> key = args.at<String>(1);
1763  ic.UpdateState(receiver, key);
1764  return ic.Load(receiver, key);
1765 }
1766 
1767 
1768 // Used from ic-<arch>.cc
1769 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
1770  HandleScope scope(isolate);
1771  ASSERT(args.length() == 2);
1772  KeyedLoadIC ic(IC::NO_EXTRA_FRAME, isolate);
1773  Handle<Object> receiver = args.at<Object>(0);
1774  Handle<Object> key = args.at<Object>(1);
1775  ic.UpdateState(receiver, key);
1776  return ic.Load(receiver, key);
1777 }
1778 
1779 
1780 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissFromStubFailure) {
1781  HandleScope scope(isolate);
1782  ASSERT(args.length() == 2);
1783  KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate);
1784  Handle<Object> receiver = args.at<Object>(0);
1785  Handle<Object> key = args.at<Object>(1);
1786  ic.UpdateState(receiver, key);
1787  return ic.Load(receiver, key);
1788 }
1789 
1790 
1791 // Used from ic-<arch>.cc.
1792 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
1793  HandleScope scope(isolate);
1794  ASSERT(args.length() == 3);
1795  StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
1796  Handle<Object> receiver = args.at<Object>(0);
1797  Handle<String> key = args.at<String>(1);
1798  ic.UpdateState(receiver, key);
1799  return ic.Store(receiver, key, args.at<Object>(2));
1800 }
1801 
1802 
1803 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) {
1804  HandleScope scope(isolate);
1805  ASSERT(args.length() == 3);
1806  StoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
1807  Handle<Object> receiver = args.at<Object>(0);
1808  Handle<String> key = args.at<String>(1);
1809  ic.UpdateState(receiver, key);
1810  return ic.Store(receiver, key, args.at<Object>(2));
1811 }
1812 
1813 
1814 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
1815  HandleScope scope(isolate);
1816 
1817  ASSERT(args.length() == 2);
1818  Handle<JSArray> receiver = args.at<JSArray>(0);
1819  Handle<Object> len = args.at<Object>(1);
1820 
1821  // The generated code should filter out non-Smis before we get here.
1822  ASSERT(len->IsSmi());
1823 
1824 #ifdef DEBUG
1825  // The length property has to be a writable callback property.
1826  LookupResult debug_lookup(isolate);
1827  receiver->LocalLookup(isolate->heap()->length_string(), &debug_lookup);
1828  ASSERT(debug_lookup.IsPropertyCallbacks() && !debug_lookup.IsReadOnly());
1829 #endif
1830 
1831  RETURN_IF_EMPTY_HANDLE(isolate,
1832  JSArray::SetElementsLength(receiver, len));
1833  return *len;
1834 }
1835 
1836 
1837 // Extend storage is called in a store inline cache when
1838 // it is necessary to extend the properties array of a
1839 // JSObject.
1840 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
1841  SealHandleScope shs(isolate);
1842  ASSERT(args.length() == 3);
1843 
1844  // Convert the parameters
1845  JSObject* object = JSObject::cast(args[0]);
1846  Map* transition = Map::cast(args[1]);
1847  Object* value = args[2];
1848 
1849  // Check the object has run out out property space.
1850  ASSERT(object->HasFastProperties());
1851  ASSERT(object->map()->unused_property_fields() == 0);
1852 
1853  // Expand the properties array.
1854  FixedArray* old_storage = object->properties();
1855  int new_unused = transition->unused_property_fields();
1856  int new_size = old_storage->length() + new_unused + 1;
1857  Object* result;
1858  MaybeObject* maybe_result = old_storage->CopySize(new_size);
1859  if (!maybe_result->ToObject(&result)) return maybe_result;
1860 
1861  FixedArray* new_storage = FixedArray::cast(result);
1862 
1863  Object* to_store = value;
1864 
1865  DescriptorArray* descriptors = transition->instance_descriptors();
1866  PropertyDetails details = descriptors->GetDetails(transition->LastAdded());
1867  if (details.representation().IsDouble()) {
1868  MaybeObject* maybe_storage =
1869  isolate->heap()->AllocateHeapNumber(value->Number());
1870  if (!maybe_storage->To(&to_store)) return maybe_storage;
1871  }
1872 
1873  new_storage->set(old_storage->length(), to_store);
1874 
1875  // Set the new property value and do the map transition.
1876  object->set_properties(new_storage);
1877  object->set_map(transition);
1878 
1879  // Return the stored value.
1880  return value;
1881 }
1882 
1883 
1884 // Used from ic-<arch>.cc.
1885 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
1886  HandleScope scope(isolate);
1887  ASSERT(args.length() == 3);
1888  KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
1889  Handle<Object> receiver = args.at<Object>(0);
1890  Handle<Object> key = args.at<Object>(1);
1891  ic.UpdateState(receiver, key);
1892  return ic.Store(receiver, key, args.at<Object>(2));
1893 }
1894 
1895 
1896 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
1897  HandleScope scope(isolate);
1898  ASSERT(args.length() == 3);
1899  KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
1900  Handle<Object> receiver = args.at<Object>(0);
1901  Handle<Object> key = args.at<Object>(1);
1902  ic.UpdateState(receiver, key);
1903  return ic.Store(receiver, key, args.at<Object>(2));
1904 }
1905 
1906 
1907 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) {
1908  HandleScope scope(isolate);
1909  ASSERT(args.length() == 3);
1910  StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
1911  Handle<Object> object = args.at<Object>(0);
1912  Handle<Object> key = args.at<Object>(1);
1913  Handle<Object> value = args.at<Object>(2);
1914  StrictMode strict_mode = ic.strict_mode();
1915  Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
1916  value,
1917  NONE,
1918  strict_mode);
1919  RETURN_IF_EMPTY_HANDLE(isolate, result);
1920  return *result;
1921 }
1922 
1923 
1924 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
1925  HandleScope scope(isolate);
1926  ASSERT(args.length() == 3);
1927  KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
1928  Handle<Object> object = args.at<Object>(0);
1929  Handle<Object> key = args.at<Object>(1);
1930  Handle<Object> value = args.at<Object>(2);
1931  StrictMode strict_mode = ic.strict_mode();
1932  Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
1933  value,
1934  NONE,
1935  strict_mode);
1936  RETURN_IF_EMPTY_HANDLE(isolate, result);
1937  return *result;
1938 }
1939 
1940 
1941 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) {
1942  HandleScope scope(isolate);
1943  ASSERT(args.length() == 4);
1944  KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
1945  Handle<Object> value = args.at<Object>(0);
1946  Handle<Map> map = args.at<Map>(1);
1947  Handle<Object> key = args.at<Object>(2);
1948  Handle<Object> object = args.at<Object>(3);
1949  StrictMode strict_mode = ic.strict_mode();
1950  if (object->IsJSObject()) {
1952  map->elements_kind());
1953  }
1954  Handle<Object> result = Runtime::SetObjectProperty(isolate, object, key,
1955  value,
1956  NONE,
1957  strict_mode);
1958  RETURN_IF_EMPTY_HANDLE(isolate, result);
1959  return *result;
1960 }
1961 
1962 
1963 BinaryOpIC::State::State(ExtraICState extra_ic_state) {
1964  // We don't deserialize the SSE2 Field, since this is only used to be able
1965  // to include SSE2 as well as non-SSE2 versions in the snapshot. For code
1966  // generation we always want it to reflect the current state.
1967  op_ = static_cast<Token::Value>(
1968  FIRST_TOKEN + OpField::decode(extra_ic_state));
1969  mode_ = OverwriteModeField::decode(extra_ic_state);
1970  fixed_right_arg_ = Maybe<int>(
1971  HasFixedRightArgField::decode(extra_ic_state),
1972  1 << FixedRightArgValueField::decode(extra_ic_state));
1973  left_kind_ = LeftKindField::decode(extra_ic_state);
1974  if (fixed_right_arg_.has_value) {
1975  right_kind_ = Smi::IsValid(fixed_right_arg_.value) ? SMI : INT32;
1976  } else {
1977  right_kind_ = RightKindField::decode(extra_ic_state);
1978  }
1979  result_kind_ = ResultKindField::decode(extra_ic_state);
1980  ASSERT_LE(FIRST_TOKEN, op_);
1981  ASSERT_LE(op_, LAST_TOKEN);
1982 }
1983 
1984 
1985 ExtraICState BinaryOpIC::State::GetExtraICState() const {
1986  bool sse2 = (Max(result_kind_, Max(left_kind_, right_kind_)) > SMI &&
1988  ExtraICState extra_ic_state =
1989  SSE2Field::encode(sse2) |
1990  OpField::encode(op_ - FIRST_TOKEN) |
1991  OverwriteModeField::encode(mode_) |
1992  LeftKindField::encode(left_kind_) |
1993  ResultKindField::encode(result_kind_) |
1994  HasFixedRightArgField::encode(fixed_right_arg_.has_value);
1995  if (fixed_right_arg_.has_value) {
1996  extra_ic_state = FixedRightArgValueField::update(
1997  extra_ic_state, WhichPowerOf2(fixed_right_arg_.value));
1998  } else {
1999  extra_ic_state = RightKindField::update(extra_ic_state, right_kind_);
2000  }
2001  return extra_ic_state;
2002 }
2003 
2004 
2005 // static
2006 void BinaryOpIC::State::GenerateAheadOfTime(
2007  Isolate* isolate, void (*Generate)(Isolate*, const State&)) {
2008  // TODO(olivf) We should investigate why adding stubs to the snapshot is so
2009  // expensive at runtime. When solved we should be able to add most binops to
2010  // the snapshot instead of hand-picking them.
2011  // Generated list of commonly used stubs
2012 #define GENERATE(op, left_kind, right_kind, result_kind, mode) \
2013  do { \
2014  State state(op, mode); \
2015  state.left_kind_ = left_kind; \
2016  state.fixed_right_arg_.has_value = false; \
2017  state.right_kind_ = right_kind; \
2018  state.result_kind_ = result_kind; \
2019  Generate(isolate, state); \
2020  } while (false)
2021  GENERATE(Token::ADD, INT32, INT32, INT32, NO_OVERWRITE);
2022  GENERATE(Token::ADD, INT32, INT32, INT32, OVERWRITE_LEFT);
2023  GENERATE(Token::ADD, INT32, INT32, NUMBER, NO_OVERWRITE);
2024  GENERATE(Token::ADD, INT32, INT32, NUMBER, OVERWRITE_LEFT);
2025  GENERATE(Token::ADD, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2026  GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2027  GENERATE(Token::ADD, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
2028  GENERATE(Token::ADD, INT32, SMI, INT32, NO_OVERWRITE);
2029  GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_LEFT);
2030  GENERATE(Token::ADD, INT32, SMI, INT32, OVERWRITE_RIGHT);
2031  GENERATE(Token::ADD, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2032  GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2033  GENERATE(Token::ADD, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
2034  GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2035  GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2036  GENERATE(Token::ADD, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
2037  GENERATE(Token::ADD, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2038  GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2039  GENERATE(Token::ADD, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
2040  GENERATE(Token::ADD, SMI, INT32, INT32, NO_OVERWRITE);
2041  GENERATE(Token::ADD, SMI, INT32, INT32, OVERWRITE_LEFT);
2042  GENERATE(Token::ADD, SMI, INT32, NUMBER, NO_OVERWRITE);
2043  GENERATE(Token::ADD, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2044  GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2045  GENERATE(Token::ADD, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2046  GENERATE(Token::ADD, SMI, SMI, INT32, OVERWRITE_LEFT);
2047  GENERATE(Token::ADD, SMI, SMI, SMI, OVERWRITE_RIGHT);
2048  GENERATE(Token::BIT_AND, INT32, INT32, INT32, NO_OVERWRITE);
2049  GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_LEFT);
2050  GENERATE(Token::BIT_AND, INT32, INT32, INT32, OVERWRITE_RIGHT);
2051  GENERATE(Token::BIT_AND, INT32, INT32, SMI, NO_OVERWRITE);
2052  GENERATE(Token::BIT_AND, INT32, INT32, SMI, OVERWRITE_RIGHT);
2053  GENERATE(Token::BIT_AND, INT32, SMI, INT32, NO_OVERWRITE);
2054  GENERATE(Token::BIT_AND, INT32, SMI, INT32, OVERWRITE_RIGHT);
2055  GENERATE(Token::BIT_AND, INT32, SMI, SMI, NO_OVERWRITE);
2056  GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_LEFT);
2057  GENERATE(Token::BIT_AND, INT32, SMI, SMI, OVERWRITE_RIGHT);
2058  GENERATE(Token::BIT_AND, NUMBER, INT32, INT32, OVERWRITE_RIGHT);
2059  GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, NO_OVERWRITE);
2060  GENERATE(Token::BIT_AND, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
2061  GENERATE(Token::BIT_AND, SMI, INT32, INT32, NO_OVERWRITE);
2062  GENERATE(Token::BIT_AND, SMI, INT32, SMI, OVERWRITE_RIGHT);
2063  GENERATE(Token::BIT_AND, SMI, NUMBER, SMI, OVERWRITE_RIGHT);
2064  GENERATE(Token::BIT_AND, SMI, SMI, SMI, NO_OVERWRITE);
2065  GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_LEFT);
2066  GENERATE(Token::BIT_AND, SMI, SMI, SMI, OVERWRITE_RIGHT);
2067  GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_LEFT);
2068  GENERATE(Token::BIT_OR, INT32, INT32, INT32, OVERWRITE_RIGHT);
2069  GENERATE(Token::BIT_OR, INT32, INT32, SMI, OVERWRITE_LEFT);
2070  GENERATE(Token::BIT_OR, INT32, SMI, INT32, NO_OVERWRITE);
2071  GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_LEFT);
2072  GENERATE(Token::BIT_OR, INT32, SMI, INT32, OVERWRITE_RIGHT);
2073  GENERATE(Token::BIT_OR, INT32, SMI, SMI, NO_OVERWRITE);
2074  GENERATE(Token::BIT_OR, INT32, SMI, SMI, OVERWRITE_RIGHT);
2075  GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, NO_OVERWRITE);
2076  GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_LEFT);
2077  GENERATE(Token::BIT_OR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
2078  GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, NO_OVERWRITE);
2079  GENERATE(Token::BIT_OR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
2080  GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_LEFT);
2081  GENERATE(Token::BIT_OR, SMI, INT32, INT32, OVERWRITE_RIGHT);
2082  GENERATE(Token::BIT_OR, SMI, INT32, SMI, OVERWRITE_RIGHT);
2083  GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_LEFT);
2084  GENERATE(Token::BIT_OR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2085  GENERATE(Token::BIT_XOR, INT32, INT32, INT32, NO_OVERWRITE);
2086  GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_LEFT);
2087  GENERATE(Token::BIT_XOR, INT32, INT32, INT32, OVERWRITE_RIGHT);
2088  GENERATE(Token::BIT_XOR, INT32, INT32, SMI, NO_OVERWRITE);
2089  GENERATE(Token::BIT_XOR, INT32, INT32, SMI, OVERWRITE_LEFT);
2090  GENERATE(Token::BIT_XOR, INT32, NUMBER, SMI, NO_OVERWRITE);
2091  GENERATE(Token::BIT_XOR, INT32, SMI, INT32, NO_OVERWRITE);
2092  GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_LEFT);
2093  GENERATE(Token::BIT_XOR, INT32, SMI, INT32, OVERWRITE_RIGHT);
2094  GENERATE(Token::BIT_XOR, NUMBER, INT32, INT32, NO_OVERWRITE);
2095  GENERATE(Token::BIT_XOR, NUMBER, SMI, INT32, NO_OVERWRITE);
2096  GENERATE(Token::BIT_XOR, NUMBER, SMI, SMI, NO_OVERWRITE);
2097  GENERATE(Token::BIT_XOR, SMI, INT32, INT32, NO_OVERWRITE);
2098  GENERATE(Token::BIT_XOR, SMI, INT32, INT32, OVERWRITE_LEFT);
2099  GENERATE(Token::BIT_XOR, SMI, INT32, SMI, OVERWRITE_LEFT);
2100  GENERATE(Token::BIT_XOR, SMI, SMI, SMI, NO_OVERWRITE);
2101  GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_LEFT);
2102  GENERATE(Token::BIT_XOR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2103  GENERATE(Token::DIV, INT32, INT32, INT32, NO_OVERWRITE);
2104  GENERATE(Token::DIV, INT32, INT32, NUMBER, NO_OVERWRITE);
2105  GENERATE(Token::DIV, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2106  GENERATE(Token::DIV, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2107  GENERATE(Token::DIV, INT32, SMI, INT32, NO_OVERWRITE);
2108  GENERATE(Token::DIV, INT32, SMI, NUMBER, NO_OVERWRITE);
2109  GENERATE(Token::DIV, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2110  GENERATE(Token::DIV, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2111  GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2112  GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2113  GENERATE(Token::DIV, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
2114  GENERATE(Token::DIV, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2115  GENERATE(Token::DIV, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2116  GENERATE(Token::DIV, SMI, INT32, INT32, NO_OVERWRITE);
2117  GENERATE(Token::DIV, SMI, INT32, NUMBER, NO_OVERWRITE);
2118  GENERATE(Token::DIV, SMI, INT32, NUMBER, OVERWRITE_LEFT);
2119  GENERATE(Token::DIV, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2120  GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2121  GENERATE(Token::DIV, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2122  GENERATE(Token::DIV, SMI, SMI, NUMBER, NO_OVERWRITE);
2123  GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_LEFT);
2124  GENERATE(Token::DIV, SMI, SMI, NUMBER, OVERWRITE_RIGHT);
2125  GENERATE(Token::DIV, SMI, SMI, SMI, NO_OVERWRITE);
2126  GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_LEFT);
2127  GENERATE(Token::DIV, SMI, SMI, SMI, OVERWRITE_RIGHT);
2128  GENERATE(Token::MOD, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2129  GENERATE(Token::MOD, SMI, SMI, SMI, NO_OVERWRITE);
2130  GENERATE(Token::MOD, SMI, SMI, SMI, OVERWRITE_LEFT);
2131  GENERATE(Token::MUL, INT32, INT32, INT32, NO_OVERWRITE);
2132  GENERATE(Token::MUL, INT32, INT32, NUMBER, NO_OVERWRITE);
2133  GENERATE(Token::MUL, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2134  GENERATE(Token::MUL, INT32, NUMBER, NUMBER, OVERWRITE_LEFT);
2135  GENERATE(Token::MUL, INT32, SMI, INT32, NO_OVERWRITE);
2136  GENERATE(Token::MUL, INT32, SMI, INT32, OVERWRITE_LEFT);
2137  GENERATE(Token::MUL, INT32, SMI, NUMBER, NO_OVERWRITE);
2138  GENERATE(Token::MUL, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2139  GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2140  GENERATE(Token::MUL, NUMBER, INT32, NUMBER, OVERWRITE_RIGHT);
2141  GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2142  GENERATE(Token::MUL, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2143  GENERATE(Token::MUL, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2144  GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2145  GENERATE(Token::MUL, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
2146  GENERATE(Token::MUL, SMI, INT32, INT32, NO_OVERWRITE);
2147  GENERATE(Token::MUL, SMI, INT32, INT32, OVERWRITE_LEFT);
2148  GENERATE(Token::MUL, SMI, INT32, NUMBER, NO_OVERWRITE);
2149  GENERATE(Token::MUL, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2150  GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2151  GENERATE(Token::MUL, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2152  GENERATE(Token::MUL, SMI, SMI, INT32, NO_OVERWRITE);
2153  GENERATE(Token::MUL, SMI, SMI, NUMBER, NO_OVERWRITE);
2154  GENERATE(Token::MUL, SMI, SMI, NUMBER, OVERWRITE_LEFT);
2155  GENERATE(Token::MUL, SMI, SMI, SMI, NO_OVERWRITE);
2156  GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_LEFT);
2157  GENERATE(Token::MUL, SMI, SMI, SMI, OVERWRITE_RIGHT);
2158  GENERATE(Token::SAR, INT32, SMI, INT32, OVERWRITE_RIGHT);
2159  GENERATE(Token::SAR, INT32, SMI, SMI, NO_OVERWRITE);
2160  GENERATE(Token::SAR, INT32, SMI, SMI, OVERWRITE_RIGHT);
2161  GENERATE(Token::SAR, NUMBER, SMI, SMI, NO_OVERWRITE);
2162  GENERATE(Token::SAR, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
2163  GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_LEFT);
2164  GENERATE(Token::SAR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2165  GENERATE(Token::SHL, INT32, SMI, INT32, NO_OVERWRITE);
2166  GENERATE(Token::SHL, INT32, SMI, INT32, OVERWRITE_RIGHT);
2167  GENERATE(Token::SHL, INT32, SMI, SMI, NO_OVERWRITE);
2168  GENERATE(Token::SHL, INT32, SMI, SMI, OVERWRITE_RIGHT);
2169  GENERATE(Token::SHL, NUMBER, SMI, SMI, OVERWRITE_RIGHT);
2170  GENERATE(Token::SHL, SMI, SMI, INT32, NO_OVERWRITE);
2171  GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_LEFT);
2172  GENERATE(Token::SHL, SMI, SMI, INT32, OVERWRITE_RIGHT);
2173  GENERATE(Token::SHL, SMI, SMI, SMI, NO_OVERWRITE);
2174  GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_LEFT);
2175  GENERATE(Token::SHL, SMI, SMI, SMI, OVERWRITE_RIGHT);
2176  GENERATE(Token::SHR, INT32, SMI, SMI, NO_OVERWRITE);
2177  GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_LEFT);
2178  GENERATE(Token::SHR, INT32, SMI, SMI, OVERWRITE_RIGHT);
2179  GENERATE(Token::SHR, NUMBER, SMI, SMI, NO_OVERWRITE);
2180  GENERATE(Token::SHR, NUMBER, SMI, SMI, OVERWRITE_LEFT);
2181  GENERATE(Token::SHR, NUMBER, SMI, INT32, OVERWRITE_RIGHT);
2182  GENERATE(Token::SHR, SMI, SMI, SMI, NO_OVERWRITE);
2183  GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_LEFT);
2184  GENERATE(Token::SHR, SMI, SMI, SMI, OVERWRITE_RIGHT);
2185  GENERATE(Token::SUB, INT32, INT32, INT32, NO_OVERWRITE);
2186  GENERATE(Token::SUB, INT32, INT32, INT32, OVERWRITE_LEFT);
2187  GENERATE(Token::SUB, INT32, NUMBER, NUMBER, NO_OVERWRITE);
2188  GENERATE(Token::SUB, INT32, NUMBER, NUMBER, OVERWRITE_RIGHT);
2189  GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_LEFT);
2190  GENERATE(Token::SUB, INT32, SMI, INT32, OVERWRITE_RIGHT);
2191  GENERATE(Token::SUB, NUMBER, INT32, NUMBER, NO_OVERWRITE);
2192  GENERATE(Token::SUB, NUMBER, INT32, NUMBER, OVERWRITE_LEFT);
2193  GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, NO_OVERWRITE);
2194  GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_LEFT);
2195  GENERATE(Token::SUB, NUMBER, NUMBER, NUMBER, OVERWRITE_RIGHT);
2196  GENERATE(Token::SUB, NUMBER, SMI, NUMBER, NO_OVERWRITE);
2197  GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_LEFT);
2198  GENERATE(Token::SUB, NUMBER, SMI, NUMBER, OVERWRITE_RIGHT);
2199  GENERATE(Token::SUB, SMI, INT32, INT32, NO_OVERWRITE);
2200  GENERATE(Token::SUB, SMI, NUMBER, NUMBER, NO_OVERWRITE);
2201  GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_LEFT);
2202  GENERATE(Token::SUB, SMI, NUMBER, NUMBER, OVERWRITE_RIGHT);
2203  GENERATE(Token::SUB, SMI, SMI, SMI, NO_OVERWRITE);
2204  GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_LEFT);
2205  GENERATE(Token::SUB, SMI, SMI, SMI, OVERWRITE_RIGHT);
2206 #undef GENERATE
2207 #define GENERATE(op, left_kind, fixed_right_arg_value, result_kind, mode) \
2208  do { \
2209  State state(op, mode); \
2210  state.left_kind_ = left_kind; \
2211  state.fixed_right_arg_.has_value = true; \
2212  state.fixed_right_arg_.value = fixed_right_arg_value; \
2213  state.right_kind_ = SMI; \
2214  state.result_kind_ = result_kind; \
2215  Generate(isolate, state); \
2216  } while (false)
2217  GENERATE(Token::MOD, SMI, 2, SMI, NO_OVERWRITE);
2218  GENERATE(Token::MOD, SMI, 4, SMI, NO_OVERWRITE);
2219  GENERATE(Token::MOD, SMI, 4, SMI, OVERWRITE_LEFT);
2220  GENERATE(Token::MOD, SMI, 8, SMI, NO_OVERWRITE);
2221  GENERATE(Token::MOD, SMI, 16, SMI, OVERWRITE_LEFT);
2222  GENERATE(Token::MOD, SMI, 32, SMI, NO_OVERWRITE);
2223  GENERATE(Token::MOD, SMI, 2048, SMI, NO_OVERWRITE);
2224 #undef GENERATE
2225 }
2226 
2227 
2228 Type* BinaryOpIC::State::GetResultType(Zone* zone) const {
2229  Kind result_kind = result_kind_;
2230  if (HasSideEffects()) {
2231  result_kind = NONE;
2232  } else if (result_kind == GENERIC && op_ == Token::ADD) {
2233  return Type::Union(Type::Number(zone), Type::String(zone), zone);
2234  } else if (result_kind == NUMBER && op_ == Token::SHR) {
2235  return Type::Unsigned32(zone);
2236  }
2237  ASSERT_NE(GENERIC, result_kind);
2238  return KindToType(result_kind, zone);
2239 }
2240 
2241 
2242 void BinaryOpIC::State::Print(StringStream* stream) const {
2243  stream->Add("(%s", Token::Name(op_));
2244  if (mode_ == OVERWRITE_LEFT) stream->Add("_ReuseLeft");
2245  else if (mode_ == OVERWRITE_RIGHT) stream->Add("_ReuseRight");
2246  if (CouldCreateAllocationMementos()) stream->Add("_CreateAllocationMementos");
2247  stream->Add(":%s*", KindToString(left_kind_));
2248  if (fixed_right_arg_.has_value) {
2249  stream->Add("%d", fixed_right_arg_.value);
2250  } else {
2251  stream->Add("%s", KindToString(right_kind_));
2252  }
2253  stream->Add("->%s)", KindToString(result_kind_));
2254 }
2255 
2256 
2257 void BinaryOpIC::State::Update(Handle<Object> left,
2258  Handle<Object> right,
2259  Handle<Object> result) {
2260  ExtraICState old_extra_ic_state = GetExtraICState();
2261 
2262  left_kind_ = UpdateKind(left, left_kind_);
2263  right_kind_ = UpdateKind(right, right_kind_);
2264 
2265  int32_t fixed_right_arg_value = 0;
2266  bool has_fixed_right_arg =
2267  op_ == Token::MOD &&
2268  right->ToInt32(&fixed_right_arg_value) &&
2269  fixed_right_arg_value > 0 &&
2270  IsPowerOf2(fixed_right_arg_value) &&
2271  FixedRightArgValueField::is_valid(WhichPowerOf2(fixed_right_arg_value)) &&
2272  (left_kind_ == SMI || left_kind_ == INT32) &&
2273  (result_kind_ == NONE || !fixed_right_arg_.has_value);
2274  fixed_right_arg_ = Maybe<int32_t>(has_fixed_right_arg,
2275  fixed_right_arg_value);
2276 
2277  result_kind_ = UpdateKind(result, result_kind_);
2278 
2279  if (!Token::IsTruncatingBinaryOp(op_)) {
2280  Kind input_kind = Max(left_kind_, right_kind_);
2281  if (result_kind_ < input_kind && input_kind <= NUMBER) {
2282  result_kind_ = input_kind;
2283  }
2284  }
2285 
2286  // We don't want to distinguish INT32 and NUMBER for string add (because
2287  // NumberToString can't make use of this anyway).
2288  if (left_kind_ == STRING && right_kind_ == INT32) {
2289  ASSERT_EQ(STRING, result_kind_);
2290  ASSERT_EQ(Token::ADD, op_);
2291  right_kind_ = NUMBER;
2292  } else if (right_kind_ == STRING && left_kind_ == INT32) {
2293  ASSERT_EQ(STRING, result_kind_);
2294  ASSERT_EQ(Token::ADD, op_);
2295  left_kind_ = NUMBER;
2296  }
2297 
2298  // Reset overwrite mode unless we can actually make use of it, or may be able
2299  // to make use of it at some point in the future.
2300  if ((mode_ == OVERWRITE_LEFT && left_kind_ > NUMBER) ||
2301  (mode_ == OVERWRITE_RIGHT && right_kind_ > NUMBER) ||
2302  result_kind_ > NUMBER) {
2303  mode_ = NO_OVERWRITE;
2304  }
2305 
2306  if (old_extra_ic_state == GetExtraICState()) {
2307  // Tagged operations can lead to non-truncating HChanges
2308  if (left->IsUndefined() || left->IsBoolean()) {
2309  left_kind_ = GENERIC;
2310  } else if (right->IsUndefined() || right->IsBoolean()) {
2311  right_kind_ = GENERIC;
2312  } else {
2313  // Since the X87 is too precise, we might bail out on numbers which
2314  // actually would truncate with 64 bit precision.
2316  ASSERT(result_kind_ < NUMBER);
2317  result_kind_ = NUMBER;
2318  }
2319  }
2320 }
2321 
2322 
2323 BinaryOpIC::State::Kind BinaryOpIC::State::UpdateKind(Handle<Object> object,
2324  Kind kind) const {
2325  Kind new_kind = GENERIC;
2326  bool is_truncating = Token::IsTruncatingBinaryOp(op());
2327  if (object->IsBoolean() && is_truncating) {
2328  // Booleans will be automatically truncated by HChange.
2329  new_kind = INT32;
2330  } else if (object->IsUndefined()) {
2331  // Undefined will be automatically truncated by HChange.
2332  new_kind = is_truncating ? INT32 : NUMBER;
2333  } else if (object->IsSmi()) {
2334  new_kind = SMI;
2335  } else if (object->IsHeapNumber()) {
2336  double value = Handle<HeapNumber>::cast(object)->value();
2337  new_kind = IsInt32Double(value) ? INT32 : NUMBER;
2338  } else if (object->IsString() && op() == Token::ADD) {
2339  new_kind = STRING;
2340  }
2341  if (new_kind == INT32 && SmiValuesAre32Bits()) {
2342  new_kind = NUMBER;
2343  }
2344  if (kind != NONE &&
2345  ((new_kind <= NUMBER && kind > NUMBER) ||
2346  (new_kind > NUMBER && kind <= NUMBER))) {
2347  new_kind = GENERIC;
2348  }
2349  return Max(kind, new_kind);
2350 }
2351 
2352 
2353 // static
2354 const char* BinaryOpIC::State::KindToString(Kind kind) {
2355  switch (kind) {
2356  case NONE: return "None";
2357  case SMI: return "Smi";
2358  case INT32: return "Int32";
2359  case NUMBER: return "Number";
2360  case STRING: return "String";
2361  case GENERIC: return "Generic";
2362  }
2363  UNREACHABLE();
2364  return NULL;
2365 }
2366 
2367 
2368 // static
2369 Type* BinaryOpIC::State::KindToType(Kind kind, Zone* zone) {
2370  switch (kind) {
2371  case NONE: return Type::None(zone);
2372  case SMI: return Type::SignedSmall(zone);
2373  case INT32: return Type::Signed32(zone);
2374  case NUMBER: return Type::Number(zone);
2375  case STRING: return Type::String(zone);
2376  case GENERIC: return Type::Any(zone);
2377  }
2378  UNREACHABLE();
2379  return NULL;
2380 }
2381 
2382 
2383 MaybeObject* BinaryOpIC::Transition(Handle<AllocationSite> allocation_site,
2384  Handle<Object> left,
2385  Handle<Object> right) {
2387 
2388  // Compute the actual result using the builtin for the binary operation.
2389  Object* builtin = isolate()->js_builtins_object()->javascript_builtin(
2390  TokenToJSBuiltin(state.op()));
2391  Handle<JSFunction> function = handle(JSFunction::cast(builtin), isolate());
2392  bool caught_exception;
2394  isolate(), function, left, 1, &right, &caught_exception);
2395  if (caught_exception) return Failure::Exception();
2396 
2397  // Execution::Call can execute arbitrary JavaScript, hence potentially
2398  // update the state of this very IC, so we must update the stored state.
2399  UpdateTarget();
2400  // Compute the new state.
2401  State old_state(target()->extra_ic_state());
2402  state.Update(left, right, result);
2403 
2404  // Check if we have a string operation here.
2406  if (!allocation_site.is_null() || state.ShouldCreateAllocationMementos()) {
2407  // Setup the allocation site on-demand.
2408  if (allocation_site.is_null()) {
2409  allocation_site = isolate()->factory()->NewAllocationSite();
2410  }
2411 
2412  // Install the stub with an allocation site.
2413  BinaryOpICWithAllocationSiteStub stub(state);
2414  target = stub.GetCodeCopyFromTemplate(isolate(), allocation_site);
2415 
2416  // Sanity check the trampoline stub.
2417  ASSERT_EQ(*allocation_site, target->FindFirstAllocationSite());
2418  } else {
2419  // Install the generic stub.
2420  BinaryOpICStub stub(state);
2421  target = stub.GetCode(isolate());
2422 
2423  // Sanity check the generic stub.
2424  ASSERT_EQ(NULL, target->FindFirstAllocationSite());
2425  }
2426  set_target(*target);
2427 
2428  if (FLAG_trace_ic) {
2429  char buffer[150];
2430  NoAllocationStringAllocator allocator(
2431  buffer, static_cast<unsigned>(sizeof(buffer)));
2432  StringStream stream(&allocator);
2433  stream.Add("[BinaryOpIC");
2434  old_state.Print(&stream);
2435  stream.Add(" => ");
2436  state.Print(&stream);
2437  stream.Add(" @ %p <- ", static_cast<void*>(*target));
2438  stream.OutputToStdOut();
2439  JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2440  if (!allocation_site.is_null()) {
2441  PrintF(" using allocation site %p", static_cast<void*>(*allocation_site));
2442  }
2443  PrintF("]\n");
2444  }
2445 
2446  // Patch the inlined smi code as necessary.
2447  if (!old_state.UseInlinedSmiCode() && state.UseInlinedSmiCode()) {
2449  } else if (old_state.UseInlinedSmiCode() && !state.UseInlinedSmiCode()) {
2451  }
2452 
2453  return *result;
2454 }
2455 
2456 
2457 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_Miss) {
2458  HandleScope scope(isolate);
2459  ASSERT_EQ(2, args.length());
2460  Handle<Object> left = args.at<Object>(BinaryOpICStub::kLeft);
2461  Handle<Object> right = args.at<Object>(BinaryOpICStub::kRight);
2462  BinaryOpIC ic(isolate);
2463  return ic.Transition(Handle<AllocationSite>::null(), left, right);
2464 }
2465 
2466 
2467 RUNTIME_FUNCTION(MaybeObject*, BinaryOpIC_MissWithAllocationSite) {
2468  HandleScope scope(isolate);
2469  ASSERT_EQ(3, args.length());
2470  Handle<AllocationSite> allocation_site = args.at<AllocationSite>(
2471  BinaryOpWithAllocationSiteStub::kAllocationSite);
2472  Handle<Object> left = args.at<Object>(
2473  BinaryOpWithAllocationSiteStub::kLeft);
2474  Handle<Object> right = args.at<Object>(
2475  BinaryOpWithAllocationSiteStub::kRight);
2476  BinaryOpIC ic(isolate);
2477  return ic.Transition(allocation_site, left, right);
2478 }
2479 
2480 
2481 Code* CompareIC::GetRawUninitialized(Isolate* isolate, Token::Value op) {
2482  ICCompareStub stub(op, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED);
2483  Code* code = NULL;
2484  CHECK(stub.FindCodeInCache(&code, isolate));
2485  return code;
2486 }
2487 
2488 
2491  return stub.GetCode(isolate);
2492 }
2493 
2494 
2495 const char* CompareIC::GetStateName(State state) {
2496  switch (state) {
2497  case UNINITIALIZED: return "UNINITIALIZED";
2498  case SMI: return "SMI";
2499  case NUMBER: return "NUMBER";
2500  case INTERNALIZED_STRING: return "INTERNALIZED_STRING";
2501  case STRING: return "STRING";
2502  case UNIQUE_NAME: return "UNIQUE_NAME";
2503  case OBJECT: return "OBJECT";
2504  case KNOWN_OBJECT: return "KNOWN_OBJECT";
2505  case GENERIC: return "GENERIC";
2506  }
2507  UNREACHABLE();
2508  return NULL;
2509 }
2510 
2511 
2513  Zone* zone,
2514  CompareIC::State state,
2515  Handle<Map> map) {
2516  switch (state) {
2517  case CompareIC::UNINITIALIZED: return Type::None(zone);
2518  case CompareIC::SMI: return Type::SignedSmall(zone);
2519  case CompareIC::NUMBER: return Type::Number(zone);
2520  case CompareIC::STRING: return Type::String(zone);
2521  case CompareIC::INTERNALIZED_STRING: return Type::InternalizedString(zone);
2522  case CompareIC::UNIQUE_NAME: return Type::UniqueName(zone);
2523  case CompareIC::OBJECT: return Type::Receiver(zone);
2525  return map.is_null() ? Type::Receiver(zone) : Type::Class(map, zone);
2526  case CompareIC::GENERIC: return Type::Any(zone);
2527  }
2528  UNREACHABLE();
2529  return NULL;
2530 }
2531 
2532 
2533 void CompareIC::StubInfoToType(int stub_minor_key,
2534  Type** left_type,
2535  Type** right_type,
2536  Type** overall_type,
2537  Handle<Map> map,
2538  Zone* zone) {
2539  State left_state, right_state, handler_state;
2540  ICCompareStub::DecodeMinorKey(stub_minor_key, &left_state, &right_state,
2541  &handler_state, NULL);
2542  *left_type = StateToType(zone, left_state);
2543  *right_type = StateToType(zone, right_state);
2544  *overall_type = StateToType(zone, handler_state, map);
2545 }
2546 
2547 
2549  Handle<Object> value) {
2550  switch (old_state) {
2551  case UNINITIALIZED:
2552  if (value->IsSmi()) return SMI;
2553  if (value->IsHeapNumber()) return NUMBER;
2554  if (value->IsInternalizedString()) return INTERNALIZED_STRING;
2555  if (value->IsString()) return STRING;
2556  if (value->IsSymbol()) return UNIQUE_NAME;
2557  if (value->IsJSObject()) return OBJECT;
2558  break;
2559  case SMI:
2560  if (value->IsSmi()) return SMI;
2561  if (value->IsHeapNumber()) return NUMBER;
2562  break;
2563  case NUMBER:
2564  if (value->IsNumber()) return NUMBER;
2565  break;
2566  case INTERNALIZED_STRING:
2567  if (value->IsInternalizedString()) return INTERNALIZED_STRING;
2568  if (value->IsString()) return STRING;
2569  if (value->IsSymbol()) return UNIQUE_NAME;
2570  break;
2571  case STRING:
2572  if (value->IsString()) return STRING;
2573  break;
2574  case UNIQUE_NAME:
2575  if (value->IsUniqueName()) return UNIQUE_NAME;
2576  break;
2577  case OBJECT:
2578  if (value->IsJSObject()) return OBJECT;
2579  break;
2580  case GENERIC:
2581  break;
2582  case KNOWN_OBJECT:
2583  UNREACHABLE();
2584  break;
2585  }
2586  return GENERIC;
2587 }
2588 
2589 
2590 CompareIC::State CompareIC::TargetState(State old_state,
2591  State old_left,
2592  State old_right,
2593  bool has_inlined_smi_code,
2594  Handle<Object> x,
2595  Handle<Object> y) {
2596  switch (old_state) {
2597  case UNINITIALIZED:
2598  if (x->IsSmi() && y->IsSmi()) return SMI;
2599  if (x->IsNumber() && y->IsNumber()) return NUMBER;
2601  // Ordered comparisons treat undefined as NaN, so the
2602  // NUMBER stub will do the right thing.
2603  if ((x->IsNumber() && y->IsUndefined()) ||
2604  (y->IsNumber() && x->IsUndefined())) {
2605  return NUMBER;
2606  }
2607  }
2608  if (x->IsInternalizedString() && y->IsInternalizedString()) {
2609  // We compare internalized strings as plain ones if we need to determine
2610  // the order in a non-equality compare.
2612  }
2613  if (x->IsString() && y->IsString()) return STRING;
2614  if (!Token::IsEqualityOp(op_)) return GENERIC;
2615  if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
2616  if (x->IsJSObject() && y->IsJSObject()) {
2617  if (Handle<JSObject>::cast(x)->map() ==
2618  Handle<JSObject>::cast(y)->map()) {
2619  return KNOWN_OBJECT;
2620  } else {
2621  return OBJECT;
2622  }
2623  }
2624  return GENERIC;
2625  case SMI:
2626  return x->IsNumber() && y->IsNumber() ? NUMBER : GENERIC;
2627  case INTERNALIZED_STRING:
2629  if (x->IsString() && y->IsString()) return STRING;
2630  if (x->IsUniqueName() && y->IsUniqueName()) return UNIQUE_NAME;
2631  return GENERIC;
2632  case NUMBER:
2633  // If the failure was due to one side changing from smi to heap number,
2634  // then keep the state (if other changed at the same time, we will get
2635  // a second miss and then go to generic).
2636  if (old_left == SMI && x->IsHeapNumber()) return NUMBER;
2637  if (old_right == SMI && y->IsHeapNumber()) return NUMBER;
2638  return GENERIC;
2639  case KNOWN_OBJECT:
2641  if (x->IsJSObject() && y->IsJSObject()) return OBJECT;
2642  return GENERIC;
2643  case STRING:
2644  case UNIQUE_NAME:
2645  case OBJECT:
2646  case GENERIC:
2647  return GENERIC;
2648  }
2649  UNREACHABLE();
2650  return GENERIC; // Make the compiler happy.
2651 }
2652 
2653 
2655  HandleScope scope(isolate());
2656  State previous_left, previous_right, previous_state;
2657  ICCompareStub::DecodeMinorKey(target()->stub_info(), &previous_left,
2658  &previous_right, &previous_state, NULL);
2659  State new_left = NewInputState(previous_left, x);
2660  State new_right = NewInputState(previous_right, y);
2661  State state = TargetState(previous_state, previous_left, previous_right,
2662  HasInlinedSmiCode(address()), x, y);
2663  ICCompareStub stub(op_, new_left, new_right, state);
2664  if (state == KNOWN_OBJECT) {
2665  stub.set_known_map(
2667  }
2668  Handle<Code> new_target = stub.GetCode(isolate());
2669  set_target(*new_target);
2670 
2671  if (FLAG_trace_ic) {
2672  PrintF("[CompareIC in ");
2673  JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
2674  PrintF(" ((%s+%s=%s)->(%s+%s=%s))#%s @ %p]\n",
2675  GetStateName(previous_left),
2676  GetStateName(previous_right),
2677  GetStateName(previous_state),
2678  GetStateName(new_left),
2679  GetStateName(new_right),
2680  GetStateName(state),
2681  Token::Name(op_),
2682  static_cast<void*>(*stub.GetCode(isolate())));
2683  }
2684 
2685  // Activate inlined smi code.
2686  if (previous_state == UNINITIALIZED) {
2688  }
2689 
2690  return *new_target;
2691 }
2692 
2693 
2694 // Used from ICCompareStub::GenerateMiss in code-stubs-<arch>.cc.
2695 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2696  HandleScope scope(isolate);
2697  ASSERT(args.length() == 3);
2698  CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2699  return ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2700 }
2701 
2702 
2704  Code* target,
2705  ConstantPoolArray* constant_pool) {
2706  if (IsCleared(target)) return;
2707  ExtraICState state = target->extra_ic_state();
2708 
2710  stub.ClearState();
2711 
2712  Code* code = NULL;
2713  CHECK(stub.FindCodeInCache(&code, target->GetIsolate()));
2714 
2715  SetTargetAtAddress(address, code, constant_pool);
2716 }
2717 
2718 
2720  Handle<Object> object) {
2721  if (object->IsNull() || object->IsUndefined()) {
2722  return Smi::FromInt(true);
2723  }
2724  return Smi::FromInt(object->IsUndetectableObject());
2725 }
2726 
2727 
2729  ExtraICState extra_ic_state = target()->extra_ic_state();
2730 
2731  CompareNilICStub stub(extra_ic_state);
2732 
2733  // Extract the current supported types from the patched IC and calculate what
2734  // types must be supported as a result of the miss.
2735  bool already_monomorphic = stub.IsMonomorphic();
2736 
2737  stub.UpdateStatus(object);
2738 
2739  NilValue nil = stub.GetNilValue();
2740 
2741  // Find or create the specialized stub to support the new set of types.
2743  if (stub.IsMonomorphic()) {
2744  Handle<Map> monomorphic_map(already_monomorphic
2745  ? target()->FindFirstMap()
2746  : HeapObject::cast(*object)->map());
2747  code = isolate()->stub_cache()->ComputeCompareNil(monomorphic_map, stub);
2748  } else {
2749  code = stub.GetCode(isolate());
2750  }
2751  set_target(*code);
2752  return DoCompareNilSlow(nil, object);
2753 }
2754 
2755 
2756 RUNTIME_FUNCTION(MaybeObject*, CompareNilIC_Miss) {
2757  HandleScope scope(isolate);
2758  Handle<Object> object = args.at<Object>(0);
2759  CompareNilIC ic(isolate);
2760  return ic.CompareNil(object);
2761 }
2762 
2763 
2764 RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
2765  UNREACHABLE();
2766  CHECK(false);
2767  return isolate->heap()->undefined_value();
2768 }
2769 
2770 
2772  switch (op) {
2773  default:
2774  UNREACHABLE();
2775  case Token::ADD:
2776  return Builtins::ADD;
2777  break;
2778  case Token::SUB:
2779  return Builtins::SUB;
2780  break;
2781  case Token::MUL:
2782  return Builtins::MUL;
2783  break;
2784  case Token::DIV:
2785  return Builtins::DIV;
2786  break;
2787  case Token::MOD:
2788  return Builtins::MOD;
2789  break;
2790  case Token::BIT_OR:
2791  return Builtins::BIT_OR;
2792  break;
2793  case Token::BIT_AND:
2794  return Builtins::BIT_AND;
2795  break;
2796  case Token::BIT_XOR:
2797  return Builtins::BIT_XOR;
2798  break;
2799  case Token::SAR:
2800  return Builtins::SAR;
2801  break;
2802  case Token::SHR:
2803  return Builtins::SHR;
2804  break;
2805  case Token::SHL:
2806  return Builtins::SHL;
2807  break;
2808  }
2809 }
2810 
2811 
2813  ToBooleanStub stub(target()->extra_ic_state());
2814  bool to_boolean_value = stub.UpdateStatus(object);
2815  Handle<Code> code = stub.GetCode(isolate());
2816  set_target(*code);
2817  return Smi::FromInt(to_boolean_value ? 1 : 0);
2818 }
2819 
2820 
2821 RUNTIME_FUNCTION(MaybeObject*, ToBooleanIC_Miss) {
2822  ASSERT(args.length() == 1);
2823  HandleScope scope(isolate);
2824  Handle<Object> object = args.at<Object>(0);
2825  ToBooleanIC ic(isolate);
2826  return ic.ToBoolean(object);
2827 }
2828 
2829 
2830 static const Address IC_utilities[] = {
2831 #define ADDR(name) FUNCTION_ADDR(name),
2833  NULL
2834 #undef ADDR
2835 };
2836 
2837 
2839  return IC_utilities[id];
2840 }
2841 
2842 
2843 } } // namespace v8::internal
byte * Address
Definition: globals.h:186
static Handle< Code > initialize_stub(Isolate *isolate, StrictMode strict_mode)
Definition: ic.cc:1267
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
Object * type_feedback_info()
Definition: objects-inl.h:5819
static Handle< 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:12410
Handle< Code > ComputeLoadNonexistent(Handle< Name > name, Handle< HeapType > type)
Definition: stub-cache.cc:171
ExtraICState extra_ic_state() const
Definition: ic.h:245
void CopyICToMegamorphicCache(Handle< String > name)
Definition: ic.cc:727
virtual Handle< Code > slow_stub() const
Definition: ic.h:532
Code * builtin(Name name)
Definition: builtins.h:322
static ExtraICState ComputeExtraICState(StrictMode flag)
Definition: ic.h:482
static bool IsTruncatingBinaryOp(Value op)
Definition: token.h:216
static ConstantPoolArray * cast(Object *obj)
static MUST_USE_RESULT MaybeObject * DoCompareNilSlow(NilValue nil, Handle< Object > object)
Definition: ic.cc:2719
void UpdateState(Handle< Object > receiver, Handle< Object > name)
Definition: ic.cc:339
MUST_USE_RESULT MaybeObject * Load(Handle< Object > object, Handle< String > name)
Definition: ic.cc:530
i::Handle< i::Map > AsClass()
Definition: types.h:262
void set(int index, Object *value)
Definition: objects-inl.h:2147
PropertyCell * GetPropertyCell(LookupResult *result)
Definition: objects.cc:14745
void PrintF(const char *format,...)
Definition: v8utils.cc:40
static void DecodeMinorKey(int minor_key, CompareIC::State *left_state, CompareIC::State *right_state, CompareIC::State *handler_state, Token::Value *op)
Definition: code-stubs.cc:350
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf map
Definition: flags.cc:350
static HeapObject * GetCodeCacheHolder(Isolate *isolate, Object *object, InlineCacheHolderFlag holder)
Definition: ic-inl.h:160
static TypeFeedbackInfo * cast(Object *obj)
virtual Code::Kind kind() const
Definition: ic.h:224
Isolate * isolate()
Definition: heap-inl.h:624
int unused_property_fields()
Definition: objects-inl.h:4022
static const char * Name(Value tok)
Definition: token.h:198
static Smi * FromInt(int value)
Definition: objects-inl.h:1209
#define LOG(isolate, Call)
Definition: log.h:86
virtual void UpdateMegamorphicCache(HeapType *type, Name *name, Code *code)
Definition: ic.cc:844
static Handle< Map > GeneralizeRepresentation(Handle< Map > map, int modify_index, Representation new_representation, StoreMode store_mode)
Definition: objects.cc:2666
static Handle< Code > GetUninitialized(Isolate *isolate, Token::Value op)
Definition: ic.cc:2489
bool is_target_set()
Definition: ic.h:174
Code * UpdateCaches(Handle< Object > x, Handle< Object > y)
Definition: ic.cc:2654
static HeapObject * cast(Object *obj)
static Handle< T > cast(Handle< S > that)
Definition: handles.h:75
static void Clear(Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic.cc:2703
T Max(T a, T b)
Definition: utils.h:227
static Map * cast(Object *obj)
static State NewInputState(State old_state, Handle< Object > value)
Definition: ic.cc:2548
virtual Handle< Code > CompileHandler(LookupResult *lookup, Handle< Object > object, Handle< String > name, Handle< Object > value, InlineCacheHolderFlag cache_holder)
Definition: ic.h:200
T & at(int i) const
Definition: list.h:90
void set_known_map(Handle< Map > map)
Definition: code-stubs.h:1342
TypeImpl< ZoneTypeConfig > Type
Builtins * builtins()
Definition: isolate.h:948
int int32_t
Definition: unicode.cc:47
KeyedAccessStoreMode
Definition: objects.h:164
static bool IsSupported(CpuFeature f)
Definition: assembler-arm.h:68
static Failure * Exception()
Definition: objects-inl.h:1244
static void Clear(Isolate *isolate, Address address, ConstantPoolArray *constant_pool)
Definition: ic.cc:429
bool is_inobject(Handle< JSObject > holder)
Definition: property.h:153
Map * LookupElementsTransitionMap(ElementsKind elements_kind)
Definition: objects.cc:3265
Handle< Code > LoadElementStub(Handle< JSObject > receiver)
Definition: ic.cc:1020
void UpdateTarget()
Definition: ic.h:251
Address address() const
Definition: ic-inl.h:41
void change_ic_with_type_info_count(int count)
Definition: objects-inl.h:6716
Failure * TypeError(const char *type, Handle< Object > object, Handle< Object > key)
Definition: ic.cc:369
#define ASSERT(condition)
Definition: checks.h:329
int translate(Handle< JSObject > holder)
Definition: property.h:158
void set_profiler_ticks(int ticks)
Definition: objects-inl.h:4461
Handle< Code > ComputeKeyedLoadElement(Handle< Map > receiver_map)
Definition: stub-cache.cc:207
static bool IsSafeForSnapshot(CpuFeature f)
Definition: assembler-arm.h:78
Isolate * isolate() const
Definition: ic.h:157
i::Handle< i::Object > AsConstant()
Definition: types.h:263
#define CHECK(condition)
Definition: checks.h:75
static const int kCallerFPOffset
Definition: frames.h:188
static Handle< Code > initialize_stub(Isolate *isolate, ExtraICState extra_state)
Definition: ic.cc:782
void TryRemoveInvalidHandlers(Handle< Map > map, Handle< String > name)
Definition: ic.cc:325
#define RETURN_IF_EMPTY_HANDLE(isolate, call)
Definition: isolate.h:151
int WhichPowerOf2(uint32_t x)
Definition: utils.h:57
Factory * factory()
Definition: isolate.h:995
PropertyAttributes
bool IsOutOfBoundsAccess(Handle< JSObject > receiver, int index)
Definition: ic.cc:1574
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check)
static Smi * cast(Object *object)
MaybeObject * Transition(Handle< AllocationSite > allocation_site, Handle< Object > left, Handle< Object > right) V8_WARN_UNUSED_RESULT
Definition: ic.cc:2383
StrictMode strict_mode() const
Definition: ic.h:499
int isnan(double x)
MUST_USE_RESULT MaybeObject * Store(Handle< Object > object, Handle< Object > name, Handle< Object > value)
Definition: ic.cc:1662
void Add(Vector< const char > format, Vector< FmtElm > elms)
static void TransitionElementsKind(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:12779
static void StubInfoToType(int stub_minor_key, Type **left_type, Type **right_type, Type **overall_type, Handle< Map > map, Zone *zone)
Definition: ic.cc:2533
MUST_USE_RESULT MaybeObject * AllocateHeapNumber(double value, PretenureFlag pretenure=NOT_TENURED)
Definition: heap.cc:2969
virtual Handle< Code > pre_monomorphic_stub()
Definition: ic.h:628
bool IsTransitionOfMonomorphicTarget(Map *source_map, Map *target_map)
Definition: ic.cc:738
V8_INLINE bool IsNull() const
Definition: v8.h:6247
HANDLE HANDLE LPSTACKFRAME64 StackFrame
static const int kCallerPCOffset
Definition: frames-arm.h:123
#define UNREACHABLE()
Definition: checks.h:52
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_string(expose_natives_as
Handle< Object > NewReferenceError(const char *message, Vector< Handle< Object > > args)
Definition: factory.cc:1072
static void PostPatching(Address address, Code *target, Code *old_target)
Definition: ic.cc:398
void UpdateStatus(Handle< Object > object)
Definition: code-stubs.cc:407
static const int kLengthOffset
Definition: objects.h:8905
virtual Handle< Code > megamorphic_stub()
Definition: ic.h:232
void PatchCache(Handle< HeapType > type, Handle< String > name, Handle< Code > code)
Definition: ic.cc:753
void UpdateMonomorphicIC(Handle< HeapType > type, Handle< Code > handler, Handle< String > name)
Definition: ic.cc:717
static Address c_entry_fp(ThreadLocalTop *thread)
Definition: isolate.h:648
virtual Handle< Code > CompileHandler(LookupResult *lookup, Handle< Object > object, Handle< String > name, Handle< Object > value, InlineCacheHolderFlag cache_holder)
Definition: ic.cc:1309
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage including flags
Definition: flags.cc:665
bool IsSymbol() const
Definition: api.cc:2369
Handle< Code > ComputeMonomorphicIC(Code::Kind kind, Handle< Name > name, Handle< HeapType > type, Handle< Code > handler, ExtraICState extra_ic_state)
Definition: stub-cache.cc:129
Address fp() const
Definition: ic.h:155
static InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags)
Definition: objects-inl.h:4651
IC(FrameDepth depth, Isolate *isolate)
Definition: ic.cc:122
StackFrame * frame() const
Definition: frames.h:863
bool FitsRepresentation(Representation representation)
Definition: objects.h:1507
static Handle< HeapType > CurrentTypeOf(Handle< Object > object, Isolate *isolate)
Definition: ic.cc:676
RuntimeProfiler * runtime_profiler()
Definition: isolate.h:866
static const int kCallerFPOffset
Definition: frames-arm.h:121
Local< Value > GetPrototype()
Definition: api.cc:3192
Handle< Code > ComputePolymorphicIC(Code::Kind kind, TypeHandleList *types, CodeHandleList *handlers, int number_of_valid_maps, Handle< Name > name, ExtraICState extra_ic_state)
Definition: stub-cache.cc:374
Handle< Code > ComputeStore(InlineCacheState ic_state, ExtraICState extra_state)
Definition: stub-cache.cc:300
NilValue
Definition: v8.h:133
static bool IsValid(intptr_t value)
Definition: objects-inl.h:1278
virtual Handle< Code > generic_stub() const
Definition: ic.cc:1281
virtual Handle< Code > megamorphic_stub()
Definition: ic.cc:1276
static Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:3313
static void PrintTop(Isolate *isolate, FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:804
const int kPointerSize
Definition: globals.h:268
Handle< Object > NewTypeError(const char *message, Vector< Handle< Object > > args)
Definition: factory.cc:1039
NilValue GetNilValue() const
Definition: code-stubs.h:1444
static KeyedAccessStoreMode GetKeyedAccessStoreMode(ExtraICState extra_state)
Definition: ic.h:597
static Address & Address_at(Address addr)
Definition: v8memory.h:79
static void UpdateMapCodeCache(Handle< HeapObject > object, Handle< Name > name, Handle< Code > code)
Definition: objects.cc:4552
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
static const int kConstantPoolOffset
Definition: frames.h:186
bool IsUndeclaredGlobal(Handle< Object > receiver)
Definition: ic.h:329
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
static bool IsCleared(Code *code)
Definition: ic.h:133
State state() const
Definition: ic.h:94
virtual Code::Kind kind() const
Definition: ic.h:526
#define ASSERT_LE(v1, v2)
Definition: checks.h:334
static const int kCallerPCOffset
Definition: frames.h:189
Handle< AllocationSite > NewAllocationSite()
Definition: factory.cc:801
Handle< Code > ComputeKeyedStoreElement(Handle< Map > receiver_map, StrictMode strict_mode, KeyedAccessStoreMode store_mode)
Definition: stub-cache.cc:223
bool is_inline_cache_stub()
Definition: objects-inl.h:4568
Handle< Code > ComputeHandler(LookupResult *lookup, Handle< Object > object, Handle< String > name, Handle< Object > value=Handle< Code >::null())
Definition: ic.cc:852
static Type * StateToType(Zone *zone, State state, Handle< Map > map=Handle< Map >())
Definition: ic.cc:2512
static Handle< Object > GetElementOrCharAt(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: runtime.cc:4924
Handle< JSBuiltinsObject > js_builtins_object()
Definition: isolate.h:680
Definition: v8.h:123
void MarkMonomorphicPrototypeFailure()
Definition: ic.h:99
bool IsPowerOf2(T x)
Definition: utils.h:51
PropertyDetails GetDetails(int descriptor_number)
Definition: objects-inl.h:2652
static JavaScriptFrame * cast(StackFrame *frame)
Definition: frames.h:635
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:923
virtual Code::Kind kind() const
Definition: ic.h:355
InlineCacheState ic_state()
Definition: objects-inl.h:4308
static bool IsEqualityOp(Value op)
Definition: token.h:228
V8_INLINE bool IsUndefined() const
Definition: v8.h:6229
static void SetTargetAtAddress(Address address, Code *target, ConstantPoolArray *constant_pool)
Definition: ic-inl.h:124
#define ADDR(name)
static Code * GetTargetAtAddress(Address address, ConstantPoolArray *constant_pool)
Definition: ic-inl.h:112
MUST_USE_RESULT MaybeObject * GetProperty(Name *key)
Definition: objects-inl.h:1081
static JSArray * cast(Object *obj)
StubCache * stub_cache()
Definition: isolate.h:877
bool UpdateStatus(Handle< Object > object)
Definition: code-stubs.cc:618
static StrictMode GetStrictMode(ExtraICState state)
Definition: ic.h:485
Handle< Code > ComputeLoad(InlineCacheState ic_state, ExtraICState extra_state)
Definition: stub-cache.cc:276
V8_INLINE bool IsString() const
Definition: v8.h:6265
bool Is(TypeImpl *that)
Definition: types.h:246
#define TRACE_IC(type, name)
Definition: ic.cc:119
virtual Handle< Code > generic_stub() const
Definition: ic.h:236
Definition: v8.h:2107
void UpdateCaches(LookupResult *lookup, Handle< JSObject > receiver, Handle< String > name, Handle< Object > value)
Definition: ic.cc:1293
virtual Handle< Code > generic_stub() const
Definition: ic.h:443
InlineCacheState State
Definition: ic.h:80
static void MigrateInstance(Handle< JSObject > instance)
Definition: objects.cc:3852
#define GENERATE(op, left_kind, right_kind, result_kind, mode)
MaybeObject * ToBoolean(Handle< Object > object)
Definition: ic.cc:2812
static Handle< Object > SetElementsLength(Handle< JSArray > array, Handle< Object > length)
Definition: objects.cc:11330
void Set(int index, const T &element)
Definition: list-inl.h:107
MUST_USE_RESULT MaybeObject * Store(Handle< Object > object, Handle< String > name, Handle< Object > value, JSReceiver::StoreFromKeyed store_mode=JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED)
Definition: ic.cc:1189
bool TryRemoveInvalidPrototypeDependentStub(Handle< Object > receiver, Handle< String > name)
Definition: ic.cc:249
static Handle< Object > Call(Isolate *isolate, Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:153
#define IC_UTIL_LIST(ICU)
Definition: ic.h:42
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
Definition: objects.cc:2858
bool is_null() const
Definition: handles.h:81
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:103
static InlineCacheHolderFlag GetCodeCacheForObject(Object *object)
Definition: ic-inl.h:150
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
Definition: flags.cc:317
bool IsNumber() const
Definition: api.cc:2416
#define TRACE_GENERIC_IC(isolate, type, reason)
Definition: ic.cc:116
static MUST_USE_RESULT MaybeObject * GetObjectPropertyOrFail(Isolate *isolate, Handle< Object > object, Handle< Object > key)
Definition: runtime.cc:4982
Handle< Code > ComputeCompareNil(Handle< Map > receiver_map, CompareNilICStub &stub)
Definition: stub-cache.cc:327
void LocalLookupRealNamedProperty(Name *name, LookupResult *result)
Definition: objects.cc:3371
static Handle< HeapType > UpdatedType(Handle< PropertyCell > cell, Handle< Object > value)
Definition: objects.cc:16392
bool is_observed()
Definition: objects.h:5930
static Handle< T > null()
Definition: handles.h:80
static T::TypeHandle MapToType(Handle< Map > map, typename T::Region *region)
Definition: ic.cc:696
Representation OptimalRepresentation(ValueType type=OPTIMAL_REPRESENTATION)
Definition: objects.h:1489
#define ASSERT_EQ(v1, v2)
Definition: checks.h:330
Handle< Code > ComputeStoreElementPolymorphic(MapHandleList *receiver_maps, KeyedAccessStoreMode store_mode, StrictMode strict_mode)
Definition: stub-cache.cc:397
MUST_USE_RESULT MaybeObject * Load(Handle< Object > object, Handle< Object > key)
Definition: ic.cc:1083
#define ASSERT_NE(v1, v2)
Definition: checks.h:331
static FixedArray * cast(Object *obj)
static Builtins::JavaScript TokenToJSBuiltin(Token::Value op)
Definition: ic.cc:2771
void Print(const v8::FunctionCallbackInfo< v8::Value > &args)
ElementsKind elements_kind()
Definition: objects.h:5945
MUST_USE_RESULT MaybeObject * CompareNil(Handle< Object > object)
Definition: ic.cc:2728
static Handle< Object > SetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr, StrictMode strict_mode)
Definition: runtime.cc:5283
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:39
static TypeHandle Constant(i::Handle< i::Object > value, Region *region)
Definition: types.h:235
int ExtraICState
Definition: objects.h:310
Code * Set(Name *name, Map *map, Code *code)
Definition: stub-cache.cc:59
static TypeHandle OfCurrently(i::Handle< i::Object > value, Region *region)
Definition: types.cc:274
Handle< Code > StoreElementStub(Handle< JSObject > receiver, KeyedAccessStoreMode store_mode)
Definition: ic.cc:1414
void set_target(Code *code)
Definition: ic.h:169
virtual Handle< Code > megamorphic_stub()
Definition: ic.cc:794
static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region *reg)
void UpdateCaches(LookupResult *lookup, Handle< Object > object, Handle< String > name)
Definition: ic.cc:812
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:118
static TypeHandle Class(i::Handle< i::Map > map, Region *region)
Definition: types.h:232
const int kMaxKeyedPolymorphism
Definition: ic.h:37
static Handle< Object > FunctionGetPrototype(Handle< JSFunction > object)
Definition: accessors.cc:537
static GlobalObject * cast(Object *obj)
static const char * GetStateName(State state)
Definition: ic.cc:2495
Handle< Code > target() const
Definition: ic.h:153
virtual Handle< Code > slow_stub() const
Definition: ic.h:365
ThreadLocalTop * thread_local_top()
Definition: isolate.h:879
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
static Address AddressFromUtilityId(UtilityId id)
Definition: ic.cc:2838
static const int kConstantPoolOffset
Definition: frames-arm.h:115
Failure * ReferenceError(const char *type, Handle< String > name)
Definition: ic.cc:380
ExtraICState extra_ic_state()
Definition: objects-inl.h:4320
static JSObject * cast(Object *obj)
void set_target(Code *code)
Definition: ic.h:357
JSFunction * function() const
Definition: frames-inl.h:284
virtual Handle< Code > CompileHandler(LookupResult *lookup, Handle< Object > object, Handle< String > name, Handle< Object > unused, InlineCacheHolderFlag cache_holder)
Definition: ic.cc:878
bool UpdatePolymorphicIC(Handle< HeapType > type, Handle< String > name, Handle< Code > code)
Definition: ic.cc:620
int FastD2I(double x)
Definition: conversions.h:74
virtual Handle< Code > pre_monomorphic_stub()
Definition: ic.h:536
static bool IsOrderedRelationalCompareOp(Value op)
Definition: token.h:224
Handle< Code > FindHandler(Handle< Name > name, Handle< Map > map, Code::Kind kind, InlineCacheHolderFlag cache_holder, Code::StubType type)
Definition: stub-cache.cc:116
Handle< Code > ComputeLoadElementPolymorphic(MapHandleList *receiver_maps)
Definition: stub-cache.cc:349
static Handle< Map > TypeToMap(HeapType *type, Isolate *isolate)
Definition: ic.cc:683
static JSFunction * cast(Object *obj)