v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ic.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "accessors.h"
31 #include "api.h"
32 #include "arguments.h"
33 #include "codegen.h"
34 #include "execution.h"
35 #include "ic-inl.h"
36 #include "runtime.h"
37 #include "stub-cache.h"
38 
39 namespace v8 {
40 namespace internal {
41 
42 #ifdef DEBUG
43 char IC::TransitionMarkFromState(IC::State state) {
44  switch (state) {
45  case UNINITIALIZED: return '0';
46  case PREMONOMORPHIC: return 'P';
47  case MONOMORPHIC: return '1';
48  case MONOMORPHIC_PROTOTYPE_FAILURE: return '^';
49  case MEGAMORPHIC: return IsGeneric() ? 'G' : 'N';
50 
51  // We never see the debugger states here, because the state is
52  // computed from the original code - not the patched code. Let
53  // these cases fall through to the unreachable code below.
54  case DEBUG_BREAK: break;
55  case DEBUG_PREPARE_STEP_IN: break;
56  }
57  UNREACHABLE();
58  return 0;
59 }
60 
61 void IC::TraceIC(const char* type,
62  Handle<Object> name,
63  State old_state,
64  Code* new_target) {
65  if (FLAG_trace_ic) {
66  State new_state = StateFrom(new_target,
67  HEAP->undefined_value(),
68  HEAP->undefined_value());
69  PrintF("[%s in ", type);
70  StackFrameIterator it;
71  while (it.frame()->fp() != this->fp()) it.Advance();
72  StackFrame* raw_frame = it.frame();
73  if (raw_frame->is_internal()) {
74  Isolate* isolate = new_target->GetIsolate();
75  Code* apply_builtin = isolate->builtins()->builtin(
76  Builtins::kFunctionApply);
77  if (raw_frame->unchecked_code() == apply_builtin) {
78  PrintF("apply from ");
79  it.Advance();
80  raw_frame = it.frame();
81  }
82  }
83  JavaScriptFrame::PrintTop(stdout, false, true);
84  bool new_can_grow =
85  Code::GetKeyedAccessGrowMode(new_target->extra_ic_state()) ==
87  PrintF(" (%c->%c%s)",
88  TransitionMarkFromState(old_state),
89  TransitionMarkFromState(new_state),
90  new_can_grow ? ".GROW" : "");
91  name->Print();
92  PrintF("]\n");
93  }
94 }
95 
96 #define TRACE_GENERIC_IC(type, reason) \
97  do { \
98  if (FLAG_trace_ic) { \
99  PrintF("[%s patching generic stub in ", type); \
100  JavaScriptFrame::PrintTop(stdout, false, true); \
101  PrintF(" (%s)]\n", reason); \
102  } \
103  } while (false)
104 
105 #else
106 #define TRACE_GENERIC_IC(type, reason)
107 #endif // DEBUG
108 
109 #define TRACE_IC(type, name, old_state, new_target) \
110  ASSERT((TraceIC(type, name, old_state, new_target), true))
111 
112 IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
113  ASSERT(isolate == Isolate::Current());
114  // To improve the performance of the (much used) IC code, we unfold
115  // a few levels of the stack frame iteration code. This yields a
116  // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag.
117  const Address entry =
119  Address* pc_address =
120  reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset);
122  // If there's another JavaScript frame on the stack, we need to look
123  // one frame further down the stack to find the frame pointer and
124  // the return address stack slot.
125  if (depth == EXTRA_CALL_FRAME) {
126  const int kCallerPCOffset = StandardFrameConstants::kCallerPCOffset;
127  pc_address = reinterpret_cast<Address*>(fp + kCallerPCOffset);
129  }
130 #ifdef DEBUG
131  StackFrameIterator it;
132  for (int i = 0; i < depth + 1; i++) it.Advance();
133  StackFrame* frame = it.frame();
134  ASSERT(fp == frame->fp() && pc_address == frame->pc_address());
135 #endif
136  fp_ = fp;
137  pc_address_ = pc_address;
138 }
139 
140 
141 #ifdef ENABLE_DEBUGGER_SUPPORT
142 Address IC::OriginalCodeAddress() const {
143  HandleScope scope;
144  // Compute the JavaScript frame for the frame pointer of this IC
145  // structure. We need this to be able to find the function
146  // corresponding to the frame.
147  StackFrameIterator it;
148  while (it.frame()->fp() != this->fp()) it.Advance();
149  JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
150  // Find the function on the stack and both the active code for the
151  // function and the original code.
152  JSFunction* function = JSFunction::cast(frame->function());
153  Handle<SharedFunctionInfo> shared(function->shared());
154  Code* code = shared->code();
155  ASSERT(Debug::HasDebugInfo(shared));
156  Code* original_code = Debug::GetDebugInfo(shared)->original_code();
157  ASSERT(original_code->IsCode());
158  // Get the address of the call site in the active code. This is the
159  // place where the call to DebugBreakXXX is and where the IC
160  // normally would be.
162  // Return the address in the original code. This is the place where
163  // the call which has been overwritten by the DebugBreakXXX resides
164  // and the place where the inline cache system should look.
165  intptr_t delta =
166  original_code->instruction_start() - code->instruction_start();
167  return addr + delta;
168 }
169 #endif
170 
171 
172 static bool HasNormalObjectsInPrototypeChain(Isolate* isolate,
173  LookupResult* lookup,
174  Object* receiver) {
175  Object* end = lookup->IsProperty()
176  ? lookup->holder() : Object::cast(isolate->heap()->null_value());
177  for (Object* current = receiver;
178  current != end;
179  current = current->GetPrototype()) {
180  if (current->IsJSObject() &&
181  !JSObject::cast(current)->HasFastProperties() &&
182  !current->IsJSGlobalProxy() &&
183  !current->IsJSGlobalObject()) {
184  return true;
185  }
186  }
187 
188  return false;
189 }
190 
191 
192 static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
193  Object* receiver,
194  Object* name) {
195  InlineCacheHolderFlag cache_holder =
196  Code::ExtractCacheHolderFromFlags(target->flags());
197 
198  if (cache_holder == OWN_MAP && !receiver->IsJSObject()) {
199  // The stub was generated for JSObject but called for non-JSObject.
200  // IC::GetCodeCacheHolder is not applicable.
201  return false;
202  } else if (cache_holder == PROTOTYPE_MAP &&
203  receiver->GetPrototype()->IsNull()) {
204  // IC::GetCodeCacheHolder is not applicable.
205  return false;
206  }
207  Map* map = IC::GetCodeCacheHolder(receiver, cache_holder)->map();
208 
209  // Decide whether the inline cache failed because of changes to the
210  // receiver itself or changes to one of its prototypes.
211  //
212  // If there are changes to the receiver itself, the map of the
213  // receiver will have changed and the current target will not be in
214  // the receiver map's code cache. Therefore, if the current target
215  // is in the receiver map's code cache, the inline cache failed due
216  // to prototype check failure.
217  int index = map->IndexInCodeCache(name, target);
218  if (index >= 0) {
219  map->RemoveFromCodeCache(String::cast(name), target, index);
220  return true;
221  }
222 
223  return false;
224 }
225 
226 
227 IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
228  IC::State state = target->ic_state();
229 
230  if (state != MONOMORPHIC || !name->IsString()) return state;
231  if (receiver->IsUndefined() || receiver->IsNull()) return state;
232 
233  // For keyed load/store/call, the most likely cause of cache failure is
234  // that the key has changed. We do not distinguish between
235  // prototype and non-prototype failures for keyed access.
236  Code::Kind kind = target->kind();
237  if (kind == Code::KEYED_LOAD_IC ||
238  kind == Code::KEYED_STORE_IC ||
239  kind == Code::KEYED_CALL_IC) {
240  return MONOMORPHIC;
241  }
242 
243  // Remove the target from the code cache if it became invalid
244  // because of changes in the prototype chain to avoid hitting it
245  // again.
246  // Call stubs handle this later to allow extra IC state
247  // transitions.
248  if (kind != Code::CALL_IC &&
249  TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
251  }
252 
253  // The builtins object is special. It only changes when JavaScript
254  // builtins are loaded lazily. It is important to keep inline
255  // caches for the builtins object monomorphic. Therefore, if we get
256  // an inline cache miss for the builtins object after lazily loading
257  // JavaScript builtins, we return uninitialized as the state to
258  // force the inline cache back to monomorphic state.
259  if (receiver->IsJSBuiltinsObject()) {
260  return UNINITIALIZED;
261  }
262 
263  return MONOMORPHIC;
264 }
265 
266 
267 RelocInfo::Mode IC::ComputeMode() {
268  Address addr = address();
269  Code* code = Code::cast(isolate()->heap()->FindCodeObject(addr));
270  for (RelocIterator it(code, RelocInfo::kCodeTargetMask);
271  !it.done(); it.next()) {
272  RelocInfo* info = it.rinfo();
273  if (info->pc() == addr) return info->rmode();
274  }
275  UNREACHABLE();
276  return RelocInfo::NONE;
277 }
278 
279 
280 Failure* IC::TypeError(const char* type,
281  Handle<Object> object,
282  Handle<Object> key) {
283  HandleScope scope(isolate());
284  Handle<Object> args[2] = { key, object };
286  type, HandleVector(args, 2));
287  return isolate()->Throw(*error);
288 }
289 
290 
291 Failure* IC::ReferenceError(const char* type, Handle<String> name) {
292  HandleScope scope(isolate());
294  type, HandleVector(&name, 1));
295  return isolate()->Throw(*error);
296 }
297 
298 
299 static int ComputeTypeInfoCountDelta(IC::State old_state, IC::State new_state) {
300  bool was_uninitialized =
301  old_state == UNINITIALIZED || old_state == PREMONOMORPHIC;
302  bool is_uninitialized =
303  new_state == UNINITIALIZED || new_state == PREMONOMORPHIC;
304  return (was_uninitialized && !is_uninitialized) ? 1 :
305  (!was_uninitialized && is_uninitialized) ? -1 : 0;
306 }
307 
308 
309 void IC::PostPatching(Address address, Code* target, Code* old_target) {
310  if (FLAG_type_info_threshold == 0 && !FLAG_watch_ic_patching) {
311  return;
312  }
313  Code* host = target->GetHeap()->isolate()->
314  inner_pointer_to_code_cache()->GetCacheEntry(address)->code;
315  if (host->kind() != Code::FUNCTION) return;
316 
317  if (FLAG_type_info_threshold > 0 &&
318  old_target->is_inline_cache_stub() &&
319  target->is_inline_cache_stub()) {
320  int delta = ComputeTypeInfoCountDelta(old_target->ic_state(),
321  target->ic_state());
322  // Not all Code objects have TypeFeedbackInfo.
323  if (delta != 0 && host->type_feedback_info()->IsTypeFeedbackInfo()) {
324  TypeFeedbackInfo* info =
325  TypeFeedbackInfo::cast(host->type_feedback_info());
327  info->ic_with_type_info_count() + delta);
328  }
329  }
330  if (FLAG_watch_ic_patching) {
331  host->set_profiler_ticks(0);
332  Isolate::Current()->runtime_profiler()->NotifyICChanged();
333  }
334  // TODO(2029): When an optimized function is patched, it would
335  // be nice to propagate the corresponding type information to its
336  // unoptimized version for the benefit of later inlining.
337 }
338 
339 
340 void IC::Clear(Address address) {
341  Code* target = GetTargetAtAddress(address);
342 
343  // Don't clear debug break inline cache as it will remove the break point.
344  if (target->ic_state() == DEBUG_BREAK) return;
345 
346  switch (target->kind()) {
347  case Code::LOAD_IC: return LoadIC::Clear(address, target);
348  case Code::KEYED_LOAD_IC:
349  return KeyedLoadIC::Clear(address, target);
350  case Code::STORE_IC: return StoreIC::Clear(address, target);
352  return KeyedStoreIC::Clear(address, target);
353  case Code::CALL_IC: return CallIC::Clear(address, target);
354  case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
355  case Code::COMPARE_IC: return CompareIC::Clear(address, target);
356  case Code::UNARY_OP_IC:
357  case Code::BINARY_OP_IC:
358  case Code::TO_BOOLEAN_IC:
359  // Clearing these is tricky and does not
360  // make any performance difference.
361  return;
362  default: UNREACHABLE();
363  }
364 }
365 
366 
367 void CallICBase::Clear(Address address, Code* target) {
368  if (target->ic_state() == UNINITIALIZED) return;
369  bool contextual = CallICBase::Contextual::decode(target->extra_ic_state());
370  Code* code =
371  Isolate::Current()->stub_cache()->FindCallInitialize(
372  target->arguments_count(),
373  contextual ? RelocInfo::CODE_TARGET_CONTEXT : RelocInfo::CODE_TARGET,
374  target->kind());
375  SetTargetAtAddress(address, code);
376 }
377 
378 
379 void KeyedLoadIC::Clear(Address address, Code* target) {
380  if (target->ic_state() == UNINITIALIZED) return;
381  // Make sure to also clear the map used in inline fast cases. If we
382  // do not clear these maps, cached code can keep objects alive
383  // through the embedded maps.
384  SetTargetAtAddress(address, initialize_stub());
385 }
386 
387 
388 void LoadIC::Clear(Address address, Code* target) {
389  if (target->ic_state() == UNINITIALIZED) return;
390  SetTargetAtAddress(address, initialize_stub());
391 }
392 
393 
394 void StoreIC::Clear(Address address, Code* target) {
395  if (target->ic_state() == UNINITIALIZED) return;
396  SetTargetAtAddress(address,
397  (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
398  ? initialize_stub_strict()
399  : initialize_stub());
400 }
401 
402 
403 void KeyedStoreIC::Clear(Address address, Code* target) {
404  if (target->ic_state() == UNINITIALIZED) return;
405  SetTargetAtAddress(address,
406  (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
407  ? initialize_stub_strict()
408  : initialize_stub());
409 }
410 
411 
412 void CompareIC::Clear(Address address, Code* target) {
413  // Only clear ICCompareStubs, we currently cannot clear generic CompareStubs.
414  if (target->major_key() != CodeStub::CompareIC) return;
415  // Only clear CompareICs that can retain objects.
416  if (target->compare_state() != KNOWN_OBJECTS) return;
418  SetTargetAtAddress(address, GetRawUninitialized(op));
420 }
421 
422 
423 static bool HasInterceptorGetter(JSObject* object) {
424  return !object->GetNamedInterceptor()->getter()->IsUndefined();
425 }
426 
427 
428 static void LookupForRead(Handle<Object> object,
429  Handle<String> name,
430  LookupResult* lookup) {
431  // Skip all the objects with named interceptors, but
432  // without actual getter.
433  while (true) {
434  object->Lookup(*name, lookup);
435  // Besides normal conditions (property not found or it's not
436  // an interceptor), bail out if lookup is not cacheable: we won't
437  // be able to IC it anyway and regular lookup should work fine.
438  if (!lookup->IsFound()
439  || (lookup->type() != INTERCEPTOR)
440  || !lookup->IsCacheable()) {
441  return;
442  }
443 
444  Handle<JSObject> holder(lookup->holder());
445  if (HasInterceptorGetter(*holder)) {
446  return;
447  }
448 
449  holder->LocalLookupRealNamedProperty(*name, lookup);
450  if (lookup->IsProperty()) {
451  ASSERT(lookup->type() != INTERCEPTOR);
452  return;
453  }
454 
455  Handle<Object> proto(holder->GetPrototype());
456  if (proto->IsNull()) {
457  lookup->NotFound();
458  return;
459  }
460 
461  object = proto;
462  }
463 }
464 
465 
468 
469  if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) {
470  // Patch the receiver and use the delegate as the function to
471  // invoke. This is used for invoking objects as if they were functions.
472  const int argc = target()->arguments_count();
473  StackFrameLocator locator;
474  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
475  int index = frame->ComputeExpressionsCount() - (argc + 1);
476  frame->SetExpression(index, *object);
477  }
478 
479  return delegate;
480 }
481 
482 
484  Handle<Object> object) {
485  while (callee->IsJSFunctionProxy()) {
486  callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap());
487  }
488 
489  if (callee->IsJSFunction()) {
490  Handle<JSFunction> function = Handle<JSFunction>::cast(callee);
491  if (!function->shared()->is_classic_mode() || function->IsBuiltin()) {
492  // Do not wrap receiver for strict mode functions or for builtins.
493  return;
494  }
495  }
496 
497  // And only wrap string, number or boolean.
498  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
499  // Change the receiver to the result of calling ToObject on it.
500  const int argc = this->target()->arguments_count();
501  StackFrameLocator locator;
502  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
503  int index = frame->ComputeExpressionsCount() - (argc + 1);
504  frame->SetExpression(index, *isolate()->factory()->ToObject(object));
505  }
506 }
507 
508 
509 MaybeObject* CallICBase::LoadFunction(State state,
510  Code::ExtraICState extra_ic_state,
511  Handle<Object> object,
512  Handle<String> name) {
513  // If the object is undefined or null it's illegal to try to get any
514  // of its properties; throw a TypeError in that case.
515  if (object->IsUndefined() || object->IsNull()) {
516  return TypeError("non_object_property_call", object, name);
517  }
518 
519  // Check if the name is trivially convertible to an index and get
520  // the element if so.
521  uint32_t index;
522  if (name->AsArrayIndex(&index)) {
523  Handle<Object> result = Object::GetElement(object, index);
524  RETURN_IF_EMPTY_HANDLE(isolate(), result);
525  if (result->IsJSFunction()) return *result;
526 
527  // Try to find a suitable function delegate for the object at hand.
528  result = TryCallAsFunction(result);
529  if (result->IsJSFunction()) return *result;
530 
531  // Otherwise, it will fail in the lookup step.
532  }
533 
534  // Lookup the property in the object.
535  LookupResult lookup(isolate());
536  LookupForRead(object, name, &lookup);
537 
538  if (!lookup.IsProperty()) {
539  // If the object does not have the requested property, check which
540  // exception we need to throw.
541  return IsContextual(object)
542  ? ReferenceError("not_defined", name)
543  : TypeError("undefined_method", object, name);
544  }
545 
546  // Lookup is valid: Update inline cache and stub cache.
547  if (FLAG_use_ic) {
548  UpdateCaches(&lookup, state, extra_ic_state, object, name);
549  }
550 
551  // Get the property.
552  PropertyAttributes attr;
553  Handle<Object> result =
554  Object::GetProperty(object, object, &lookup, name, &attr);
555  RETURN_IF_EMPTY_HANDLE(isolate(), result);
556 
557  if (lookup.type() == INTERCEPTOR && attr == ABSENT) {
558  // If the object does not have the requested property, check which
559  // exception we need to throw.
560  return IsContextual(object)
561  ? ReferenceError("not_defined", name)
562  : TypeError("undefined_method", object, name);
563  }
564 
565  ASSERT(!result->IsTheHole());
566 
567  // Make receiver an object if the callee requires it. Strict mode or builtin
568  // functions do not wrap the receiver, non-strict functions and objects
569  // called as functions do.
570  ReceiverToObjectIfRequired(result, object);
571 
572  if (result->IsJSFunction()) {
573  Handle<JSFunction> function = Handle<JSFunction>::cast(result);
574 #ifdef ENABLE_DEBUGGER_SUPPORT
575  // Handle stepping into a function if step into is active.
576  Debug* debug = isolate()->debug();
577  if (debug->StepInActive()) {
578  // Protect the result in a handle as the debugger can allocate and might
579  // cause GC.
580  debug->HandleStepIn(function, object, fp(), false);
581  }
582 #endif
583  return *function;
584  }
585 
586  // Try to find a suitable function delegate for the object at hand.
587  result = TryCallAsFunction(result);
588  if (result->IsJSFunction()) return *result;
589 
590  return TypeError("property_not_function", object, name);
591 }
592 
593 
594 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
595  Handle<Object> object,
596  Code::ExtraICState* extra_ic_state) {
598  if (lookup->type() != CONSTANT_FUNCTION) return false;
599  JSFunction* function = lookup->GetConstantFunction();
600  if (!function->shared()->HasBuiltinFunctionId()) return false;
601 
602  // Fetch the arguments passed to the called function.
603  const int argc = target()->arguments_count();
604  Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
606  Arguments args(argc + 1,
607  &Memory::Object_at(fp +
609  argc * kPointerSize));
610  switch (function->shared()->builtin_function_id()) {
611  case kStringCharCodeAt:
612  case kStringCharAt:
613  if (object->IsString()) {
614  String* string = String::cast(*object);
615  // Check there's the right string value or wrapper in the receiver slot.
616  ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
617  // If we're in the default (fastest) state and the index is
618  // out of bounds, update the state to record this fact.
619  if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB &&
620  argc >= 1 && args[1]->IsNumber()) {
621  double index = DoubleToInteger(args.number_at(1));
622  if (index < 0 || index >= string->length()) {
623  *extra_ic_state =
624  StringStubState::update(*extra_ic_state,
626  return true;
627  }
628  }
629  }
630  break;
631  default:
632  return false;
633  }
634  return false;
635 }
636 
637 
639  State state,
640  Code::ExtraICState extra_state,
641  Handle<Object> object,
642  Handle<String> name) {
643  int argc = target()->arguments_count();
644  Handle<JSObject> holder(lookup->holder());
645  switch (lookup->type()) {
646  case FIELD: {
647  int index = lookup->GetFieldIndex();
648  return isolate()->stub_cache()->ComputeCallField(
649  argc, kind_, extra_state, name, object, holder, index);
650  }
651  case CONSTANT_FUNCTION: {
652  // Get the constant function and compute the code stub for this
653  // call; used for rewriting to monomorphic state and making sure
654  // that the code stub is in the stub cache.
655  Handle<JSFunction> function(lookup->GetConstantFunction());
657  argc, kind_, extra_state, name, object, holder, function);
658  }
659  case NORMAL: {
660  // If we return a null handle, the IC will not be patched.
661  if (!object->IsJSObject()) return Handle<Code>::null();
662  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
663 
664  if (holder->IsGlobalObject()) {
666  Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
667  if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
668  Handle<JSFunction> function(JSFunction::cast(cell->value()));
669  return isolate()->stub_cache()->ComputeCallGlobal(
670  argc, kind_, extra_state, name, receiver, global, cell, function);
671  } else {
672  // There is only one shared stub for calling normalized
673  // properties. It does not traverse the prototype chain, so the
674  // property must be found in the receiver for the stub to be
675  // applicable.
676  if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
677  return isolate()->stub_cache()->ComputeCallNormal(
678  argc, kind_, extra_state);
679  }
680  break;
681  }
682  case INTERCEPTOR:
683  ASSERT(HasInterceptorGetter(*holder));
685  argc, kind_, extra_state, name, object, holder);
686  default:
687  return Handle<Code>::null();
688  }
689 }
690 
691 
692 void CallICBase::UpdateCaches(LookupResult* lookup,
693  State state,
694  Code::ExtraICState extra_ic_state,
695  Handle<Object> object,
696  Handle<String> name) {
697  // Bail out if we didn't find a result.
698  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
699 
700  if (lookup->holder() != *object &&
701  HasNormalObjectsInPrototypeChain(
702  isolate(), lookup, object->GetPrototype())) {
703  // Suppress optimization for prototype chains with slow properties objects
704  // in the middle.
705  return;
706  }
707 
708  // Compute the number of arguments.
709  int argc = target()->arguments_count();
710  bool had_proto_failure = false;
711  Handle<Code> code;
712  if (state == UNINITIALIZED) {
713  // This is the first time we execute this inline cache.
714  // Set the target to the pre monomorphic stub to delay
715  // setting the monomorphic state.
717  argc, kind_, extra_ic_state);
718  } else if (state == MONOMORPHIC) {
719  if (kind_ == Code::CALL_IC &&
720  TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
721  code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
722  object, name);
723  } else if (kind_ == Code::CALL_IC &&
724  TryRemoveInvalidPrototypeDependentStub(target(),
725  *object,
726  *name)) {
727  had_proto_failure = true;
728  code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
729  object, name);
730  } else {
732  argc, kind_, extra_ic_state);
733  }
734  } else {
735  code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
736  object, name);
737  }
738 
739  // If there's no appropriate stub we simply avoid updating the caches.
740  if (code.is_null()) return;
741 
742  // Patch the call site depending on the state of the cache.
743  if (state == UNINITIALIZED ||
744  state == PREMONOMORPHIC ||
745  state == MONOMORPHIC ||
747  set_target(*code);
748  } else if (state == MEGAMORPHIC) {
749  // Cache code holding map should be consistent with
750  // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
751  Handle<JSObject> cache_object = object->IsJSObject()
752  ? Handle<JSObject>::cast(object)
753  : Handle<JSObject>(JSObject::cast(object->GetPrototype()));
754  // Update the stub cache.
755  isolate()->stub_cache()->Set(*name, cache_object->map(), *code);
756  }
757 
758  if (had_proto_failure) state = MONOMORPHIC_PROTOTYPE_FAILURE;
759  TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
760  name, state, target());
761 }
762 
763 
764 MaybeObject* KeyedCallIC::LoadFunction(State state,
765  Handle<Object> object,
766  Handle<Object> key) {
767  if (key->IsSymbol()) {
768  return CallICBase::LoadFunction(state,
770  object,
771  Handle<String>::cast(key));
772  }
773 
774  if (object->IsUndefined() || object->IsNull()) {
775  return TypeError("non_object_property_call", object, key);
776  }
777 
778  if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) {
779  int argc = target()->arguments_count();
780  Handle<Map> map =
781  isolate()->factory()->non_strict_arguments_elements_map();
782  if (object->IsJSObject() &&
783  Handle<JSObject>::cast(object)->elements()->map() == *map) {
785  argc, Code::KEYED_CALL_IC);
786  set_target(*code);
787  TRACE_IC("KeyedCallIC", key, state, target());
788  } else if (!object->IsAccessCheckNeeded()) {
791  set_target(*code);
792  TRACE_IC("KeyedCallIC", key, state, target());
793  }
794  }
795 
796  Handle<Object> result = GetProperty(object, key);
797  RETURN_IF_EMPTY_HANDLE(isolate(), result);
798 
799  // Make receiver an object if the callee requires it. Strict mode or builtin
800  // functions do not wrap the receiver, non-strict functions and objects
801  // called as functions do.
802  ReceiverToObjectIfRequired(result, object);
803  if (result->IsJSFunction()) return *result;
804 
805  result = TryCallAsFunction(result);
806  if (result->IsJSFunction()) return *result;
807 
808  return TypeError("property_not_function", object, key);
809 }
810 
811 
812 MaybeObject* LoadIC::Load(State state,
813  Handle<Object> object,
814  Handle<String> name) {
815  // If the object is undefined or null it's illegal to try to get any
816  // of its properties; throw a TypeError in that case.
817  if (object->IsUndefined() || object->IsNull()) {
818  return TypeError("non_object_property_load", object, name);
819  }
820 
821  if (FLAG_use_ic) {
822  // Use specialized code for getting the length of strings and
823  // string wrapper objects. The length property of string wrapper
824  // objects is read-only and therefore always returns the length of
825  // the underlying string value. See ECMA-262 15.5.5.1.
826  if ((object->IsString() || object->IsStringWrapper()) &&
827  name->Equals(isolate()->heap()->length_symbol())) {
828  Handle<Code> stub;
829  if (state == UNINITIALIZED) {
830  stub = pre_monomorphic_stub();
831  } else if (state == PREMONOMORPHIC) {
832  stub = object->IsString()
833  ? isolate()->builtins()->LoadIC_StringLength()
834  : isolate()->builtins()->LoadIC_StringWrapperLength();
835  } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
836  stub = isolate()->builtins()->LoadIC_StringWrapperLength();
837  } else if (state != MEGAMORPHIC) {
838  stub = megamorphic_stub();
839  }
840  if (!stub.is_null()) {
841  set_target(*stub);
842 #ifdef DEBUG
843  if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
844 #endif
845  }
846  // Get the string if we have a string wrapper object.
847  Handle<Object> string = object->IsJSValue()
848  ? Handle<Object>(Handle<JSValue>::cast(object)->value())
849  : object;
850  return Smi::FromInt(String::cast(*string)->length());
851  }
852 
853  // Use specialized code for getting the length of arrays.
854  if (object->IsJSArray() &&
855  name->Equals(isolate()->heap()->length_symbol())) {
856  Handle<Code> stub;
857  if (state == UNINITIALIZED) {
858  stub = pre_monomorphic_stub();
859  } else if (state == PREMONOMORPHIC) {
860  stub = isolate()->builtins()->LoadIC_ArrayLength();
861  } else if (state != MEGAMORPHIC) {
862  stub = megamorphic_stub();
863  }
864  if (!stub.is_null()) {
865  set_target(*stub);
866 #ifdef DEBUG
867  if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
868 #endif
869  }
870  return JSArray::cast(*object)->length();
871  }
872 
873  // Use specialized code for getting prototype of functions.
874  if (object->IsJSFunction() &&
875  name->Equals(isolate()->heap()->prototype_symbol()) &&
876  Handle<JSFunction>::cast(object)->should_have_prototype()) {
877  Handle<Code> stub;
878  if (state == UNINITIALIZED) {
879  stub = pre_monomorphic_stub();
880  } else if (state == PREMONOMORPHIC) {
881  stub = isolate()->builtins()->LoadIC_FunctionPrototype();
882  } else if (state != MEGAMORPHIC) {
883  stub = megamorphic_stub();
884  }
885  if (!stub.is_null()) {
886  set_target(*stub);
887 #ifdef DEBUG
888  if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
889 #endif
890  }
891  return Accessors::FunctionGetPrototype(*object, 0);
892  }
893  }
894 
895  // Check if the name is trivially convertible to an index and get
896  // the element if so.
897  uint32_t index;
898  if (name->AsArrayIndex(&index)) return object->GetElement(index);
899 
900  // Named lookup in the object.
901  LookupResult lookup(isolate());
902  LookupForRead(object, name, &lookup);
903 
904  // If we did not find a property, check if we need to throw an exception.
905  if (!lookup.IsProperty()) {
906  if (IsContextual(object)) {
907  return ReferenceError("not_defined", name);
908  }
909  LOG(isolate(), SuspectReadEvent(*name, *object));
910  }
911 
912  // Update inline cache and stub cache.
913  if (FLAG_use_ic) {
914  UpdateCaches(&lookup, state, object, name);
915  }
916 
917  PropertyAttributes attr;
918  if (lookup.IsFound() &&
919  (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
920  // Get the property.
921  Handle<Object> result =
922  Object::GetProperty(object, object, &lookup, name, &attr);
923  RETURN_IF_EMPTY_HANDLE(isolate(), result);
924  // If the property is not present, check if we need to throw an
925  // exception.
926  if (attr == ABSENT && IsContextual(object)) {
927  return ReferenceError("not_defined", name);
928  }
929  return *result;
930  }
931 
932  // Get the property.
933  return object->GetProperty(*object, &lookup, *name, &attr);
934 }
935 
936 
937 void LoadIC::UpdateCaches(LookupResult* lookup,
938  State state,
939  Handle<Object> object,
940  Handle<String> name) {
941  // Bail out if the result is not cacheable.
942  if (!lookup->IsCacheable()) return;
943 
944  // Loading properties from values is not common, so don't try to
945  // deal with non-JS objects here.
946  if (!object->IsJSObject()) return;
947  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
948 
949  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
950 
951  // Compute the code stub for this load.
952  Handle<Code> code;
953  if (state == UNINITIALIZED) {
954  // This is the first time we execute this inline cache.
955  // Set the target to the pre monomorphic stub to delay
956  // setting the monomorphic state.
957  code = pre_monomorphic_stub();
958  } else if (!lookup->IsProperty()) {
959  // Nonexistent property. The result is undefined.
960  code = isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
961  } else {
962  // Compute monomorphic stub.
963  Handle<JSObject> holder(lookup->holder());
964  switch (lookup->type()) {
965  case FIELD:
966  code = isolate()->stub_cache()->ComputeLoadField(
967  name, receiver, holder, lookup->GetFieldIndex());
968  break;
969  case CONSTANT_FUNCTION: {
970  Handle<JSFunction> constant(lookup->GetConstantFunction());
972  name, receiver, holder, constant);
973  break;
974  }
975  case NORMAL:
976  if (holder->IsGlobalObject()) {
977  Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
978  Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
979  code = isolate()->stub_cache()->ComputeLoadGlobal(
980  name, receiver, global, cell, lookup->IsDontDelete());
981  } else {
982  // There is only one shared stub for loading normalized
983  // properties. It does not traverse the prototype chain, so the
984  // property must be found in the receiver for the stub to be
985  // applicable.
986  if (!holder.is_identical_to(receiver)) return;
987  code = isolate()->stub_cache()->ComputeLoadNormal();
988  }
989  break;
990  case CALLBACKS: {
991  Handle<Object> callback(lookup->GetCallbackObject());
992  if (callback->IsAccessorInfo()) {
993  Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
994  if (v8::ToCData<Address>(info->getter()) == 0) return;
995  if (!info->IsCompatibleReceiver(*receiver)) return;
997  name, receiver, holder, info);
998  } else if (callback->IsAccessorPair()) {
999  Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter());
1000  if (!getter->IsJSFunction()) return;
1001  if (holder->IsGlobalObject()) return;
1002  if (!receiver->HasFastProperties()) return;
1004  name, receiver, holder, Handle<JSFunction>::cast(getter));
1005  } else {
1006  ASSERT(callback->IsForeign());
1007  // No IC support for old-style native accessors.
1008  return;
1009  }
1010  break;
1011  }
1012  case INTERCEPTOR:
1013  ASSERT(HasInterceptorGetter(*holder));
1015  name, receiver, holder);
1016  break;
1017  default:
1018  return;
1019  }
1020  }
1021 
1022  // Patch the call site depending on the state of the cache.
1023  if (state == UNINITIALIZED ||
1024  state == PREMONOMORPHIC ||
1025  state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1026  set_target(*code);
1027  } else if (state == MONOMORPHIC) {
1028  // We are transitioning from monomorphic to megamorphic case.
1029  // Place the current monomorphic stub and stub compiled for
1030  // the receiver into stub cache.
1031  Map* map = target()->FindFirstMap();
1032  if (map != NULL) {
1033  isolate()->stub_cache()->Set(*name, map, target());
1034  }
1035  isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1036 
1037  set_target(*megamorphic_stub());
1038  } else if (state == MEGAMORPHIC) {
1039  // Cache code holding map should be consistent with
1040  // GenerateMonomorphicCacheProbe.
1041  isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1042  }
1043 
1044  TRACE_IC("LoadIC", name, state, target());
1045 }
1046 
1047 
1049  bool is_js_array,
1050  ElementsKind elements_kind,
1051  KeyedAccessGrowMode grow_mode) {
1052  ASSERT(grow_mode == DO_NOT_ALLOW_JSARRAY_GROWTH);
1053  return KeyedLoadElementStub(elements_kind).GetCode();
1054 }
1055 
1056 
1058  MapHandleList* receiver_maps,
1059  StrictModeFlag strict_mode,
1060  KeyedAccessGrowMode growth_mode) {
1061  CodeHandleList handler_ics(receiver_maps->length());
1062  for (int i = 0; i < receiver_maps->length(); ++i) {
1063  Handle<Map> receiver_map = receiver_maps->at(i);
1065  receiver_map, strict_mode, growth_mode);
1066  handler_ics.Add(cached_stub);
1067  }
1068  KeyedLoadStubCompiler compiler(isolate());
1069  Handle<Code> code = compiler.CompileLoadPolymorphic(
1070  receiver_maps, &handler_ics);
1071  isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
1072  PROFILE(isolate(),
1073  CodeCreateEvent(Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, *code, 0));
1074  return code;
1075 }
1076 
1077 
1078 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) {
1079  // This helper implements a few common fast cases for converting
1080  // non-smi keys of keyed loads/stores to a smi or a string.
1081  if (key->IsHeapNumber()) {
1082  double value = Handle<HeapNumber>::cast(key)->value();
1083  if (isnan(value)) {
1084  key = isolate->factory()->nan_symbol();
1085  } else {
1086  int int_value = FastD2I(value);
1087  if (value == int_value && Smi::IsValid(int_value)) {
1088  key = Handle<Smi>(Smi::FromInt(int_value));
1089  }
1090  }
1091  } else if (key->IsUndefined()) {
1092  key = isolate->factory()->undefined_symbol();
1093  }
1094  return key;
1095 }
1096 
1097 
1098 MaybeObject* KeyedLoadIC::Load(State state,
1099  Handle<Object> object,
1100  Handle<Object> key,
1101  bool force_generic_stub) {
1102  // Check for values that can be converted into a symbol directly or
1103  // is representable as a smi.
1104  key = TryConvertKey(key, isolate());
1105 
1106  if (key->IsSymbol()) {
1108 
1109  // If the object is undefined or null it's illegal to try to get any
1110  // of its properties; throw a TypeError in that case.
1111  if (object->IsUndefined() || object->IsNull()) {
1112  return TypeError("non_object_property_load", object, name);
1113  }
1114 
1115  if (FLAG_use_ic) {
1116  // TODO(1073): don't ignore the current stub state.
1117 
1118  // Use specialized code for getting the length of strings.
1119  if (object->IsString() &&
1120  name->Equals(isolate()->heap()->length_symbol())) {
1121  Handle<String> string = Handle<String>::cast(object);
1122  Handle<Code> code =
1123  isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, string);
1124  ASSERT(!code.is_null());
1125  set_target(*code);
1126  TRACE_IC("KeyedLoadIC", name, state, target());
1127  return Smi::FromInt(string->length());
1128  }
1129 
1130  // Use specialized code for getting the length of arrays.
1131  if (object->IsJSArray() &&
1132  name->Equals(isolate()->heap()->length_symbol())) {
1133  Handle<JSArray> array = Handle<JSArray>::cast(object);
1134  Handle<Code> code =
1135  isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array);
1136  ASSERT(!code.is_null());
1137  set_target(*code);
1138  TRACE_IC("KeyedLoadIC", name, state, target());
1139  return array->length();
1140  }
1141 
1142  // Use specialized code for getting prototype of functions.
1143  if (object->IsJSFunction() &&
1144  name->Equals(isolate()->heap()->prototype_symbol()) &&
1145  Handle<JSFunction>::cast(object)->should_have_prototype()) {
1146  Handle<JSFunction> function = Handle<JSFunction>::cast(object);
1147  Handle<Code> code =
1149  name, function);
1150  ASSERT(!code.is_null());
1151  set_target(*code);
1152  TRACE_IC("KeyedLoadIC", name, state, target());
1153  return Accessors::FunctionGetPrototype(*object, 0);
1154  }
1155  }
1156 
1157  // Check if the name is trivially convertible to an index and get
1158  // the element or char if so.
1159  uint32_t index = 0;
1160  if (name->AsArrayIndex(&index)) {
1161  // Rewrite to the generic keyed load stub.
1162  if (FLAG_use_ic) set_target(*generic_stub());
1163  return Runtime::GetElementOrCharAt(isolate(), object, index);
1164  }
1165 
1166  // Named lookup.
1167  LookupResult lookup(isolate());
1168  LookupForRead(object, name, &lookup);
1169 
1170  // If we did not find a property, check if we need to throw an exception.
1171  if (!lookup.IsProperty() && IsContextual(object)) {
1172  return ReferenceError("not_defined", name);
1173  }
1174 
1175  if (FLAG_use_ic) {
1176  UpdateCaches(&lookup, state, object, name);
1177  }
1178 
1179  PropertyAttributes attr;
1180  if (lookup.IsFound() && lookup.type() == INTERCEPTOR) {
1181  // Get the property.
1182  Handle<Object> result =
1183  Object::GetProperty(object, object, &lookup, name, &attr);
1184  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1185  // If the property is not present, check if we need to throw an
1186  // exception.
1187  if (attr == ABSENT && IsContextual(object)) {
1188  return ReferenceError("not_defined", name);
1189  }
1190  return *result;
1191  }
1192 
1193  return object->GetProperty(*object, &lookup, *name, &attr);
1194  }
1195 
1196  // Do not use ICs for objects that require access checks (including
1197  // the global object).
1198  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1199 
1200  if (use_ic) {
1201  Handle<Code> stub = generic_stub();
1202  if (!force_generic_stub) {
1203  if (object->IsString() && key->IsNumber()) {
1204  if (state == UNINITIALIZED) {
1205  stub = string_stub();
1206  }
1207  } else if (object->IsJSObject()) {
1208  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1209  if (receiver->elements()->map() ==
1210  isolate()->heap()->non_strict_arguments_elements_map()) {
1211  stub = non_strict_arguments_stub();
1212  } else if (receiver->HasIndexedInterceptor()) {
1213  stub = indexed_interceptor_stub();
1214  } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
1215  stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub);
1216  }
1217  }
1218  } else {
1219  TRACE_GENERIC_IC("KeyedLoadIC", "force generic");
1220  }
1221  if (!stub.is_null()) set_target(*stub);
1222  }
1223 
1224  TRACE_IC("KeyedLoadIC", key, state, target());
1225 
1226  // Get the property.
1227  return Runtime::GetObjectProperty(isolate(), object, key);
1228 }
1229 
1230 
1231 void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
1232  State state,
1233  Handle<Object> object,
1234  Handle<String> name) {
1235  // Bail out if we didn't find a result.
1236  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
1237 
1238  if (!object->IsJSObject()) return;
1239  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1240 
1241  if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
1242 
1243  // Compute the code stub for this load.
1244  Handle<Code> code;
1245 
1246  if (state == UNINITIALIZED) {
1247  // This is the first time we execute this inline cache.
1248  // Set the target to the pre monomorphic stub to delay
1249  // setting the monomorphic state.
1250  code = pre_monomorphic_stub();
1251  } else {
1252  // Compute a monomorphic stub.
1253  Handle<JSObject> holder(lookup->holder());
1254  switch (lookup->type()) {
1255  case FIELD:
1257  name, receiver, holder, lookup->GetFieldIndex());
1258  break;
1259  case CONSTANT_FUNCTION: {
1260  Handle<JSFunction> constant(lookup->GetConstantFunction());
1262  name, receiver, holder, constant);
1263  break;
1264  }
1265  case CALLBACKS: {
1266  Handle<Object> callback_object(lookup->GetCallbackObject());
1267  if (!callback_object->IsAccessorInfo()) return;
1268  Handle<AccessorInfo> callback =
1269  Handle<AccessorInfo>::cast(callback_object);
1270  if (v8::ToCData<Address>(callback->getter()) == 0) return;
1271  if (!callback->IsCompatibleReceiver(*receiver)) return;
1273  name, receiver, holder, callback);
1274  break;
1275  }
1276  case INTERCEPTOR:
1277  ASSERT(HasInterceptorGetter(lookup->holder()));
1279  name, receiver, holder);
1280  break;
1281  default:
1282  // Always rewrite to the generic case so that we do not
1283  // repeatedly try to rewrite.
1284  code = generic_stub();
1285  break;
1286  }
1287  }
1288 
1289  // Patch the call site depending on the state of the cache. Make
1290  // sure to always rewrite from monomorphic to megamorphic.
1292  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1293  set_target(*code);
1294  } else if (state == MONOMORPHIC) {
1295  set_target(*megamorphic_stub());
1296  }
1297 
1298  TRACE_IC("KeyedLoadIC", name, state, target());
1299 }
1300 
1301 
1302 static bool StoreICableLookup(LookupResult* lookup) {
1303  // Bail out if we didn't find a result.
1304  if (!lookup->IsFound() || lookup->type() == NULL_DESCRIPTOR) return false;
1305 
1306  // Bail out if inline caching is not allowed.
1307  if (!lookup->IsCacheable()) return false;
1308 
1309  // If the property is read-only, we leave the IC in its current state.
1310  if (lookup->IsReadOnly()) return false;
1311 
1312  return true;
1313 }
1314 
1315 
1316 static bool LookupForWrite(Handle<JSObject> receiver,
1317  Handle<String> name,
1318  LookupResult* lookup) {
1319  receiver->LocalLookup(*name, lookup);
1320  if (!StoreICableLookup(lookup)) {
1321  return false;
1322  }
1323 
1324  if (lookup->type() == INTERCEPTOR &&
1325  receiver->GetNamedInterceptor()->setter()->IsUndefined()) {
1326  receiver->LocalLookupRealNamedProperty(*name, lookup);
1327  return StoreICableLookup(lookup);
1328  }
1329 
1330  return true;
1331 }
1332 
1333 
1334 MaybeObject* StoreIC::Store(State state,
1335  StrictModeFlag strict_mode,
1336  Handle<Object> object,
1337  Handle<String> name,
1338  Handle<Object> value) {
1339  if (!object->IsJSObject()) {
1340  // Handle proxies.
1341  if (object->IsJSProxy()) {
1342  return JSProxy::cast(*object)->
1343  SetProperty(*name, *value, NONE, strict_mode);
1344  }
1345 
1346  // If the object is undefined or null it's illegal to try to set any
1347  // properties on it; throw a TypeError in that case.
1348  if (object->IsUndefined() || object->IsNull()) {
1349  return TypeError("non_object_property_store", object, name);
1350  }
1351 
1352  // The length property of string values is read-only. Throw in strict mode.
1353  if (strict_mode == kStrictMode && object->IsString() &&
1354  name->Equals(isolate()->heap()->length_symbol())) {
1355  return TypeError("strict_read_only_property", object, name);
1356  }
1357  // Ignore other stores where the receiver is not a JSObject.
1358  // TODO(1475): Must check prototype chains of object wrappers.
1359  return *value;
1360  }
1361 
1362  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1363 
1364  // Check if the given name is an array index.
1365  uint32_t index;
1366  if (name->AsArrayIndex(&index)) {
1367  Handle<Object> result =
1368  JSObject::SetElement(receiver, index, value, NONE, strict_mode);
1369  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1370  return *value;
1371  }
1372 
1373  // Use specialized code for setting the length of arrays with fast
1374  // properties. Slow properties might indicate redefinition of the
1375  // length property.
1376  if (receiver->IsJSArray() &&
1377  name->Equals(isolate()->heap()->length_symbol()) &&
1378  Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
1379  receiver->HasFastProperties()) {
1380 #ifdef DEBUG
1381  if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
1382 #endif
1383  Handle<Code> stub = (strict_mode == kStrictMode)
1384  ? isolate()->builtins()->StoreIC_ArrayLength_Strict()
1385  : isolate()->builtins()->StoreIC_ArrayLength();
1386  set_target(*stub);
1387  return receiver->SetProperty(*name, *value, NONE, strict_mode);
1388  }
1389 
1390  // Lookup the property locally in the receiver.
1391  if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
1392  LookupResult lookup(isolate());
1393 
1394  if (LookupForWrite(receiver, name, &lookup)) {
1395  // Generate a stub for this store.
1396  UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1397  } else {
1398  // Strict mode doesn't allow setting non-existent global property
1399  // or an assignment to a read only property.
1400  if (strict_mode == kStrictMode) {
1401  if (lookup.IsProperty() && lookup.IsReadOnly()) {
1402  return TypeError("strict_read_only_property", object, name);
1403  } else if (IsContextual(object)) {
1404  return ReferenceError("not_defined", name);
1405  }
1406  }
1407  }
1408  }
1409 
1410  if (receiver->IsJSGlobalProxy()) {
1411  // TODO(ulan): find out why we patch this site even with --no-use-ic
1412  // Generate a generic stub that goes to the runtime when we see a global
1413  // proxy as receiver.
1414  Handle<Code> stub = (strict_mode == kStrictMode)
1415  ? global_proxy_stub_strict()
1416  : global_proxy_stub();
1417  if (target() != *stub) {
1418  set_target(*stub);
1419  TRACE_IC("StoreIC", name, state, target());
1420  }
1421  }
1422 
1423  // Set the property.
1424  return receiver->SetProperty(*name,
1425  *value,
1426  NONE,
1427  strict_mode,
1429 }
1430 
1431 
1432 void StoreIC::UpdateCaches(LookupResult* lookup,
1433  State state,
1434  StrictModeFlag strict_mode,
1435  Handle<JSObject> receiver,
1436  Handle<String> name,
1437  Handle<Object> value) {
1438  ASSERT(!receiver->IsJSGlobalProxy());
1439  ASSERT(StoreICableLookup(lookup));
1440  // These are not cacheable, so we never see such LookupResults here.
1441  ASSERT(lookup->type() != HANDLER);
1442  // We get only called for properties or transitions, see StoreICableLookup.
1443  ASSERT(lookup->type() != NULL_DESCRIPTOR);
1444 
1445  // If the property has a non-field type allowing map transitions
1446  // where there is extra room in the object, we leave the IC in its
1447  // current state.
1448  PropertyType type = lookup->type();
1449 
1450  // Compute the code stub for this store; used for rewriting to
1451  // monomorphic state and making sure that the code stub is in the
1452  // stub cache.
1453  Handle<JSObject> holder(lookup->holder());
1454  Handle<Code> code;
1455  switch (type) {
1456  case FIELD:
1457  code = isolate()->stub_cache()->ComputeStoreField(name,
1458  receiver,
1459  lookup->GetFieldIndex(),
1461  strict_mode);
1462  break;
1463  case MAP_TRANSITION: {
1464  if (lookup->GetAttributes() != NONE) return;
1465  Handle<Map> transition(lookup->GetTransitionMap());
1466  int index = transition->PropertyIndexFor(*name);
1467  code = isolate()->stub_cache()->ComputeStoreField(
1468  name, receiver, index, transition, strict_mode);
1469  break;
1470  }
1471  case NORMAL:
1472  if (receiver->IsGlobalObject()) {
1473  // The stub generated for the global object picks the value directly
1474  // from the property cell. So the property must be directly on the
1475  // global object.
1477  Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
1478  code = isolate()->stub_cache()->ComputeStoreGlobal(
1479  name, global, cell, strict_mode);
1480  } else {
1481  if (!holder.is_identical_to(receiver)) return;
1482  code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode);
1483  }
1484  break;
1485  case CALLBACKS: {
1486  Handle<Object> callback(lookup->GetCallbackObject());
1487  if (callback->IsAccessorInfo()) {
1488  Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback);
1489  if (v8::ToCData<Address>(info->setter()) == 0) return;
1490  ASSERT(info->IsCompatibleReceiver(*receiver));
1492  name, receiver, info, strict_mode);
1493  } else if (callback->IsAccessorPair()) {
1494  Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter());
1495  if (!setter->IsJSFunction()) return;
1496  if (holder->IsGlobalObject()) return;
1497  if (!receiver->HasFastProperties()) return;
1499  name, receiver, Handle<JSFunction>::cast(setter), strict_mode);
1500  } else {
1501  ASSERT(callback->IsForeign());
1502  // No IC support for old-style native accessors.
1503  return;
1504  }
1505  break;
1506  }
1507  case INTERCEPTOR:
1508  ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
1510  name, receiver, strict_mode);
1511  break;
1512  case CONSTANT_FUNCTION:
1513  case CONSTANT_TRANSITION:
1514  return;
1515  case HANDLER:
1516  case NULL_DESCRIPTOR:
1517  UNREACHABLE();
1518  return;
1519  }
1520 
1521  // Patch the call site depending on the state of the cache.
1522  if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1523  set_target(*code);
1524  } else if (state == MONOMORPHIC) {
1525  // Only move to megamorphic if the target changes.
1526  if (target() != *code) {
1527  set_target((strict_mode == kStrictMode)
1528  ? megamorphic_stub_strict()
1529  : megamorphic_stub());
1530  }
1531  } else if (state == MEGAMORPHIC) {
1532  // Update the stub cache.
1533  isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1534  }
1535 
1536  TRACE_IC("StoreIC", name, state, target());
1537 }
1538 
1539 
1540 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
1541  Handle<Map> new_receiver_map) {
1542  ASSERT(!new_receiver_map.is_null());
1543  for (int current = 0; current < receiver_maps->length(); ++current) {
1544  if (!receiver_maps->at(current).is_null() &&
1545  receiver_maps->at(current).is_identical_to(new_receiver_map)) {
1546  return false;
1547  }
1548  }
1549  receiver_maps->Add(new_receiver_map);
1550  return true;
1551 }
1552 
1553 
1554 void KeyedIC::GetReceiverMapsForStub(Handle<Code> stub,
1555  MapHandleList* result) {
1556  ASSERT(stub->is_inline_cache_stub());
1557  if (!string_stub().is_null() && stub.is_identical_to(string_stub())) {
1558  return result->Add(isolate()->factory()->string_map());
1559  } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
1560  if (stub->ic_state() == MONOMORPHIC) {
1561  result->Add(Handle<Map>(stub->FindFirstMap()));
1562  } else {
1563  ASSERT(stub->ic_state() == MEGAMORPHIC);
1564  AssertNoAllocation no_allocation;
1565  int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1566  for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
1567  RelocInfo* info = it.rinfo();
1568  Handle<Object> object(info->target_object());
1569  ASSERT(object->IsMap());
1570  AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
1571  }
1572  }
1573  }
1574 }
1575 
1576 
1578  StubKind stub_kind,
1579  StrictModeFlag strict_mode,
1580  Handle<Code> generic_stub) {
1581  State ic_state = target()->ic_state();
1582  KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind)
1585 
1586  // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1587  // via megamorphic stubs, since they don't have a map in their relocation info
1588  // and so the stubs can't be harvested for the object needed for a map check.
1589  if (target()->type() != NORMAL) {
1590  TRACE_GENERIC_IC("KeyedIC", "non-NORMAL target type");
1591  return generic_stub;
1592  }
1593 
1594  bool monomorphic = false;
1595  bool is_transition_stub = IsTransitionStubKind(stub_kind);
1596  Handle<Map> receiver_map(receiver->map());
1597  Handle<Map> monomorphic_map = receiver_map;
1598  MapHandleList target_receiver_maps;
1599  if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1600  // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1601  // yet will do so and stay there.
1602  monomorphic = true;
1603  } else {
1604  GetReceiverMapsForStub(Handle<Code>(target()), &target_receiver_maps);
1605  if (ic_state == MONOMORPHIC && is_transition_stub) {
1606  // The first time a receiver is seen that is a transitioned version of the
1607  // previous monomorphic receiver type, assume the new ElementsKind is the
1608  // monomorphic type. This benefits global arrays that only transition
1609  // once, and all call sites accessing them are faster if they remain
1610  // monomorphic. If this optimistic assumption is not true, the IC will
1611  // miss again and it will become polymorphic and support both the
1612  // untransitioned and transitioned maps.
1614  target_receiver_maps.at(0)->elements_kind(),
1615  receiver->GetElementsKind());
1616  }
1617  }
1618 
1619  if (monomorphic) {
1620  if (is_transition_stub) {
1621  monomorphic_map = ComputeTransitionedMap(receiver, stub_kind);
1622  ASSERT(*monomorphic_map != *receiver_map);
1623  stub_kind = GetNoTransitionStubKind(stub_kind);
1624  }
1625  return ComputeMonomorphicStub(
1626  monomorphic_map, stub_kind, strict_mode, generic_stub);
1627  }
1628  ASSERT(target() != *generic_stub);
1629 
1630  // Determine the list of receiver maps that this call site has seen,
1631  // adding the map that was just encountered.
1632  bool map_added =
1633  AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
1634  if (IsTransitionStubKind(stub_kind)) {
1635  Handle<Map> new_map = ComputeTransitionedMap(receiver, stub_kind);
1636  map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map);
1637  }
1638  if (!map_added) {
1639  // If the miss wasn't due to an unseen map, a polymorphic stub
1640  // won't help, use the generic stub.
1641  TRACE_GENERIC_IC("KeyedIC", "same map added twice");
1642  return generic_stub;
1643  }
1644 
1645  // If the maximum number of receiver maps has been exceeded, use the generic
1646  // version of the IC.
1647  if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1648  TRACE_GENERIC_IC("KeyedIC", "max polymorph exceeded");
1649  return generic_stub;
1650  }
1651 
1652  if ((Code::GetKeyedAccessGrowMode(target()->extra_ic_state()) ==
1654  grow_mode = ALLOW_JSARRAY_GROWTH;
1655  }
1656 
1658  isolate()->factory()->polymorphic_code_cache();
1659  Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode,
1660  strict_mode);
1662  Handle<Object> probe = cache->Lookup(&target_receiver_maps, flags);
1663  if (probe->IsCode()) return Handle<Code>::cast(probe);
1664 
1665  Handle<Code> stub =
1666  ComputePolymorphicStub(&target_receiver_maps, strict_mode, grow_mode);
1667  PolymorphicCodeCache::Update(cache, &target_receiver_maps, flags, stub);
1668  return stub;
1669 }
1670 
1671 
1673  Handle<Map> receiver_map,
1674  StrictModeFlag strict_mode,
1675  KeyedAccessGrowMode grow_mode) {
1676  if ((receiver_map->instance_type() & kNotStringTag) == 0) {
1677  ASSERT(!string_stub().is_null());
1678  return string_stub();
1679  } else {
1680  ASSERT(receiver_map->has_dictionary_elements() ||
1681  receiver_map->has_fast_smi_or_object_elements() ||
1682  receiver_map->has_fast_double_elements() ||
1683  receiver_map->has_external_array_elements());
1684  bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1685  return GetElementStubWithoutMapCheck(is_js_array,
1686  receiver_map->elements_kind(),
1687  grow_mode);
1688  }
1689 }
1690 
1691 
1692 Handle<Code> KeyedIC::ComputeMonomorphicStub(Handle<Map> receiver_map,
1693  StubKind stub_kind,
1694  StrictModeFlag strict_mode,
1695  Handle<Code> generic_stub) {
1696  ElementsKind elements_kind = receiver_map->elements_kind();
1697  if (IsFastElementsKind(elements_kind) ||
1698  IsExternalArrayElementsKind(elements_kind) ||
1699  IsDictionaryElementsKind(elements_kind)) {
1701  receiver_map, stub_kind, strict_mode);
1702  } else {
1703  return generic_stub;
1704  }
1705 }
1706 
1707 
1708 Handle<Map> KeyedIC::ComputeTransitionedMap(Handle<JSObject> receiver,
1709  StubKind stub_kind) {
1710  switch (stub_kind) {
1723  return JSObject::GetElementsTransitionMap(receiver,
1727  return JSObject::GetElementsTransitionMap(receiver,
1729  case KeyedIC::LOAD:
1732  UNREACHABLE();
1733  break;
1734  }
1735  return Handle<Map>::null();
1736 }
1737 
1738 
1740  bool is_js_array,
1741  ElementsKind elements_kind,
1742  KeyedAccessGrowMode grow_mode) {
1743  return KeyedStoreElementStub(is_js_array, elements_kind, grow_mode).GetCode();
1744 }
1745 
1746 
1748  MapHandleList* receiver_maps,
1749  StrictModeFlag strict_mode,
1750  KeyedAccessGrowMode grow_mode) {
1751  // Collect MONOMORPHIC stubs for all target_receiver_maps.
1752  CodeHandleList handler_ics(receiver_maps->length());
1753  MapHandleList transitioned_maps(receiver_maps->length());
1754  for (int i = 0; i < receiver_maps->length(); ++i) {
1755  Handle<Map> receiver_map(receiver_maps->at(i));
1756  Handle<Code> cached_stub;
1757  Handle<Map> transitioned_map =
1758  receiver_map->FindTransitionedMap(receiver_maps);
1759  if (!transitioned_map.is_null()) {
1760  cached_stub = ElementsTransitionAndStoreStub(
1761  receiver_map->elements_kind(), // original elements_kind
1762  transitioned_map->elements_kind(),
1763  receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array
1764  strict_mode, grow_mode).GetCode();
1765  } else {
1766  cached_stub = ComputeMonomorphicStubWithoutMapCheck(receiver_map,
1767  strict_mode,
1768  grow_mode);
1769  }
1770  ASSERT(!cached_stub.is_null());
1771  handler_ics.Add(cached_stub);
1772  transitioned_maps.Add(transitioned_map);
1773  }
1774  KeyedStoreStubCompiler compiler(isolate(), strict_mode, grow_mode);
1775  Handle<Code> code = compiler.CompileStorePolymorphic(
1776  receiver_maps, &handler_ics, &transitioned_maps);
1777  isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1778  PROFILE(isolate(),
1779  CodeCreateEvent(Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, *code, 0));
1780  return code;
1781 }
1782 
1783 
1784 KeyedIC::StubKind KeyedStoreIC::GetStubKind(Handle<JSObject> receiver,
1785  Handle<Object> key,
1786  Handle<Object> value) {
1787  ASSERT(key->IsSmi());
1788  int index = Smi::cast(*key)->value();
1789  bool allow_growth = receiver->IsJSArray() &&
1790  JSArray::cast(*receiver)->length()->IsSmi() &&
1791  index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
1792 
1793  if (allow_growth) {
1794  // Handle growing array in stub if necessary.
1795  if (receiver->HasFastSmiElements()) {
1796  if (value->IsHeapNumber()) {
1797  if (receiver->HasFastHoleyElements()) {
1799  } else {
1801  }
1802  }
1803  if (value->IsHeapObject()) {
1804  if (receiver->HasFastHoleyElements()) {
1806  } else {
1808  }
1809  }
1810  } else if (receiver->HasFastDoubleElements()) {
1811  if (!value->IsSmi() && !value->IsHeapNumber()) {
1812  if (receiver->HasFastHoleyElements()) {
1814  } else {
1816  }
1817  }
1818  }
1820  } else {
1821  // Handle only in-bounds elements accesses.
1822  if (receiver->HasFastSmiElements()) {
1823  if (value->IsHeapNumber()) {
1824  if (receiver->HasFastHoleyElements()) {
1826  } else {
1828  }
1829  } else if (value->IsHeapObject()) {
1830  if (receiver->HasFastHoleyElements()) {
1832  } else {
1834  }
1835  }
1836  } else if (receiver->HasFastDoubleElements()) {
1837  if (!value->IsSmi() && !value->IsHeapNumber()) {
1838  if (receiver->HasFastHoleyElements()) {
1840  } else {
1842  }
1843  }
1844  }
1845  return STORE_NO_TRANSITION;
1846  }
1847 }
1848 
1849 
1850 MaybeObject* KeyedStoreIC::Store(State state,
1851  StrictModeFlag strict_mode,
1852  Handle<Object> object,
1853  Handle<Object> key,
1854  Handle<Object> value,
1855  bool force_generic) {
1856  // Check for values that can be converted into a symbol directly or
1857  // is representable as a smi.
1858  key = TryConvertKey(key, isolate());
1859 
1860  if (key->IsSymbol()) {
1862 
1863  // Handle proxies.
1864  if (object->IsJSProxy()) {
1865  return JSProxy::cast(*object)->SetProperty(
1866  *name, *value, NONE, strict_mode);
1867  }
1868 
1869  // If the object is undefined or null it's illegal to try to set any
1870  // properties on it; throw a TypeError in that case.
1871  if (object->IsUndefined() || object->IsNull()) {
1872  return TypeError("non_object_property_store", object, name);
1873  }
1874 
1875  // Ignore stores where the receiver is not a JSObject.
1876  if (!object->IsJSObject()) return *value;
1877  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1878 
1879  // Check if the given name is an array index.
1880  uint32_t index;
1881  if (name->AsArrayIndex(&index)) {
1882  Handle<Object> result =
1883  JSObject::SetElement(receiver, index, value, NONE, strict_mode);
1884  RETURN_IF_EMPTY_HANDLE(isolate(), result);
1885  return *value;
1886  }
1887 
1888  // Update inline cache and stub cache.
1889  if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) {
1890  LookupResult lookup(isolate());
1891  if (LookupForWrite(receiver, name, &lookup)) {
1892  UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
1893  }
1894  }
1895 
1896  // Set the property.
1897  return receiver->SetProperty(*name, *value, NONE, strict_mode);
1898  }
1899 
1900  // Do not use ICs for objects that require access checks (including
1901  // the global object).
1902  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1903  ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1904 
1905  if (use_ic) {
1906  Handle<Code> stub = (strict_mode == kStrictMode)
1907  ? generic_stub_strict()
1908  : generic_stub();
1909  if (object->IsJSObject()) {
1910  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1911  if (receiver->elements()->map() ==
1912  isolate()->heap()->non_strict_arguments_elements_map()) {
1913  stub = non_strict_arguments_stub();
1914  } else if (!force_generic) {
1915  if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
1916  StubKind stub_kind = GetStubKind(receiver, key, value);
1917  stub = ComputeStub(receiver, stub_kind, strict_mode, stub);
1918  }
1919  } else {
1920  TRACE_GENERIC_IC("KeyedStoreIC", "force generic");
1921  }
1922  }
1923  if (!stub.is_null()) set_target(*stub);
1924  }
1925 
1926  TRACE_IC("KeyedStoreIC", key, state, target());
1927 
1928  // Set the property.
1930  isolate(), object , key, value, NONE, strict_mode);
1931 }
1932 
1933 
1934 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1935  State state,
1936  StrictModeFlag strict_mode,
1937  Handle<JSObject> receiver,
1938  Handle<String> name,
1939  Handle<Object> value) {
1940  ASSERT(!receiver->IsJSGlobalProxy());
1941  ASSERT(StoreICableLookup(lookup));
1942  // These are not cacheable, so we never see such LookupResults here.
1943  ASSERT(lookup->type() != HANDLER);
1944  // We get only called for properties or transitions, see StoreICableLookup.
1945  ASSERT(lookup->type() != NULL_DESCRIPTOR);
1946 
1947  // If the property has a non-field type allowing map transitions
1948  // where there is extra room in the object, we leave the IC in its
1949  // current state.
1950  PropertyType type = lookup->type();
1951 
1952  // Compute the code stub for this store; used for rewriting to
1953  // monomorphic state and making sure that the code stub is in the
1954  // stub cache.
1955  Handle<Code> code;
1956 
1957  switch (type) {
1958  case FIELD:
1960  name, receiver, lookup->GetFieldIndex(),
1961  Handle<Map>::null(), strict_mode);
1962  break;
1963  case MAP_TRANSITION:
1964  if (lookup->GetAttributes() == NONE) {
1965  Handle<Map> transition(lookup->GetTransitionMap());
1966  int index = transition->PropertyIndexFor(*name);
1968  name, receiver, index, transition, strict_mode);
1969  break;
1970  }
1971  // fall through.
1972  case NORMAL:
1973  case CONSTANT_FUNCTION:
1974  case CALLBACKS:
1975  case INTERCEPTOR:
1976  case CONSTANT_TRANSITION:
1977  // Always rewrite to the generic case so that we do not
1978  // repeatedly try to rewrite.
1979  code = (strict_mode == kStrictMode)
1980  ? generic_stub_strict()
1981  : generic_stub();
1982  break;
1983  case HANDLER:
1984  case NULL_DESCRIPTOR:
1985  UNREACHABLE();
1986  return;
1987  }
1988 
1989  ASSERT(!code.is_null());
1990 
1991  // Patch the call site depending on the state of the cache. Make
1992  // sure to always rewrite from monomorphic to megamorphic.
1994  if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1995  set_target(*code);
1996  } else if (state == MONOMORPHIC) {
1997  set_target((strict_mode == kStrictMode)
1998  ? *megamorphic_stub_strict()
1999  : *megamorphic_stub());
2000  }
2001 
2002  TRACE_IC("KeyedStoreIC", name, state, target());
2003 }
2004 
2005 
2006 #undef TRACE_IC
2007 
2008 
2009 // ----------------------------------------------------------------------------
2010 // Static IC stub generators.
2011 //
2012 
2013 // Used from ic-<arch>.cc.
2014 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) {
2015  HandleScope scope(isolate);
2016  ASSERT(args.length() == 2);
2017  CallIC ic(isolate);
2018  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2019  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2020  MaybeObject* maybe_result = ic.LoadFunction(state,
2021  extra_ic_state,
2022  args.at<Object>(0),
2023  args.at<String>(1));
2024  // Result could be a function or a failure.
2025  JSFunction* raw_function = NULL;
2026  if (!maybe_result->To(&raw_function)) return maybe_result;
2027 
2028  // The first time the inline cache is updated may be the first time the
2029  // function it references gets called. If the function is lazily compiled
2030  // then the first call will trigger a compilation. We check for this case
2031  // and we do the compilation immediately, instead of waiting for the stub
2032  // currently attached to the JSFunction object to trigger compilation.
2033  if (raw_function->is_compiled()) return raw_function;
2034 
2035  Handle<JSFunction> function(raw_function);
2037  return *function;
2038 }
2039 
2040 
2041 // Used from ic-<arch>.cc.
2042 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) {
2043  HandleScope scope(isolate);
2044  ASSERT(args.length() == 2);
2045  KeyedCallIC ic(isolate);
2046  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2047  MaybeObject* maybe_result =
2048  ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
2049  // Result could be a function or a failure.
2050  JSFunction* raw_function = NULL;
2051  if (!maybe_result->To(&raw_function)) return maybe_result;
2052 
2053  if (raw_function->is_compiled()) return raw_function;
2054 
2055  Handle<JSFunction> function(raw_function);
2057  return *function;
2058 }
2059 
2060 
2061 // Used from ic-<arch>.cc.
2062 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
2063  HandleScope scope(isolate);
2064  ASSERT(args.length() == 2);
2065  LoadIC ic(isolate);
2066  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2067  return ic.Load(state, args.at<Object>(0), args.at<String>(1));
2068 }
2069 
2070 
2071 // Used from ic-<arch>.cc
2072 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
2073  HandleScope scope(isolate);
2074  ASSERT(args.length() == 2);
2075  KeyedLoadIC ic(isolate);
2076  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2077  return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false);
2078 }
2079 
2080 
2081 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2082  HandleScope scope(isolate);
2083  ASSERT(args.length() == 2);
2084  KeyedLoadIC ic(isolate);
2085  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2086  return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true);
2087 }
2088 
2089 
2090 // Used from ic-<arch>.cc.
2091 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
2092  HandleScope scope;
2093  ASSERT(args.length() == 3);
2094  StoreIC ic(isolate);
2095  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2096  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2097  return ic.Store(state,
2098  Code::GetStrictMode(extra_ic_state),
2099  args.at<Object>(0),
2100  args.at<String>(1),
2101  args.at<Object>(2));
2102 }
2103 
2104 
2105 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
2106  NoHandleAllocation nha;
2107 
2108  ASSERT(args.length() == 2);
2109  JSArray* receiver = JSArray::cast(args[0]);
2110  Object* len = args[1];
2111 
2112  // The generated code should filter out non-Smis before we get here.
2113  ASSERT(len->IsSmi());
2114 
2115 #ifdef DEBUG
2116  // The length property has to be a writable callback property.
2117  LookupResult debug_lookup(isolate);
2118  receiver->LocalLookup(isolate->heap()->length_symbol(), &debug_lookup);
2119  ASSERT(debug_lookup.type() == CALLBACKS && !debug_lookup.IsReadOnly());
2120 #endif
2121 
2122  Object* result;
2123  { MaybeObject* maybe_result = receiver->SetElementsLength(len);
2124  if (!maybe_result->ToObject(&result)) return maybe_result;
2125  }
2126  return len;
2127 }
2128 
2129 
2130 // Extend storage is called in a store inline cache when
2131 // it is necessary to extend the properties array of a
2132 // JSObject.
2133 RUNTIME_FUNCTION(MaybeObject*, SharedStoreIC_ExtendStorage) {
2134  NoHandleAllocation na;
2135  ASSERT(args.length() == 3);
2136 
2137  // Convert the parameters
2138  JSObject* object = JSObject::cast(args[0]);
2139  Map* transition = Map::cast(args[1]);
2140  Object* value = args[2];
2141 
2142  // Check the object has run out out property space.
2143  ASSERT(object->HasFastProperties());
2144  ASSERT(object->map()->unused_property_fields() == 0);
2145 
2146  // Expand the properties array.
2147  FixedArray* old_storage = object->properties();
2148  int new_unused = transition->unused_property_fields();
2149  int new_size = old_storage->length() + new_unused + 1;
2150  Object* result;
2151  { MaybeObject* maybe_result = old_storage->CopySize(new_size);
2152  if (!maybe_result->ToObject(&result)) return maybe_result;
2153  }
2154  FixedArray* new_storage = FixedArray::cast(result);
2155  new_storage->set(old_storage->length(), value);
2156 
2157  // Set the new property value and do the map transition.
2158  object->set_properties(new_storage);
2159  object->set_map(transition);
2160 
2161  // Return the stored value.
2162  return value;
2163 }
2164 
2165 
2166 // Used from ic-<arch>.cc.
2167 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
2168  HandleScope scope(isolate);
2169  ASSERT(args.length() == 3);
2170  KeyedStoreIC ic(isolate);
2171  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2172  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2173  return ic.Store(state,
2174  Code::GetStrictMode(extra_ic_state),
2175  args.at<Object>(0),
2176  args.at<Object>(1),
2177  args.at<Object>(2),
2178  false);
2179 }
2180 
2181 
2182 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
2183  NoHandleAllocation na;
2184  ASSERT(args.length() == 3);
2185  KeyedStoreIC ic(isolate);
2186  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2187  Handle<Object> object = args.at<Object>(0);
2188  Handle<Object> key = args.at<Object>(1);
2189  Handle<Object> value = args.at<Object>(2);
2190  StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state);
2191  return Runtime::SetObjectProperty(isolate,
2192  object,
2193  key,
2194  value,
2195  NONE,
2196  strict_mode);
2197 }
2198 
2199 
2200 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2201  HandleScope scope(isolate);
2202  ASSERT(args.length() == 3);
2203  KeyedStoreIC ic(isolate);
2204  IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2205  Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2206  return ic.Store(state,
2207  Code::GetStrictMode(extra_ic_state),
2208  args.at<Object>(0),
2209  args.at<Object>(1),
2210  args.at<Object>(2),
2211  true);
2212 }
2213 
2214 
2215 void UnaryOpIC::patch(Code* code) {
2216  set_target(code);
2217 }
2218 
2219 
2220 const char* UnaryOpIC::GetName(TypeInfo type_info) {
2221  switch (type_info) {
2222  case UNINITIALIZED: return "Uninitialized";
2223  case SMI: return "Smi";
2224  case HEAP_NUMBER: return "HeapNumbers";
2225  case GENERIC: return "Generic";
2226  default: return "Invalid";
2227  }
2228 }
2229 
2230 
2232  switch (type_info) {
2233  case UNINITIALIZED:
2235  case SMI:
2236  case HEAP_NUMBER:
2237  return MONOMORPHIC;
2238  case GENERIC:
2239  return MEGAMORPHIC;
2240  }
2241  UNREACHABLE();
2243 }
2244 
2246  ::v8::internal::TypeInfo operand_type =
2248  if (operand_type.IsSmi()) {
2249  return SMI;
2250  } else if (operand_type.IsNumber()) {
2251  return HEAP_NUMBER;
2252  } else {
2253  return GENERIC;
2254  }
2255 }
2256 
2257 
2259  UnaryOpIC::TypeInfo current_type,
2260  UnaryOpIC::TypeInfo previous_type) {
2261  switch (previous_type) {
2263  return current_type;
2264  case UnaryOpIC::SMI:
2265  return (current_type == UnaryOpIC::GENERIC)
2269  return UnaryOpIC::GENERIC;
2270  case UnaryOpIC::GENERIC:
2271  // We should never do patching if we are in GENERIC state.
2272  UNREACHABLE();
2273  return UnaryOpIC::GENERIC;
2274  }
2275  UNREACHABLE();
2276  return UnaryOpIC::GENERIC;
2277 }
2278 
2279 
2281  set_target(code);
2282 }
2283 
2284 
2285 const char* BinaryOpIC::GetName(TypeInfo type_info) {
2286  switch (type_info) {
2287  case UNINITIALIZED: return "Uninitialized";
2288  case SMI: return "SMI";
2289  case INT32: return "Int32s";
2290  case HEAP_NUMBER: return "HeapNumbers";
2291  case ODDBALL: return "Oddball";
2292  case BOTH_STRING: return "BothStrings";
2293  case STRING: return "Strings";
2294  case GENERIC: return "Generic";
2295  default: return "Invalid";
2296  }
2297 }
2298 
2299 
2301  switch (type_info) {
2302  case UNINITIALIZED:
2304  case SMI:
2305  case INT32:
2306  case HEAP_NUMBER:
2307  case ODDBALL:
2308  case BOTH_STRING:
2309  case STRING:
2310  return MONOMORPHIC;
2311  case GENERIC:
2312  return MEGAMORPHIC;
2313  }
2314  UNREACHABLE();
2316 }
2317 
2318 
2321  if (x == UNINITIALIZED) return y;
2322  if (y == UNINITIALIZED) return x;
2323  if (x == y) return x;
2324  if (x == BOTH_STRING && y == STRING) return STRING;
2325  if (x == STRING && y == BOTH_STRING) return STRING;
2326  if (x == STRING || x == BOTH_STRING || y == STRING || y == BOTH_STRING) {
2327  return GENERIC;
2328  }
2329  if (x > y) return x;
2330  return y;
2331 }
2332 
2333 
2335  Handle<Object> right) {
2336  ::v8::internal::TypeInfo left_type =
2338  ::v8::internal::TypeInfo right_type =
2340 
2341  if (left_type.IsSmi() && right_type.IsSmi()) {
2342  return SMI;
2343  }
2344 
2345  if (left_type.IsInteger32() && right_type.IsInteger32()) {
2346  // Platforms with 32-bit Smis have no distinct INT32 type.
2347  if (kSmiValueSize == 32) return SMI;
2348  return INT32;
2349  }
2350 
2351  if (left_type.IsNumber() && right_type.IsNumber()) {
2352  return HEAP_NUMBER;
2353  }
2354 
2355  // Patching for fast string ADD makes sense even if only one of the
2356  // arguments is a string.
2357  if (left_type.IsString()) {
2358  return right_type.IsString() ? BOTH_STRING : STRING;
2359  } else if (right_type.IsString()) {
2360  return STRING;
2361  }
2362 
2363  // Check for oddball objects.
2364  if (left->IsUndefined() && right->IsNumber()) return ODDBALL;
2365  if (left->IsNumber() && right->IsUndefined()) return ODDBALL;
2366 
2367  return GENERIC;
2368 }
2369 
2370 
2371 RUNTIME_FUNCTION(MaybeObject*, UnaryOp_Patch) {
2372  ASSERT(args.length() == 4);
2373 
2374  HandleScope scope(isolate);
2375  Handle<Object> operand = args.at<Object>(0);
2376  Token::Value op = static_cast<Token::Value>(args.smi_at(1));
2377  UnaryOverwriteMode mode = static_cast<UnaryOverwriteMode>(args.smi_at(2));
2378  UnaryOpIC::TypeInfo previous_type =
2379  static_cast<UnaryOpIC::TypeInfo>(args.smi_at(3));
2380 
2382  type = UnaryOpIC::ComputeNewType(type, previous_type);
2383 
2384  UnaryOpStub stub(op, mode, type);
2385  Handle<Code> code = stub.GetCode();
2386  if (!code.is_null()) {
2387  if (FLAG_trace_ic) {
2388  PrintF("[UnaryOpIC (%s->%s)#%s]\n",
2389  UnaryOpIC::GetName(previous_type),
2390  UnaryOpIC::GetName(type),
2391  Token::Name(op));
2392  }
2393  UnaryOpIC ic(isolate);
2394  ic.patch(*code);
2395  }
2396 
2398  isolate->thread_local_top()->context_->builtins(), isolate);
2399  Object* builtin = NULL; // Initialization calms down the compiler.
2400  switch (op) {
2401  case Token::SUB:
2402  builtin = builtins->javascript_builtin(Builtins::UNARY_MINUS);
2403  break;
2404  case Token::BIT_NOT:
2405  builtin = builtins->javascript_builtin(Builtins::BIT_NOT);
2406  break;
2407  default:
2408  UNREACHABLE();
2409  }
2410 
2411  Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
2412 
2413  bool caught_exception;
2414  Handle<Object> result = Execution::Call(builtin_function, operand, 0, NULL,
2415  &caught_exception);
2416  if (caught_exception) {
2417  return Failure::Exception();
2418  }
2419  return *result;
2420 }
2421 
2422 RUNTIME_FUNCTION(MaybeObject*, BinaryOp_Patch) {
2423  ASSERT(args.length() == 5);
2424 
2425  HandleScope scope(isolate);
2426  Handle<Object> left = args.at<Object>(0);
2427  Handle<Object> right = args.at<Object>(1);
2428  int key = args.smi_at(2);
2429  Token::Value op = static_cast<Token::Value>(args.smi_at(3));
2430  BinaryOpIC::TypeInfo previous_type =
2431  static_cast<BinaryOpIC::TypeInfo>(args.smi_at(4));
2432 
2433  BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(left, right);
2434  type = BinaryOpIC::JoinTypes(type, previous_type);
2436  if ((type == BinaryOpIC::STRING || type == BinaryOpIC::BOTH_STRING) &&
2437  op != Token::ADD) {
2438  type = BinaryOpIC::GENERIC;
2439  }
2440  if (type == BinaryOpIC::SMI && previous_type == BinaryOpIC::SMI) {
2441  if (op == Token::DIV ||
2442  op == Token::MUL ||
2443  op == Token::SHR ||
2444  kSmiValueSize == 32) {
2445  // Arithmetic on two Smi inputs has yielded a heap number.
2446  // That is the only way to get here from the Smi stub.
2447  // With 32-bit Smis, all overflows give heap numbers, but with
2448  // 31-bit Smis, most operations overflow to int32 results.
2449  result_type = BinaryOpIC::HEAP_NUMBER;
2450  } else {
2451  // Other operations on SMIs that overflow yield int32s.
2452  result_type = BinaryOpIC::INT32;
2453  }
2454  }
2455  if (type == BinaryOpIC::INT32 && previous_type == BinaryOpIC::INT32) {
2456  // We must be here because an operation on two INT32 types overflowed.
2457  result_type = BinaryOpIC::HEAP_NUMBER;
2458  }
2459 
2460  BinaryOpStub stub(key, type, result_type);
2461  Handle<Code> code = stub.GetCode();
2462  if (!code.is_null()) {
2463  if (FLAG_trace_ic) {
2464  PrintF("[BinaryOpIC (%s->(%s->%s))#%s]\n",
2465  BinaryOpIC::GetName(previous_type),
2466  BinaryOpIC::GetName(type),
2467  BinaryOpIC::GetName(result_type),
2468  Token::Name(op));
2469  }
2470  BinaryOpIC ic(isolate);
2471  ic.patch(*code);
2472 
2473  // Activate inlined smi code.
2474  if (previous_type == BinaryOpIC::UNINITIALIZED) {
2476  }
2477  }
2478 
2480  isolate->thread_local_top()->context_->builtins(), isolate);
2481  Object* builtin = NULL; // Initialization calms down the compiler.
2482  switch (op) {
2483  case Token::ADD:
2484  builtin = builtins->javascript_builtin(Builtins::ADD);
2485  break;
2486  case Token::SUB:
2487  builtin = builtins->javascript_builtin(Builtins::SUB);
2488  break;
2489  case Token::MUL:
2490  builtin = builtins->javascript_builtin(Builtins::MUL);
2491  break;
2492  case Token::DIV:
2493  builtin = builtins->javascript_builtin(Builtins::DIV);
2494  break;
2495  case Token::MOD:
2496  builtin = builtins->javascript_builtin(Builtins::MOD);
2497  break;
2498  case Token::BIT_AND:
2499  builtin = builtins->javascript_builtin(Builtins::BIT_AND);
2500  break;
2501  case Token::BIT_OR:
2502  builtin = builtins->javascript_builtin(Builtins::BIT_OR);
2503  break;
2504  case Token::BIT_XOR:
2505  builtin = builtins->javascript_builtin(Builtins::BIT_XOR);
2506  break;
2507  case Token::SHR:
2508  builtin = builtins->javascript_builtin(Builtins::SHR);
2509  break;
2510  case Token::SAR:
2511  builtin = builtins->javascript_builtin(Builtins::SAR);
2512  break;
2513  case Token::SHL:
2514  builtin = builtins->javascript_builtin(Builtins::SHL);
2515  break;
2516  default:
2517  UNREACHABLE();
2518  }
2519 
2520  Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
2521 
2522  bool caught_exception;
2523  Handle<Object> builtin_args[] = { right };
2524  Handle<Object> result = Execution::Call(builtin_function,
2525  left,
2526  ARRAY_SIZE(builtin_args),
2527  builtin_args,
2528  &caught_exception);
2529  if (caught_exception) {
2530  return Failure::Exception();
2531  }
2532  return *result;
2533 }
2534 
2535 
2536 Code* CompareIC::GetRawUninitialized(Token::Value op) {
2537  ICCompareStub stub(op, UNINITIALIZED);
2538  Code* code = NULL;
2539  CHECK(stub.FindCodeInCache(&code));
2540  return code;
2541 }
2542 
2543 
2545  ICCompareStub stub(op, UNINITIALIZED);
2546  return stub.GetCode();
2547 }
2548 
2549 
2551  int key = target->major_key();
2552  if (key == CodeStub::Compare) return GENERIC;
2553  ASSERT(key == CodeStub::CompareIC);
2554  return static_cast<State>(target->compare_state());
2555 }
2556 
2557 
2559  ASSERT(target->major_key() == CodeStub::CompareIC);
2560  return static_cast<Token::Value>(target->compare_operation());
2561 }
2562 
2563 
2564 const char* CompareIC::GetStateName(State state) {
2565  switch (state) {
2566  case UNINITIALIZED: return "UNINITIALIZED";
2567  case SMIS: return "SMIS";
2568  case HEAP_NUMBERS: return "HEAP_NUMBERS";
2569  case OBJECTS: return "OBJECTS";
2570  case KNOWN_OBJECTS: return "OBJECTS";
2571  case SYMBOLS: return "SYMBOLS";
2572  case STRINGS: return "STRINGS";
2573  case GENERIC: return "GENERIC";
2574  default:
2575  UNREACHABLE();
2576  return NULL;
2577  }
2578 }
2579 
2580 
2581 CompareIC::State CompareIC::TargetState(State state,
2582  bool has_inlined_smi_code,
2583  Handle<Object> x,
2584  Handle<Object> y) {
2585  switch (state) {
2586  case UNINITIALIZED:
2587  if (x->IsSmi() && y->IsSmi()) return SMIS;
2588  if (x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS;
2590  // Ordered comparisons treat undefined as NaN, so the
2591  // HEAP_NUMBER stub will do the right thing.
2592  if ((x->IsNumber() && y->IsUndefined()) ||
2593  (y->IsNumber() && x->IsUndefined())) {
2594  return HEAP_NUMBERS;
2595  }
2596  }
2597  if (x->IsSymbol() && y->IsSymbol()) {
2598  // We compare symbols as strings if we need to determine
2599  // the order in a non-equality compare.
2600  return Token::IsEqualityOp(op_) ? SYMBOLS : STRINGS;
2601  }
2602  if (x->IsString() && y->IsString()) return STRINGS;
2603  if (!Token::IsEqualityOp(op_)) return GENERIC;
2604  if (x->IsJSObject() && y->IsJSObject()) {
2605  if (Handle<JSObject>::cast(x)->map() ==
2606  Handle<JSObject>::cast(y)->map() &&
2607  Token::IsEqualityOp(op_)) {
2608  return KNOWN_OBJECTS;
2609  } else {
2610  return OBJECTS;
2611  }
2612  }
2613  return GENERIC;
2614  case SMIS:
2615  return has_inlined_smi_code && x->IsNumber() && y->IsNumber()
2616  ? HEAP_NUMBERS
2617  : GENERIC;
2618  case SYMBOLS:
2620  return x->IsString() && y->IsString() ? STRINGS : GENERIC;
2621  case HEAP_NUMBERS:
2622  case STRINGS:
2623  case OBJECTS:
2624  case KNOWN_OBJECTS:
2625  case GENERIC:
2626  return GENERIC;
2627  }
2628  UNREACHABLE();
2629  return GENERIC;
2630 }
2631 
2632 
2633 // Used from ic_<arch>.cc.
2634 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2635  NoHandleAllocation na;
2636  ASSERT(args.length() == 3);
2637  CompareIC ic(isolate, static_cast<Token::Value>(args.smi_at(2)));
2638  ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
2639  return ic.target();
2640 }
2641 
2642 
2643 RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) {
2644  ASSERT(args.length() == 3);
2645 
2646  HandleScope scope(isolate);
2647  Handle<Object> object = args.at<Object>(0);
2648  Register tos = Register::from_code(args.smi_at(1));
2649  ToBooleanStub::Types old_types(args.smi_at(2));
2650 
2651  ToBooleanStub::Types new_types(old_types);
2652  bool to_boolean_value = new_types.Record(object);
2653  old_types.TraceTransition(new_types);
2654 
2655  ToBooleanStub stub(tos, new_types);
2656  Handle<Code> code = stub.GetCode();
2657  ToBooleanIC ic(isolate);
2658  ic.patch(*code);
2659  return Smi::FromInt(to_boolean_value ? 1 : 0);
2660 }
2661 
2662 
2664  set_target(code);
2665 }
2666 
2667 
2668 static const Address IC_utilities[] = {
2669 #define ADDR(name) FUNCTION_ADDR(name),
2671  NULL
2672 #undef ADDR
2673 };
2674 
2675 
2677  return IC_utilities[id];
2678 }
2679 
2680 
2681 } } // namespace v8::internal
byte * Address
Definition: globals.h:172
void patch(Code *code)
Definition: ic.cc:2663
virtual Handle< Code > string_stub()
Definition: ic.h:527
int IndexInCodeCache(Object *name, Code *code)
Definition: objects.cc:4971
static TypeInfo GetTypeInfo(Handle< Object > operand)
Definition: ic.cc:2245
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:1944
Code * builtin(Name name)
Definition: builtins.h:312
static bool CompileLazy(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7465
Object * function() const
Definition: frames-inl.h:231
static Object *& Object_at(Address addr)
Definition: v8memory.h:75
bool IsExternalArrayElementsKind(ElementsKind kind)
Definition: elements-kind.h:94
void UpdateCaches(LookupResult *lookup, State state, Code::ExtraICState extra_ic_state, Handle< Object > object, Handle< String > name)
Definition: ic.cc:692
virtual Code::Kind kind() const =0
Handle< Code > ComputeLoadNormal()
Definition: stub-cache.cc:232
Handle< Code > ComputeCallGlobal(int argc, Code::Kind, Code::ExtraICState extra_state, Handle< String > name, Handle< JSObject > receiver, Handle< GlobalObject > holder, Handle< JSGlobalPropertyCell > cell, Handle< JSFunction > function)
Definition: stub-cache.cc:693
Code * target() const
Definition: ic.h:97
void set(int index, Object *value)
Definition: objects-inl.h:1695
void PrintF(const char *format,...)
Definition: v8utils.cc:40
Handle< Code > ComputeKeyedLoadFunctionPrototype(Handle< String > name, Handle< JSFunction > receiver)
Definition: stub-cache.cc:368
Handle< Code > ComputeStoreField(Handle< String > name, Handle< JSObject > receiver, int field_index, Handle< Map > transition, StrictModeFlag strict_mode)
Definition: stub-cache.cc:385
static TypeFeedbackInfo * cast(Object *obj)
static String * cast(Object *obj)
virtual bool IsGeneric() const
Definition: ic.h:100
static const char * GetName(TypeInfo type_info)
Definition: ic.cc:2220
Code * Set(String *name, Map *map, Code *code)
Definition: stub-cache.cc:59
virtual Handle< Code > GetElementStubWithoutMapCheck(bool is_js_array, ElementsKind elements_kind, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1739
Isolate * isolate()
Definition: heap-inl.h:494
double DoubleToInteger(double x)
int unused_property_fields()
Definition: objects-inl.h:2874
static const char * Name(Value tok)
Definition: token.h:196
static Smi * FromInt(int value)
Definition: objects-inl.h:973
#define LOG(isolate, Call)
Definition: log.h:81
MUST_USE_RESULT MaybeObject * LoadFunction(State state, Handle< Object > object, Handle< Object > key)
Definition: ic.cc:764
void patch(Code *code)
Definition: ic.cc:2215
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
Definition: flags.cc:1349
MUST_USE_RESULT MaybeObject * Load(State state, Handle< Object > object, Handle< String > name)
Definition: ic.cc:812
static Handle< T > cast(Handle< S > that)
Definition: handles.h:81
const int kSmiValueSize
Definition: v8.h:3900
static Map * cast(Object *obj)
static KeyedAccessGrowMode GetKeyedAccessGrowMode(ExtraICState extra_ic_state)
Definition: objects.h:4381
T & at(int i) const
Definition: list.h:85
Flag flags[]
Definition: flags.cc:1467
Builtins * builtins()
Definition: isolate.h:909
static Failure * Exception()
Definition: objects-inl.h:1016
#define TRACE_IC(type, name, old_state, new_target)
Definition: ic.cc:109
static MUST_USE_RESULT MaybeObject * SetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attr, StrictModeFlag strict_mode)
Definition: runtime.cc:4540
void set_ic_with_type_info_count(int count)
Handle< Code > ComputeLoadCallback(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< AccessorInfo > callback)
Definition: stub-cache.cc:155
Address address() const
Definition: ic-inl.h:41
Handle< Code > ComputeKeyedLoadOrStoreElement(Handle< Map > receiver_map, KeyedIC::StubKind stub_kind, StrictModeFlag strict_mode)
Definition: stub-cache.cc:406
List< Handle< Map > > MapHandleList
Definition: list.h:193
Failure * TypeError(const char *type, Handle< Object > object, Handle< Object > key)
Definition: ic.cc:280
#define ASSERT(condition)
Definition: checks.h:270
Handle< Code > ComputeCallMegamorphic(int argc, Code::Kind kind, Code::ExtraICState state)
Definition: stub-cache.cc:835
void set_profiler_ticks(int ticks)
Definition: objects-inl.h:3164
int ComputeExpressionsCount() const
Definition: frames.cc:586
#define PROFILE(isolate, Call)
Definition: cpu-profiler.h:190
static State StateFrom(Code *target, Object *receiver, Object *name)
Definition: ic.cc:227
Handle< Code > ComputeKeyedLoadInterceptor(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder)
Definition: stub-cache.cc:296
static TypeInfo GetTypeInfo(Handle< Object > left, Handle< Object > right)
Definition: ic.cc:2334
Code::Kind kind_
Definition: ic.h:259
static const char * GetName(TypeInfo type_info)
Definition: ic.cc:2285
Isolate * isolate() const
Definition: ic.h:140
static const ExtraICState kNoExtraICState
Definition: objects.h:4199
Handle< Code > ComputeKeyedLoadCallback(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< AccessorInfo > callback)
Definition: stub-cache.cc:314
#define CHECK(condition)
Definition: checks.h:56
int isnan(double x)
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:282
#define RETURN_IF_EMPTY_HANDLE(isolate, call)
Definition: isolate.h:134
Factory * factory()
Definition: isolate.h:977
bool IsFastElementsKind(ElementsKind kind)
PropertyAttributes
static uint32_t update(uint32_t previous, StringStubFeedbackvalue)
Definition: utils.h:267
static TypeInfo TypeFromValue(Handle< Object > value)
Definition: type-info.cc:45
MUST_USE_RESULT MaybeObject * Store(State state, StrictModeFlag strict_mode, Handle< Object > object, Handle< String > name, Handle< Object > value)
Definition: ic.cc:1334
static Code * cast(Object *obj)
static State ToState(TypeInfo type_info)
Definition: ic.cc:2300
void ReceiverToObjectIfRequired(Handle< Object > callee, Handle< Object > object)
Definition: ic.cc:483
void PatchInlinedSmiCode(Address address, InlinedSmiCheck check)
static Smi * cast(Object *object)
Handle< Code > ComputeKeyedLoadArrayLength(Handle< String > name, Handle< JSArray > receiver)
Definition: stub-cache.cc:335
Handle< Code > ComputeCallInterceptor(int argc, Code::Kind, Code::ExtraICState extra_state, Handle< String > name, Handle< Object > object, Handle< JSObject > holder)
Definition: stub-cache.cc:656
Handle< Code > ComputeCallArguments(int argc, Code::Kind kind)
Definition: stub-cache.cc:818
Handle< Code > ComputeLoadField(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, int field_index)
Definition: stub-cache.cc:136
static JSFunctionProxy * cast(Object *obj)
const uint32_t kNotStringTag
Definition: objects.h:438
HANDLE HANDLE LPSTACKFRAME64 StackFrame
static const int kCallerPCOffset
Definition: frames-arm.h:129
#define UNREACHABLE()
Definition: checks.h:50
Handle< Code > ComputeStoreNormal(StrictModeFlag strict_mode)
Definition: stub-cache.cc:474
static void Update(Handle< PolymorphicCodeCache > cache, MapHandleList *maps, Code::Flags flags, Handle< Code > code)
Definition: objects.cc:5504
static void PrintTop(FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:754
static void PostPatching(Address address, Code *target, Code *old_target)
Definition: ic.cc:309
Address pc() const
Definition: ic.h:139
Handle< Code > ComputeCallField(int argc, Code::Kind, Code::ExtraICState extra_state, Handle< String > name, Handle< Object > object, Handle< JSObject > holder, int index)
Definition: stub-cache.cc:618
static Address c_entry_fp(ThreadLocalTop *thread)
Definition: isolate.h:614
Address fp() const
Definition: ic.h:138
static InlineCacheHolderFlag ExtractCacheHolderFromFlags(Flags flags)
Definition: objects-inl.h:3369
IC(FrameDepth depth, Isolate *isolate)
Definition: ic.cc:112
static const int kCallerFPOffset
Definition: frames-arm.h:127
V8EXPORT Local< Value > GetPrototype()
Definition: api.cc:2892
static bool IsValid(intptr_t value)
Definition: objects-inl.h:1051
byte * instruction_start()
Definition: objects-inl.h:4376
static Handle< Map > GetElementsTransitionMap(Handle< JSObject > object, ElementsKind to_kind)
Definition: objects.cc:2303
static StrictModeFlag GetStrictMode(ExtraICState extra_ic_state)
Definition: objects.h:4377
const int kPointerSize
Definition: globals.h:234
void SetExpression(int index, Object *value)
Definition: frames-inl.h:158
Handle< Object > SetProperty(Handle< Object > object, Handle< Object > key, Handle< Object > value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: handles.cc:232
int Compare(const T &a, const T &b)
Definition: utils.h:156
static Code * GetTargetAtAddress(Address address)
Definition: ic-inl.h:69
static Address & Address_at(Address addr)
Definition: v8memory.h:71
Handle< Code > ComputeKeyedLoadStringLength(Handle< String > name, Handle< String > receiver)
Definition: stub-cache.cc:351
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
MUST_USE_RESULT MaybeObject * LoadFunction(State state, Code::ExtraICState extra_ic_state, Handle< Object > object, Handle< String > name)
Definition: ic.cc:509
static ExtraICState ComputeExtraICState(KeyedAccessGrowMode grow_mode, StrictModeFlag strict_mode)
Definition: objects.h:4386
static bool decode(uint32_t value)
Definition: utils.h:272
static Register from_code(int code)
static void Clear(Address address, Code *target)
Definition: ic.cc:367
static State ToState(TypeInfo type_info)
Definition: ic.cc:2231
static MUST_USE_RESULT Handle< Object > SetElement(Handle< JSObject > object, uint32_t index, Handle< Object > value, PropertyAttributes attr, StrictModeFlag strict_mode, SetPropertyMode set_mode=SET_PROPERTY)
Definition: objects.cc:9663
bool is_inline_cache_stub()
Definition: objects-inl.h:3306
Definition: v8.h:104
Handle< Code > ComputeStoreGlobal(Handle< String > name, Handle< GlobalObject > receiver, Handle< JSGlobalPropertyCell > cell, StrictModeFlag strict_mode)
Definition: stub-cache.cc:481
static JavaScriptFrame * cast(StackFrame *frame)
Definition: frames.h:532
virtual Handle< Code > GetElementStubWithoutMapCheck(bool is_js_array, ElementsKind elements_kind, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1048
Failure * Throw(Object *exception, MessageLocation *location=NULL)
Definition: isolate.cc:918
InlineCacheState ic_state()
Definition: objects-inl.h:3024
static bool IsEqualityOp(Value op)
Definition: token.h:222
static const int kCallTargetAddressOffset
Handle< Code > ComputeStoreInterceptor(Handle< String > name, Handle< JSObject > receiver, StrictModeFlag strict_mode)
Definition: stub-cache.cc:536
static Handle< Object > Call(Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:144
#define ADDR(name)
static JSArray * cast(Object *obj)
StubCache * stub_cache()
Definition: isolate.h:822
virtual Handle< Code > ComputePolymorphicStub(MapHandleList *receiver_maps, StrictModeFlag strict_mode, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1057
Handle< Code > ComputeLoadViaGetter(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > getter)
Definition: stub-cache.cc:175
static TypeInfo ComputeNewType(TypeInfo type, TypeInfo previous)
Definition: ic.cc:2258
Handle< Object > TryCallAsFunction(Handle< Object > object)
Definition: ic.cc:466
InlineCacheState State
Definition: ic.h:82
Handle< Code > ComputeKeyedLoadField(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, int field_index)
Definition: stub-cache.cc:257
MUST_USE_RESULT MaybeObject * Load(State state, Handle< Object > object, Handle< Object > key, bool force_generic_stub)
Definition: ic.cc:1098
Handle< Code > ComputeCallNormal(int argc, Code::Kind kind, Code::ExtraICState state)
Definition: stub-cache.cc:801
#define IC_UTIL_LIST(ICU)
Definition: ic.h:40
bool is_null() const
Definition: handles.h:87
Handle< Object > NewReferenceError(const char *type, Vector< Handle< Object > > args)
Definition: factory.cc:646
Handle< Code > ComputeKeyedStoreField(Handle< String > name, Handle< JSObject > receiver, int field_index, Handle< Map > transition, StrictModeFlag strict_mode)
Definition: stub-cache.cc:552
ExtraICState extra_ic_state()
Definition: objects-inl.h:3037
static Object * cast(Object *value)
Definition: objects.h:962
static MUST_USE_RESULT MaybeObject * FunctionGetPrototype(Object *object, void *)
Definition: accessors.cc:449
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, PropertyType type=NORMAL, int argc=-1, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:3312
Handle< Object > NewTypeError(const char *type, Vector< Handle< Object > > args)
Definition: factory.cc:614
static Token::Value ComputeOperation(Code *target)
Definition: ic.cc:2558
static Handle< Object > GetFunctionDelegate(Handle< Object > object)
Definition: execution.cc:223
static JSValue * cast(Object *obj)
Definition: objects-inl.h:4327
static Handle< T > null()
Definition: handles.h:86
virtual Handle< Code > ComputePolymorphicStub(MapHandleList *receiver_maps, StrictModeFlag strict_mode, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1747
Map * FindFirstMap()
Definition: objects.cc:8230
#define HEAP
Definition: isolate.h:1408
static JSObject * GetCodeCacheHolder(Object *object, InlineCacheHolderFlag holder)
Definition: ic-inl.h:127
static void SetTargetAtAddress(Address address, Code *target)
Definition: ic-inl.h:80
MUST_USE_RESULT MaybeObject * GetProperty(String *key)
Definition: objects-inl.h:851
static MUST_USE_RESULT MaybeObject * GetObjectProperty(Isolate *isolate, Handle< Object > object, Handle< Object > key)
Definition: runtime.cc:4288
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
virtual Handle< Code > ComputePolymorphicStub(MapHandleList *receiver_maps, StrictModeFlag strict_mode, KeyedAccessGrowMode grow_mode)=0
static JSProxy * cast(Object *obj)
static State ComputeState(Code *target)
Definition: ic.cc:2550
virtual Handle< Code > string_stub()
Definition: ic.h:430
Counters * counters()
Definition: isolate.h:804
Handle< Code > ComputeMonomorphicStub(LookupResult *lookup, State state, Code::ExtraICState extra_state, Handle< Object > object, Handle< String > name)
Definition: ic.cc:638
Handle< Code > ComputeStub(Handle< JSObject > receiver, StubKind stub_kind, StrictModeFlag strict_mode, Handle< Code > default_stub)
Definition: ic.cc:1577
static FixedArray * cast(Object *obj)
#define TRACE_GENERIC_IC(type, reason)
Definition: ic.cc:106
static Handle< Object > GetElement(Handle< Object > object, uint32_t index)
Definition: objects.cc:244
bool TryUpdateExtraICState(LookupResult *lookup, Handle< Object > object, Code::ExtraICState *extra_ic_state)
Definition: ic.cc:594
void set_target(Code *code)
Definition: ic.h:149
Handle< Code > ComputeCallPreMonomorphic(int argc, Code::Kind kind, Code::ExtraICState extra_state)
Definition: stub-cache.cc:783
virtual Handle< Code > GetElementStubWithoutMapCheck(bool is_js_array, ElementsKind elements_kind, KeyedAccessGrowMode grow_mode)=0
Handle< Code > ComputeLoadNonexistent(Handle< String > name, Handle< JSObject > receiver)
Definition: stub-cache.cc:103
static TypeInfo JoinTypes(TypeInfo x, TypeInfo y)
Definition: ic.cc:2319
Handle< Code > ComputeLoadConstant(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > value)
Definition: stub-cache.cc:194
Vector< Handle< Object > > HandleVector(v8::internal::Handle< T > *elms, int length)
Definition: v8utils.h:114
const int kMaxKeyedPolymorphism
Definition: type-info.h:39
Handle< Code > ComputeLoadInterceptor(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder)
Definition: stub-cache.cc:214
Handle< Code > CompileLoadPolymorphic(MapHandleList *receiver_maps, CodeHandleList *handler_ics)
Handle< Code > ComputeCallConstant(int argc, Code::Kind, Code::ExtraICState extra_state, Handle< String > name, Handle< Object > object, Handle< JSObject > holder, Handle< JSFunction > function)
Definition: stub-cache.cc:577
Handle< Code > CompileStorePolymorphic(MapHandleList *receiver_maps, CodeHandleList *handler_stubs, MapHandleList *transitioned_maps)
static const char * GetStateName(State state)
Definition: ic.cc:2564
KeyedAccessGrowMode
Definition: objects.h:141
MUST_USE_RESULT MaybeObject * Store(State state, StrictModeFlag strict_mode, Handle< Object > object, Handle< Object > name, Handle< Object > value, bool force_generic)
Definition: ic.cc:1850
ThreadLocalTop * thread_local_top()
Definition: isolate.h:824
void patch(Code *code)
Definition: ic.cc:2280
RelocInfo::Mode ComputeMode()
Definition: ic.cc:267
static Address AddressFromUtilityId(UtilityId id)
Definition: ic.cc:2676
static Handle< Code > GetUninitialized(Token::Value op)
Definition: ic.cc:2544
#define ARRAY_SIZE(a)
Definition: globals.h:295
Handle< Code > ComputeKeyedLoadConstant(Handle< String > name, Handle< JSObject > receiver, Handle< JSObject > holder, Handle< JSFunction > value)
Definition: stub-cache.cc:276
bool IsContextual(Handle< Object > receiver)
Definition: ic.h:115
Failure * ReferenceError(const char *type, Handle< String > name)
Definition: ic.cc:291
Handle< Code > ComputeLoadGlobal(Handle< String > name, Handle< JSObject > receiver, Handle< GlobalObject > holder, Handle< JSGlobalPropertyCell > cell, bool is_dont_delete)
Definition: stub-cache.cc:237
static JSObject * cast(Object *obj)
static MUST_USE_RESULT MaybeObject * GetElementOrCharAt(Isolate *isolate, Handle< Object > object, uint32_t index)
Definition: runtime.cc:4263
FlagType type() const
Definition: flags.cc:1358
Handle< Code > ComputeMonomorphicStubWithoutMapCheck(Handle< Map > receiver_map, StrictModeFlag strict_mode, KeyedAccessGrowMode grow_mode)
Definition: ic.cc:1672
static void Clear(Address address)
Definition: ic.cc:340
bool IsDictionaryElementsKind(ElementsKind kind)
Definition: elements-kind.h:89
int FastD2I(double x)
Definition: conversions.h:64
Handle< Code > ComputeStoreCallback(Handle< String > name, Handle< JSObject > receiver, Handle< AccessorInfo > callback, StrictModeFlag strict_mode)
Definition: stub-cache.cc:499
static bool IsOrderedRelationalCompareOp(Value op)
Definition: token.h:218
Handle< Code > ComputeStoreViaSetter(Handle< String > name, Handle< JSObject > receiver, Handle< JSFunction > setter, StrictModeFlag strict_mode)
Definition: stub-cache.cc:518
static JSFunction * cast(Object *obj)