Revision f230a1cf deps/v8/src/ic.cc

View differences:

deps/v8/src/ic.cc
71 71

  
72 72

  
73 73
void IC::TraceIC(const char* type,
74
                 Handle<Object> name,
75
                 State old_state,
76
                 Code* new_target) {
74
                 Handle<Object> name) {
77 75
  if (FLAG_trace_ic) {
78
    Object* undef = new_target->GetHeap()->undefined_value();
79
    State new_state = StateFrom(new_target, undef, undef);
80
    PrintF("[%s in ", type);
81
    Isolate* isolate = new_target->GetIsolate();
82
    StackFrameIterator it(isolate);
76
    Code* new_target = raw_target();
77
    State new_state = new_target->ic_state();
78
    PrintF("[%s%s in ", new_target->is_keyed_stub() ? "Keyed" : "", type);
79
    StackFrameIterator it(isolate());
83 80
    while (it.frame()->fp() != this->fp()) it.Advance();
84 81
    StackFrame* raw_frame = it.frame();
85 82
    if (raw_frame->is_internal()) {
86
      Code* apply_builtin = isolate->builtins()->builtin(
83
      Code* apply_builtin = isolate()->builtins()->builtin(
87 84
          Builtins::kFunctionApply);
88 85
      if (raw_frame->unchecked_code() == apply_builtin) {
89 86
        PrintF("apply from ");
......
91 88
        raw_frame = it.frame();
92 89
      }
93 90
    }
94
    JavaScriptFrame::PrintTop(isolate, stdout, false, true);
95
    Code::ExtraICState state = new_target->extra_ic_state();
91
    JavaScriptFrame::PrintTop(isolate(), stdout, false, true);
92
    Code::ExtraICState extra_state = new_target->extra_ic_state();
96 93
    const char* modifier =
97
        GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(state));
94
        GetTransitionMarkModifier(Code::GetKeyedAccessStoreMode(extra_state));
98 95
    PrintF(" (%c->%c%s)",
99
           TransitionMarkFromState(old_state),
96
           TransitionMarkFromState(state()),
100 97
           TransitionMarkFromState(new_state),
101 98
           modifier);
102 99
    name->Print();
......
117 114
#define TRACE_GENERIC_IC(isolate, type, reason)
118 115
#endif  // DEBUG
119 116

  
120
#define TRACE_IC(type, name, old_state, new_target)             \
121
  ASSERT((TraceIC(type, name, old_state, new_target), true))
117
#define TRACE_IC(type, name)             \
118
  ASSERT((TraceIC(type, name), true))
122 119

  
123
IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) {
120
IC::IC(FrameDepth depth, Isolate* isolate)
121
    : isolate_(isolate),
122
      target_set_(false) {
124 123
  // To improve the performance of the (much used) IC code, we unfold a few
125 124
  // levels of the stack frame iteration code. This yields a ~35% speedup when
126 125
  // running DeltaBlue and a ~25% speedup of gbemu with the '--nouse-ic' flag.
......
145 144
#endif
146 145
  fp_ = fp;
147 146
  pc_address_ = StackFrame::ResolveReturnAddressLocation(pc_address);
147
  target_ = handle(raw_target(), isolate);
148
  state_ = target_->ic_state();
148 149
}
149 150

  
150 151

  
......
179 180
#endif
180 181

  
181 182

  
182
static bool TryRemoveInvalidPrototypeDependentStub(Code* target,
183
                                                   Object* receiver,
184
                                                   Object* name) {
185
  if (target->is_keyed_load_stub() ||
186
      target->is_keyed_call_stub() ||
187
      target->is_keyed_store_stub()) {
183
static bool HasInterceptorGetter(JSObject* object) {
184
  return !object->GetNamedInterceptor()->getter()->IsUndefined();
185
}
186

  
187

  
188
static bool HasInterceptorSetter(JSObject* object) {
189
  return !object->GetNamedInterceptor()->setter()->IsUndefined();
190
}
191

  
192

  
193
static void LookupForRead(Handle<Object> object,
194
                          Handle<String> name,
195
                          LookupResult* lookup) {
196
  // Skip all the objects with named interceptors, but
197
  // without actual getter.
198
  while (true) {
199
    object->Lookup(*name, lookup);
200
    // Besides normal conditions (property not found or it's not
201
    // an interceptor), bail out if lookup is not cacheable: we won't
202
    // be able to IC it anyway and regular lookup should work fine.
203
    if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
204
      return;
205
    }
206

  
207
    Handle<JSObject> holder(lookup->holder(), lookup->isolate());
208
    if (HasInterceptorGetter(*holder)) {
209
      return;
210
    }
211

  
212
    holder->LocalLookupRealNamedProperty(*name, lookup);
213
    if (lookup->IsFound()) {
214
      ASSERT(!lookup->IsInterceptor());
215
      return;
216
    }
217

  
218
    Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
219
    if (proto->IsNull()) {
220
      ASSERT(!lookup->IsFound());
221
      return;
222
    }
223

  
224
    object = proto;
225
  }
226
}
227

  
228

  
229
bool CallIC::TryUpdateExtraICState(LookupResult* lookup,
230
                                   Handle<Object> object) {
231
  if (!lookup->IsConstantFunction()) return false;
232
  JSFunction* function = lookup->GetConstantFunction();
233
  if (!function->shared()->HasBuiltinFunctionId()) return false;
234

  
235
  // Fetch the arguments passed to the called function.
236
  const int argc = target()->arguments_count();
237
  Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
238
  Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
239
  Arguments args(argc + 1,
240
                 &Memory::Object_at(fp +
241
                                    StandardFrameConstants::kCallerSPOffset +
242
                                    argc * kPointerSize));
243
  switch (function->shared()->builtin_function_id()) {
244
    case kStringCharCodeAt:
245
    case kStringCharAt:
246
      if (object->IsString()) {
247
        String* string = String::cast(*object);
248
        // Check there's the right string value or wrapper in the receiver slot.
249
        ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
250
        // If we're in the default (fastest) state and the index is
251
        // out of bounds, update the state to record this fact.
252
        if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB &&
253
            argc >= 1 && args[1]->IsNumber()) {
254
          double index = DoubleToInteger(args.number_at(1));
255
          if (index < 0 || index >= string->length()) {
256
            extra_ic_state_ =
257
                StringStubState::update(extra_ic_state(),
258
                                        STRING_INDEX_OUT_OF_BOUNDS);
259
            return true;
260
          }
261
        }
262
      }
263
      break;
264
    default:
265
      return false;
266
  }
267
  return false;
268
}
269

  
270

  
271
bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
272
                                                Handle<String> name) {
273
  DisallowHeapAllocation no_gc;
274

  
275
  if (target()->is_call_stub()) {
276
    LookupResult lookup(isolate());
277
    LookupForRead(receiver, name, &lookup);
278
    if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) {
279
      return true;
280
    }
281
  }
282

  
283
  if (target()->is_keyed_stub()) {
188 284
    // Determine whether the failure is due to a name failure.
189 285
    if (!name->IsName()) return false;
190
    Name* stub_name = target->FindFirstName();
191
    if (Name::cast(name) != stub_name) return false;
286
    Name* stub_name = target()->FindFirstName();
287
    if (*name != stub_name) return false;
192 288
  }
193 289

  
194 290
  InlineCacheHolderFlag cache_holder =
195
      Code::ExtractCacheHolderFromFlags(target->flags());
291
      Code::ExtractCacheHolderFromFlags(target()->flags());
196 292

  
197
  Isolate* isolate = target->GetIsolate();
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(isolate)->IsNull()) {
204
    // IC::GetCodeCacheHolder is not applicable.
205
    return false;
293
  switch (cache_holder) {
294
    case OWN_MAP:
295
      // The stub was generated for JSObject but called for non-JSObject.
296
      // IC::GetCodeCacheHolder is not applicable.
297
      if (!receiver->IsJSObject()) return false;
298
      break;
299
    case PROTOTYPE_MAP:
300
      // IC::GetCodeCacheHolder is not applicable.
301
      if (receiver->GetPrototype(isolate())->IsNull()) return false;
302
      break;
206 303
  }
207
  Map* map = IC::GetCodeCacheHolder(isolate, receiver, cache_holder)->map();
304

  
305
  Handle<Map> map(
306
      IC::GetCodeCacheHolder(isolate(), *receiver, cache_holder)->map());
208 307

  
209 308
  // Decide whether the inline cache failed because of changes to the
210 309
  // receiver itself or changes to one of its prototypes.
......
214 313
  // the receiver map's code cache.  Therefore, if the current target
215 314
  // is in the receiver map's code cache, the inline cache failed due
216 315
  // to prototype check failure.
217
  int index = map->IndexInCodeCache(name, target);
316
  int index = map->IndexInCodeCache(*name, *target());
218 317
  if (index >= 0) {
219
    map->RemoveFromCodeCache(String::cast(name), target, index);
220
    // For loads and stores, handlers are stored in addition to the ICs on the
221
    // map. Remove those, too.
222
    if ((target->is_load_stub() || target->is_keyed_load_stub() ||
223
         target->is_store_stub() || target->is_keyed_store_stub()) &&
224
        target->type() != Code::NORMAL) {
225
      Code* handler = target->FindFirstCode();
226
      index = map->IndexInCodeCache(name, handler);
227
      if (index >= 0) {
228
        map->RemoveFromCodeCache(String::cast(name), handler, index);
229
      }
230
    }
318
    map->RemoveFromCodeCache(*name, *target(), index);
319
    // Handlers are stored in addition to the ICs on the map. Remove those, too.
320
    TryRemoveInvalidHandlers(map, name);
231 321
    return true;
232 322
  }
233 323

  
......
240 330
  // If the IC is shared between multiple receivers (slow dictionary mode), then
241 331
  // the map cannot be deprecated and the stub invalidated.
242 332
  if (cache_holder == OWN_MAP) {
243
    Map* old_map = target->FindFirstMap();
244
    if (old_map == map) return true;
333
    Map* old_map = target()->FindFirstMap();
334
    if (old_map == *map) return true;
245 335
    if (old_map != NULL) {
246 336
      if (old_map->is_deprecated()) return true;
247 337
      if (IsMoreGeneralElementsKindTransition(old_map->elements_kind(),
......
252 342
  }
253 343

  
254 344
  if (receiver->IsGlobalObject()) {
255
    if (!name->IsName()) return false;
256
    Isolate* isolate = target->GetIsolate();
257
    LookupResult lookup(isolate);
258
    GlobalObject* global = GlobalObject::cast(receiver);
259
    global->LocalLookupRealNamedProperty(Name::cast(name), &lookup);
345
    LookupResult lookup(isolate());
346
    GlobalObject* global = GlobalObject::cast(*receiver);
347
    global->LocalLookupRealNamedProperty(*name, &lookup);
260 348
    if (!lookup.IsFound()) return false;
261 349
    PropertyCell* cell = global->GetPropertyCell(&lookup);
262 350
    return cell->type()->IsConstant();
......
266 354
}
267 355

  
268 356

  
269
IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) {
270
  IC::State state = target->ic_state();
357
void IC::TryRemoveInvalidHandlers(Handle<Map> map, Handle<String> name) {
358
  CodeHandleList handlers;
359
  target()->FindHandlers(&handlers);
360
  for (int i = 0; i < handlers.length(); i++) {
361
    Handle<Code> handler = handlers.at(i);
362
    int index = map->IndexInCodeCache(*name, *handler);
363
    if (index >= 0) {
364
      map->RemoveFromCodeCache(*name, *handler, index);
365
      return;
366
    }
367
  }
368
}
369

  
271 370

  
272
  if (state != MONOMORPHIC || !name->IsString()) return state;
273
  if (receiver->IsUndefined() || receiver->IsNull()) return state;
371
void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) {
372
  if (!name->IsString()) return;
373
  if (state() != MONOMORPHIC) {
374
    if (state() == POLYMORPHIC && receiver->IsHeapObject()) {
375
      TryRemoveInvalidHandlers(
376
          handle(Handle<HeapObject>::cast(receiver)->map()),
377
          Handle<String>::cast(name));
378
    }
379
    return;
380
  }
381
  if (receiver->IsUndefined() || receiver->IsNull()) return;
274 382

  
275
  Code::Kind kind = target->kind();
276 383
  // Remove the target from the code cache if it became invalid
277 384
  // because of changes in the prototype chain to avoid hitting it
278 385
  // again.
279
  // Call stubs handle this later to allow extra IC state
280
  // transitions.
281
  if (kind != Code::CALL_IC && kind != Code::KEYED_CALL_IC &&
282
      TryRemoveInvalidPrototypeDependentStub(target, receiver, name)) {
283
    return MONOMORPHIC_PROTOTYPE_FAILURE;
386
  if (TryRemoveInvalidPrototypeDependentStub(
387
          receiver, Handle<String>::cast(name))) {
388
    return MarkMonomorphicPrototypeFailure();
284 389
  }
285 390

  
286 391
  // The builtins object is special.  It only changes when JavaScript
......
289 394
  // an inline cache miss for the builtins object after lazily loading
290 395
  // JavaScript builtins, we return uninitialized as the state to
291 396
  // force the inline cache back to monomorphic state.
292
  if (receiver->IsJSBuiltinsObject()) {
293
    return UNINITIALIZED;
294
  }
295

  
296
  return MONOMORPHIC;
397
  if (receiver->IsJSBuiltinsObject()) state_ = UNINITIALIZED;
297 398
}
298 399

  
299 400

  
......
403 504

  
404 505

  
405 506
void CallICBase::Clear(Address address, Code* target) {
406
  if (target->ic_state() == UNINITIALIZED) return;
507
  if (IsCleared(target)) return;
407 508
  bool contextual = CallICBase::Contextual::decode(target->extra_ic_state());
408 509
  Code* code =
409 510
      target->GetIsolate()->stub_cache()->FindCallInitialize(
......
415 516

  
416 517

  
417 518
void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) {
418
  if (target->ic_state() == UNINITIALIZED) return;
519
  if (IsCleared(target)) return;
419 520
  // Make sure to also clear the map used in inline fast cases.  If we
420 521
  // do not clear these maps, cached code can keep objects alive
421 522
  // through the embedded maps.
422
  SetTargetAtAddress(address, *initialize_stub(isolate));
523
  SetTargetAtAddress(address, *pre_monomorphic_stub(isolate));
423 524
}
424 525

  
425 526

  
426 527
void LoadIC::Clear(Isolate* isolate, Address address, Code* target) {
427
  if (target->ic_state() == UNINITIALIZED) return;
428
  SetTargetAtAddress(address, *initialize_stub(isolate));
528
  if (IsCleared(target)) return;
529
  SetTargetAtAddress(address, *pre_monomorphic_stub(isolate));
429 530
}
430 531

  
431 532

  
432 533
void StoreIC::Clear(Isolate* isolate, Address address, Code* target) {
433
  if (target->ic_state() == UNINITIALIZED) return;
534
  if (IsCleared(target)) return;
434 535
  SetTargetAtAddress(address,
435
      (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
436
        ? *initialize_stub_strict(isolate)
437
        : *initialize_stub(isolate));
536
      *pre_monomorphic_stub(
537
          isolate, Code::GetStrictMode(target->extra_ic_state())));
438 538
}
439 539

  
440 540

  
441 541
void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) {
442
  if (target->ic_state() == UNINITIALIZED) return;
542
  if (IsCleared(target)) return;
443 543
  SetTargetAtAddress(address,
444
      (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
445
        ? *initialize_stub_strict(isolate)
446
        : *initialize_stub(isolate));
544
      *pre_monomorphic_stub(
545
          isolate, Code::GetStrictMode(target->extra_ic_state())));
447 546
}
448 547

  
449 548

  
......
460 559
}
461 560

  
462 561

  
463
static bool HasInterceptorGetter(JSObject* object) {
464
  return !object->GetNamedInterceptor()->getter()->IsUndefined();
465
}
466

  
467

  
468
static void LookupForRead(Handle<Object> object,
469
                          Handle<String> name,
470
                          LookupResult* lookup) {
471
  // Skip all the objects with named interceptors, but
472
  // without actual getter.
473
  while (true) {
474
    object->Lookup(*name, lookup);
475
    // Besides normal conditions (property not found or it's not
476
    // an interceptor), bail out if lookup is not cacheable: we won't
477
    // be able to IC it anyway and regular lookup should work fine.
478
    if (!lookup->IsInterceptor() || !lookup->IsCacheable()) {
479
      return;
480
    }
481

  
482
    Handle<JSObject> holder(lookup->holder(), lookup->isolate());
483
    if (HasInterceptorGetter(*holder)) {
484
      return;
485
    }
486

  
487
    holder->LocalLookupRealNamedProperty(*name, lookup);
488
    if (lookup->IsFound()) {
489
      ASSERT(!lookup->IsInterceptor());
490
      return;
491
    }
492

  
493
    Handle<Object> proto(holder->GetPrototype(), lookup->isolate());
494
    if (proto->IsNull()) {
495
      ASSERT(!lookup->IsFound());
496
      return;
497
    }
498

  
499
    object = proto;
500
  }
501
}
502

  
503

  
504 562
Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) {
505 563
  Handle<Object> delegate = Execution::GetFunctionDelegate(isolate(), object);
506 564

  
......
545 603
}
546 604

  
547 605

  
548
MaybeObject* CallICBase::LoadFunction(State state,
549
                                      Code::ExtraICState extra_ic_state,
550
                                      Handle<Object> object,
606
static bool MigrateDeprecated(Handle<Object> object) {
607
  if (!object->IsJSObject()) return false;
608
  Handle<JSObject> receiver = Handle<JSObject>::cast(object);
609
  if (!receiver->map()->is_deprecated()) return false;
610
  JSObject::MigrateInstance(Handle<JSObject>::cast(object));
611
  return true;
612
}
613

  
614

  
615
MaybeObject* CallICBase::LoadFunction(Handle<Object> object,
551 616
                                      Handle<String> name) {
552
  if (object->IsJSObject()) {
553
    Handle<JSObject> receiver = Handle<JSObject>::cast(object);
554
    if (receiver->map()->is_deprecated()) {
555
      JSObject::MigrateInstance(receiver);
556
    }
557
  }
617
  bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
558 618

  
559 619
  // If the object is undefined or null it's illegal to try to get any
560 620
  // of its properties; throw a TypeError in that case.
......
590 650
  }
591 651

  
592 652
  // Lookup is valid: Update inline cache and stub cache.
593
  if (FLAG_use_ic) {
594
    UpdateCaches(&lookup, state, extra_ic_state, object, name);
595
  }
653
  if (use_ic) UpdateCaches(&lookup, object, name);
596 654

  
597 655
  // Get the property.
598 656
  PropertyAttributes attr;
......
637 695
}
638 696

  
639 697

  
640
bool CallICBase::TryUpdateExtraICState(LookupResult* lookup,
641
                                       Handle<Object> object,
642
                                       Code::ExtraICState* extra_ic_state) {
643
  ASSERT(kind_ == Code::CALL_IC);
644
  if (!lookup->IsConstantFunction()) return false;
645
  JSFunction* function = lookup->GetConstantFunction();
646
  if (!function->shared()->HasBuiltinFunctionId()) return false;
647

  
648
  // Fetch the arguments passed to the called function.
649
  const int argc = target()->arguments_count();
650
  Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
651
  Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
652
  Arguments args(argc + 1,
653
                 &Memory::Object_at(fp +
654
                                    StandardFrameConstants::kCallerSPOffset +
655
                                    argc * kPointerSize));
656
  switch (function->shared()->builtin_function_id()) {
657
    case kStringCharCodeAt:
658
    case kStringCharAt:
659
      if (object->IsString()) {
660
        String* string = String::cast(*object);
661
        // Check there's the right string value or wrapper in the receiver slot.
662
        ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
663
        // If we're in the default (fastest) state and the index is
664
        // out of bounds, update the state to record this fact.
665
        if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB &&
666
            argc >= 1 && args[1]->IsNumber()) {
667
          double index = DoubleToInteger(args.number_at(1));
668
          if (index < 0 || index >= string->length()) {
669
            *extra_ic_state =
670
                StringStubState::update(*extra_ic_state,
671
                                        STRING_INDEX_OUT_OF_BOUNDS);
672
            return true;
673
          }
674
        }
675
      }
676
      break;
677
    default:
678
      return false;
679
  }
680
  return false;
681
}
682

  
683

  
684 698
Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup,
685
                                                State state,
686
                                                Code::ExtraICState extra_state,
687 699
                                                Handle<Object> object,
688 700
                                                Handle<String> name) {
689 701
  int argc = target()->arguments_count();
......
692 704
    case FIELD: {
693 705
      PropertyIndex index = lookup->GetFieldIndex();
694 706
      return isolate()->stub_cache()->ComputeCallField(
695
          argc, kind_, extra_state, name, object, holder, index);
707
          argc, kind_, extra_ic_state(), name, object, holder, index);
696 708
    }
697 709
    case CONSTANT: {
698 710
      if (!lookup->IsConstantFunction()) return Handle<Code>::null();
......
701 713
      // that the code stub is in the stub cache.
702 714
      Handle<JSFunction> function(lookup->GetConstantFunction(), isolate());
703 715
      return isolate()->stub_cache()->ComputeCallConstant(
704
          argc, kind_, extra_state, name, object, holder, function);
716
          argc, kind_, extra_ic_state(), name, object, holder, function);
705 717
    }
706 718
    case NORMAL: {
707 719
      // If we return a null handle, the IC will not be patched.
......
715 727
        if (!cell->value()->IsJSFunction()) return Handle<Code>::null();
716 728
        Handle<JSFunction> function(JSFunction::cast(cell->value()));
717 729
        return isolate()->stub_cache()->ComputeCallGlobal(
718
            argc, kind_, extra_state, name, receiver, global, cell, function);
730
            argc, kind_, extra_ic_state(), name,
731
            receiver, global, cell, function);
719 732
      } else {
720 733
        // There is only one shared stub for calling normalized
721 734
        // properties. It does not traverse the prototype chain, so the
......
723 736
        // applicable.
724 737
        if (!holder.is_identical_to(receiver)) return Handle<Code>::null();
725 738
        return isolate()->stub_cache()->ComputeCallNormal(
726
            argc, kind_, extra_state);
739
            argc, kind_, extra_ic_state());
727 740
      }
728 741
      break;
729 742
    }
730 743
    case INTERCEPTOR:
731 744
      ASSERT(HasInterceptorGetter(*holder));
732 745
      return isolate()->stub_cache()->ComputeCallInterceptor(
733
          argc, kind_, extra_state, name, object, holder);
746
          argc, kind_, extra_ic_state(), name, object, holder);
734 747
    default:
735 748
      return Handle<Code>::null();
736 749
  }
737 750
}
738 751

  
739 752

  
753
Handle<Code> CallICBase::megamorphic_stub() {
754
  return isolate()->stub_cache()->ComputeCallMegamorphic(
755
      target()->arguments_count(), kind_, extra_ic_state());
756
}
757

  
758

  
759
Handle<Code> CallICBase::pre_monomorphic_stub() {
760
  return isolate()->stub_cache()->ComputeCallPreMonomorphic(
761
      target()->arguments_count(), kind_, extra_ic_state());
762
}
763

  
764

  
740 765
void CallICBase::UpdateCaches(LookupResult* lookup,
741
                              State state,
742
                              Code::ExtraICState extra_ic_state,
743 766
                              Handle<Object> object,
744 767
                              Handle<String> name) {
745 768
  // Bail out if we didn't find a result.
746 769
  if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
747 770

  
748 771
  // Compute the number of arguments.
749
  int argc = target()->arguments_count();
750 772
  Handle<Code> code;
751
  if (state == UNINITIALIZED) {
752
    // This is the first time we execute this inline cache.
753
    // Set the target to the pre monomorphic stub to delay
754
    // setting the monomorphic state.
755
    code = isolate()->stub_cache()->ComputeCallPreMonomorphic(
756
        argc, kind_, extra_ic_state);
757
  } else if (state == MONOMORPHIC) {
758
    if (kind_ == Code::CALL_IC &&
759
        TryUpdateExtraICState(lookup, object, &extra_ic_state)) {
760
      code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
761
                                    object, name);
762
    } else if (TryRemoveInvalidPrototypeDependentStub(target(),
763
                                                      *object,
764
                                                      *name)) {
765
      state = MONOMORPHIC_PROTOTYPE_FAILURE;
766
      code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
767
                                    object, name);
768
    } else {
769
      code = isolate()->stub_cache()->ComputeCallMegamorphic(
770
          argc, kind_, extra_ic_state);
771
    }
772
  } else {
773
    code = ComputeMonomorphicStub(lookup, state, extra_ic_state,
774
                                  object, name);
775
  }
773
  code = state() == UNINITIALIZED
774
      ? pre_monomorphic_stub()
775
      : ComputeMonomorphicStub(lookup, object, name);
776 776

  
777 777
  // If there's no appropriate stub we simply avoid updating the caches.
778
  // TODO(verwaest): Install a slow fallback in this case to avoid not learning,
779
  // and deopting Crankshaft code.
778 780
  if (code.is_null()) return;
779 781

  
780
  // Patch the call site depending on the state of the cache.
781
  switch (state) {
782
    case UNINITIALIZED:
783
    case MONOMORPHIC_PROTOTYPE_FAILURE:
784
    case PREMONOMORPHIC:
785
    case MONOMORPHIC:
786
      set_target(*code);
787
      break;
788
    case MEGAMORPHIC: {
789
      // Cache code holding map should be consistent with
790
      // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
791
      Handle<JSObject> cache_object = object->IsJSObject()
792
          ? Handle<JSObject>::cast(object)
793
          : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
794
                             isolate());
795
      // Update the stub cache.
796
      UpdateMegamorphicCache(cache_object->map(), *name, *code);
797
      break;
798
    }
799
    case DEBUG_STUB:
800
      break;
801
    case POLYMORPHIC:
802
    case GENERIC:
803
      UNREACHABLE();
804
      break;
805
  }
782
  Handle<JSObject> cache_object = object->IsJSObject()
783
      ? Handle<JSObject>::cast(object)
784
      : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())),
785
                         isolate());
806 786

  
807
  TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
808
           name, state, target());
787
  PatchCache(cache_object, name, code);
788
  TRACE_IC("CallIC", name);
809 789
}
810 790

  
811 791

  
812
MaybeObject* KeyedCallIC::LoadFunction(State state,
813
                                       Handle<Object> object,
792
MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object,
814 793
                                       Handle<Object> key) {
815 794
  if (key->IsInternalizedString()) {
816
    return CallICBase::LoadFunction(state,
817
                                    Code::kNoExtraICState,
818
                                    object,
819
                                    Handle<String>::cast(key));
820
  }
821

  
822
  if (object->IsJSObject()) {
823
    Handle<JSObject> receiver = Handle<JSObject>::cast(object);
824
    if (receiver->map()->is_deprecated()) {
825
      JSObject::MigrateInstance(receiver);
826
    }
795
    return CallICBase::LoadFunction(object, Handle<String>::cast(key));
827 796
  }
828 797

  
829 798
  if (object->IsUndefined() || object->IsNull()) {
830 799
    return TypeError("non_object_property_call", object, key);
831 800
  }
832 801

  
833
  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
834
  ASSERT(!(use_ic && object->IsJSGlobalProxy()));
802
  bool use_ic = MigrateDeprecated(object)
803
      ? false : FLAG_use_ic && !object->IsAccessCheckNeeded();
835 804

  
836
  if (use_ic && state != MEGAMORPHIC) {
805
  if (use_ic && state() != MEGAMORPHIC) {
806
    ASSERT(!object->IsJSGlobalProxy());
837 807
    int argc = target()->arguments_count();
838 808
    Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic(
839 809
        argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
......
846 816
    }
847 817
    ASSERT(!stub.is_null());
848 818
    set_target(*stub);
849
    TRACE_IC("KeyedCallIC", key, state, target());
819
    TRACE_IC("CallIC", key);
850 820
  }
851 821

  
852 822
  Handle<Object> result = GetProperty(isolate(), object, key);
......
865 835
}
866 836

  
867 837

  
868
MaybeObject* LoadIC::Load(State state,
869
                          Handle<Object> object,
838
MaybeObject* LoadIC::Load(Handle<Object> object,
870 839
                          Handle<String> name) {
871 840
  // If the object is undefined or null it's illegal to try to get any
872 841
  // of its properties; throw a TypeError in that case.
......
879 848
    // string wrapper objects.  The length property of string wrapper
880 849
    // objects is read-only and therefore always returns the length of
881 850
    // the underlying string value.  See ECMA-262 15.5.5.1.
882
    if ((object->IsString() || object->IsStringWrapper()) &&
851
    if (object->IsStringWrapper() &&
883 852
        name->Equals(isolate()->heap()->length_string())) {
884 853
      Handle<Code> stub;
885
      if (state == UNINITIALIZED) {
854
      if (state() == UNINITIALIZED) {
886 855
        stub = pre_monomorphic_stub();
887
      } else if (state == PREMONOMORPHIC) {
888
        StringLengthStub string_length_stub(kind(), !object->IsString());
889
        stub = string_length_stub.GetCode(isolate());
890
      } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
891
        StringLengthStub string_length_stub(kind(), true);
856
      } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) {
857
        StringLengthStub string_length_stub(kind());
892 858
        stub = string_length_stub.GetCode(isolate());
893
      } else if (state != MEGAMORPHIC) {
894
        ASSERT(state != GENERIC);
859
      } else if (state() != MEGAMORPHIC) {
860
        ASSERT(state() != GENERIC);
895 861
        stub = megamorphic_stub();
896 862
      }
897 863
      if (!stub.is_null()) {
898 864
        set_target(*stub);
899 865
#ifdef DEBUG
900
        if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
866
        if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n");
901 867
#endif
902 868
      }
903 869
      // Get the string if we have a string wrapper object.
904
      Handle<Object> string = object->IsJSValue()
905
          ? Handle<Object>(Handle<JSValue>::cast(object)->value(), isolate())
906
          : object;
907
      return Smi::FromInt(String::cast(*string)->length());
870
      String* string = String::cast(JSValue::cast(*object)->value());
871
      return Smi::FromInt(string->length());
908 872
    }
909 873

  
910 874
    // Use specialized code for getting prototype of functions.
......
912 876
        name->Equals(isolate()->heap()->prototype_string()) &&
913 877
        Handle<JSFunction>::cast(object)->should_have_prototype()) {
914 878
      Handle<Code> stub;
915
      if (state == UNINITIALIZED) {
879
      if (state() == UNINITIALIZED) {
916 880
        stub = pre_monomorphic_stub();
917
      } else if (state == PREMONOMORPHIC) {
881
      } else if (state() == PREMONOMORPHIC) {
918 882
        FunctionPrototypeStub function_prototype_stub(kind());
919 883
        stub = function_prototype_stub.GetCode(isolate());
920
      } else if (state != MEGAMORPHIC) {
921
        ASSERT(state != GENERIC);
884
      } else if (state() != MEGAMORPHIC) {
885
        ASSERT(state() != GENERIC);
922 886
        stub = megamorphic_stub();
923 887
      }
924 888
      if (!stub.is_null()) {
......
940 904
    return Runtime::GetElementOrCharAtOrFail(isolate(), object, index);
941 905
  }
942 906

  
943
  if (object->IsJSObject()) {
944
    Handle<JSObject> receiver = Handle<JSObject>::cast(object);
945
    if (receiver->map()->is_deprecated()) {
946
      JSObject::MigrateInstance(receiver);
947
    }
948
  }
907
  bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
949 908

  
950 909
  // Named lookup in the object.
951 910
  LookupResult lookup(isolate());
......
960 919
  }
961 920

  
962 921
  // Update inline cache and stub cache.
963
  if (FLAG_use_ic) UpdateCaches(&lookup, state, object, name);
922
  if (use_ic) UpdateCaches(&lookup, object, name);
964 923

  
965 924
  PropertyAttributes attr;
966
  if (lookup.IsInterceptor() || lookup.IsHandler()) {
967
    // Get the property.
968
    Handle<Object> result =
969
        Object::GetProperty(object, object, &lookup, name, &attr);
970
    RETURN_IF_EMPTY_HANDLE(isolate(), result);
971
    // If the property is not present, check if we need to throw an
972
    // exception.
973
    if (attr == ABSENT && IsUndeclaredGlobal(object)) {
974
      return ReferenceError("not_defined", name);
975
    }
976
    return *result;
977
  }
978

  
979 925
  // Get the property.
980
  return Object::GetPropertyOrFail(object, object, &lookup, name, &attr);
926
  Handle<Object> result =
927
      Object::GetProperty(object, object, &lookup, name, &attr);
928
  RETURN_IF_EMPTY_HANDLE(isolate(), result);
929
  // If the property is not present, check if we need to throw an
930
  // exception.
931
  if ((lookup.IsInterceptor() || lookup.IsHandler()) &&
932
      attr == ABSENT && IsUndeclaredGlobal(object)) {
933
    return ReferenceError("not_defined", name);
934
  }
935
  return *result;
981 936
}
982 937

  
983 938

  
......
995 950
}
996 951

  
997 952

  
998
bool IC::UpdatePolymorphicIC(State state,
999
                             Handle<HeapObject> receiver,
953
bool IC::UpdatePolymorphicIC(Handle<HeapObject> receiver,
1000 954
                             Handle<String> name,
1001
                             Handle<Code> code,
1002
                             StrictModeFlag strict_mode) {
1003
  if (code->type() == Code::NORMAL) return false;
1004
  if (target()->ic_state() == MONOMORPHIC &&
1005
      target()->type() == Code::NORMAL) {
1006
    return false;
1007
  }
955
                             Handle<Code> code) {
956
  if (!code->is_handler()) return false;
1008 957

  
1009 958
  MapHandleList receiver_maps;
1010 959
  CodeHandleList handlers;
......
1033 982
    }
1034 983

  
1035 984
    if (number_of_valid_maps >= 4) return false;
985
    if (number_of_maps == 0) return false;
1036 986

  
1037
    // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC.
1038
    // In that case, allow the IC to go back monomorphic.
1039
    if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) {
987
    if (!target()->FindHandlers(&handlers, receiver_maps.length())) {
1040 988
      return false;
1041 989
    }
1042
    target()->FindAllCode(&handlers, receiver_maps.length());
1043 990
  }
1044 991

  
1045 992
  number_of_valid_maps++;
......
1050 997
    handlers.Add(code);
1051 998
  }
1052 999

  
1053
  Handle<Code> ic = ComputePolymorphicIC(
1054
      &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode);
1000
  Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC(
1001
      &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode());
1055 1002
  set_target(*ic);
1056 1003
  return true;
1057 1004
}
1058 1005

  
1059 1006

  
1060
Handle<Code> LoadIC::ComputePolymorphicIC(MapHandleList* receiver_maps,
1061
                                          CodeHandleList* handlers,
1062
                                          int number_of_valid_maps,
1063
                                          Handle<Name> name,
1064
                                          StrictModeFlag strict_mode) {
1065
  return isolate()->stub_cache()->ComputePolymorphicLoadIC(
1066
      receiver_maps, handlers, number_of_valid_maps, name);
1067
}
1068

  
1069

  
1070
Handle<Code> StoreIC::ComputePolymorphicIC(MapHandleList* receiver_maps,
1071
                                           CodeHandleList* handlers,
1072
                                           int number_of_valid_maps,
1073
                                           Handle<Name> name,
1074
                                           StrictModeFlag strict_mode) {
1075
  return isolate()->stub_cache()->ComputePolymorphicStoreIC(
1076
      receiver_maps, handlers, number_of_valid_maps, name, strict_mode);
1077
}
1078

  
1079

  
1080
void LoadIC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1081
                                 Handle<Code> handler,
1082
                                 Handle<String> name,
1083
                                 StrictModeFlag strict_mode) {
1084
  if (handler->is_load_stub()) return set_target(*handler);
1085
  Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicLoadIC(
1086
      receiver, handler, name);
1087
  set_target(*ic);
1088
}
1089

  
1090

  
1091
void KeyedLoadIC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1092
                                      Handle<Code> handler,
1093
                                      Handle<String> name,
1094
                                      StrictModeFlag strict_mode) {
1095
  if (handler->is_keyed_load_stub()) return set_target(*handler);
1096
  Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedLoadIC(
1097
      receiver, handler, name);
1098
  set_target(*ic);
1099
}
1100

  
1101

  
1102
void StoreIC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1103
                                  Handle<Code> handler,
1104
                                  Handle<String> name,
1105
                                  StrictModeFlag strict_mode) {
1106
  if (handler->is_store_stub()) return set_target(*handler);
1107
  Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicStoreIC(
1108
      receiver, handler, name, strict_mode);
1109
  set_target(*ic);
1110
}
1111

  
1112

  
1113
void KeyedStoreIC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1114
                                       Handle<Code> handler,
1115
                                       Handle<String> name,
1116
                                       StrictModeFlag strict_mode) {
1117
  if (handler->is_keyed_store_stub()) return set_target(*handler);
1118
  Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedStoreIC(
1119
      receiver, handler, name, strict_mode);
1007
void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver,
1008
                             Handle<Code> handler,
1009
                             Handle<String> name) {
1010
  if (!handler->is_handler()) return set_target(*handler);
1011
  Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC(
1012
      receiver, handler, name, strict_mode());
1120 1013
  set_target(*ic);
1121 1014
}
1122 1015

  
......
1127 1020
  {
1128 1021
    DisallowHeapAllocation no_gc;
1129 1022
    target()->FindAllMaps(&receiver_maps);
1130
    target()->FindAllCode(&handlers, receiver_maps.length());
1023
    if (!target()->FindHandlers(&handlers, receiver_maps.length())) return;
1131 1024
  }
1132 1025
  for (int i = 0; i < receiver_maps.length(); i++) {
1133 1026
    UpdateMegamorphicCache(*receiver_maps.at(i), *name, *handlers.at(i));
......
1151 1044
}
1152 1045

  
1153 1046

  
1154
// Since GC may have been invoked, by the time PatchCache is called, |state| is
1155
// not necessarily equal to target()->state().
1156
void IC::PatchCache(State state,
1157
                    StrictModeFlag strict_mode,
1158
                    Handle<HeapObject> receiver,
1047
void IC::PatchCache(Handle<HeapObject> receiver,
1159 1048
                    Handle<String> name,
1160 1049
                    Handle<Code> code) {
1161
  switch (state) {
1050
  switch (state()) {
1162 1051
    case UNINITIALIZED:
1163 1052
    case PREMONOMORPHIC:
1164 1053
    case MONOMORPHIC_PROTOTYPE_FAILURE:
1165
      UpdateMonomorphicIC(receiver, code, name, strict_mode);
1054
      UpdateMonomorphicIC(receiver, code, name);
1166 1055
      break;
1167 1056
    case MONOMORPHIC:
1168
      // Only move to megamorphic if the target changes.
1169
      if (target() != *code) {
1170
        if (target()->is_load_stub() || target()->is_store_stub()) {
1171
          bool is_same_handler = false;
1172
          {
1173
            DisallowHeapAllocation no_allocation;
1174
            Code* old_handler = target()->FindFirstCode();
1175
            is_same_handler = old_handler == *code;
1176
          }
1177
          if (is_same_handler
1178
              && IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
1179
            UpdateMonomorphicIC(receiver, code, name, strict_mode);
1180
            break;
1181
          }
1182
          if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) {
1183
            break;
1184
          }
1185

  
1186
          if (target()->type() != Code::NORMAL) {
1187
            CopyICToMegamorphicCache(name);
1188
          }
1057
      // For now, call stubs are allowed to rewrite to the same stub. This
1058
      // happens e.g., when the field does not contain a function.
1059
      ASSERT(target()->is_call_stub() ||
1060
             target()->is_keyed_call_stub() ||
1061
             !target().is_identical_to(code));
1062
      if (!target()->is_keyed_stub()) {
1063
        bool is_same_handler = false;
1064
        {
1065
          DisallowHeapAllocation no_allocation;
1066
          Code* old_handler = target()->FindFirstHandler();
1067
          is_same_handler = old_handler == *code;
1068
        }
1069
        if (is_same_handler
1070
            && IsTransitionedMapOfMonomorphicTarget(receiver->map())) {
1071
          UpdateMonomorphicIC(receiver, code, name);
1072
          break;
1073
        }
1074
        if (UpdatePolymorphicIC(receiver, name, code)) {
1075
          break;
1189 1076
        }
1190 1077

  
1191
        UpdateMegamorphicCache(receiver->map(), *name, *code);
1192
        set_target((strict_mode == kStrictMode)
1193
                     ? *megamorphic_stub_strict()
1194
                     : *megamorphic_stub());
1078
        CopyICToMegamorphicCache(name);
1195 1079
      }
1080

  
1081
      UpdateMegamorphicCache(receiver->map(), *name, *code);
1082
      set_target(*megamorphic_stub());
1196 1083
      break;
1197 1084
    case MEGAMORPHIC:
1198
      // Update the stub cache.
1199 1085
      UpdateMegamorphicCache(receiver->map(), *name, *code);
1200 1086
      break;
1201 1087
    case POLYMORPHIC:
1202
      if (target()->is_load_stub() || target()->is_store_stub()) {
1203
        if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) {
1088
      if (target()->is_keyed_stub()) {
1089
        // When trying to patch a polymorphic keyed stub with anything other
1090
        // than another polymorphic stub, go generic.
1091
        set_target(*generic_stub());
1092
      } else {
1093
        if (UpdatePolymorphicIC(receiver, name, code)) {
1204 1094
          break;
1205 1095
        }
1206 1096
        CopyICToMegamorphicCache(name);
1207 1097
        UpdateMegamorphicCache(receiver->map(), *name, *code);
1208
        set_target((strict_mode == kStrictMode)
1209
                   ? *megamorphic_stub_strict()
1210
                   : *megamorphic_stub());
1211
      } else {
1212
        // When trying to patch a polymorphic keyed load/store element stub
1213
        // with anything other than another polymorphic stub, go generic.
1214
        set_target((strict_mode == kStrictMode)
1215
                   ? *generic_stub_strict()
1216
                   : *generic_stub());
1098
        set_target(*megamorphic_stub());
1217 1099
      }
1218 1100
      break;
1219 1101
    case DEBUG_STUB:
......
1225 1107
}
1226 1108

  
1227 1109

  
1228
static void GetReceiverMapsForStub(Handle<Code> stub,
1229
                                   MapHandleList* result) {
1230
  ASSERT(stub->is_inline_cache_stub());
1231
  switch (stub->ic_state()) {
1232
    case MONOMORPHIC: {
1233
      Map* map = stub->FindFirstMap();
1234
      if (map != NULL) {
1235
        result->Add(Handle<Map>(map));
1236
      }
1237
      break;
1238
    }
1239
    case POLYMORPHIC: {
1240
      DisallowHeapAllocation no_allocation;
1241
      int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1242
      for (RelocIterator it(*stub, mask); !it.done(); it.next()) {
1243
        RelocInfo* info = it.rinfo();
1244
        Handle<Object> object(info->target_object(), stub->GetIsolate());
1245
        if (object->IsString()) break;
1246
        ASSERT(object->IsMap());
1247
        AddOneReceiverMapIfMissing(result, Handle<Map>::cast(object));
1248
      }
1249
      break;
1250
    }
1251
    case MEGAMORPHIC:
1252
      break;
1253
    case UNINITIALIZED:
1254
    case PREMONOMORPHIC:
1255
    case MONOMORPHIC_PROTOTYPE_FAILURE:
1256
    case GENERIC:
1257
    case DEBUG_STUB:
1258
      UNREACHABLE();
1259
      break;
1110
Handle<Code> LoadIC::SimpleFieldLoad(int offset,
1111
                                     bool inobject,
1112
                                     Representation representation) {
1113
  if (kind() == Code::LOAD_IC) {
1114
    LoadFieldStub stub(inobject, offset, representation);
1115
    return stub.GetCode(isolate());
1116
  } else {
1117
    KeyedLoadFieldStub stub(inobject, offset, representation);
1118
    return stub.GetCode(isolate());
1260 1119
  }
1261 1120
}
1262 1121

  
1263

  
1264 1122
void LoadIC::UpdateCaches(LookupResult* lookup,
1265
                          State state,
1266 1123
                          Handle<Object> object,
1267 1124
                          Handle<String> name) {
1125
  // TODO(verwaest): It would be nice to support loading fields from smis as
1126
  // well. For now just fail to update the cache.
1268 1127
  if (!object->IsHeapObject()) return;
1269 1128

  
1270 1129
  Handle<HeapObject> receiver = Handle<HeapObject>::cast(object);
1271 1130

  
1272 1131
  Handle<Code> code;
1273
  if (state == UNINITIALIZED) {
1132
  if (state() == UNINITIALIZED) {
1274 1133
    // This is the first time we execute this inline cache.
1275 1134
    // Set the target to the pre monomorphic stub to delay
1276 1135
    // setting the monomorphic state.
......
1278 1137
  } else if (!lookup->IsCacheable()) {
1279 1138
    // Bail out if the result is not cacheable.
1280 1139
    code = slow_stub();
1140
  } else if (object->IsString() &&
1141
             name->Equals(isolate()->heap()->length_string())) {
1142
    int length_index = String::kLengthOffset / kPointerSize;
1143
    code = SimpleFieldLoad(length_index);
1281 1144
  } else if (!object->IsJSObject()) {
1282 1145
    // TODO(jkummerow): It would be nice to support non-JSObjects in
1283 1146
    // ComputeLoadHandler, then we wouldn't need to go generic here.
1284 1147
    code = slow_stub();
1148
  } else if (!lookup->IsProperty()) {
1149
    code = kind() == Code::LOAD_IC
1150
        ? isolate()->stub_cache()->ComputeLoadNonexistent(
1151
              name, Handle<JSObject>::cast(receiver))
1152
        : slow_stub();
1285 1153
  } else {
1286
    code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name);
1287
    if (code.is_null()) code = slow_stub();
1154
    code = ComputeHandler(lookup, Handle<JSObject>::cast(receiver), name);
1288 1155
  }
1289 1156

  
1290
  PatchCache(state, kNonStrictMode, receiver, name, code);
1291
  TRACE_IC("LoadIC", name, state, target());
1157
  PatchCache(receiver, name, code);
1158
  TRACE_IC("LoadIC", name);
1292 1159
}
1293 1160

  
1294 1161

  
......
1299 1166
}
1300 1167

  
1301 1168

  
1302
Handle<Code> LoadIC::ComputeLoadHandler(LookupResult* lookup,
1303
                                        Handle<JSObject> receiver,
1304
                                        Handle<String> name) {
1305
  if (!lookup->IsProperty()) {
1306
    // Nonexistent property. The result is undefined.
1307
    return isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
1169
Handle<Code> IC::ComputeHandler(LookupResult* lookup,
1170
                                Handle<JSObject> receiver,
1171
                                Handle<String> name,
1172
                                Handle<Object> value) {
1173
  Handle<Code> code = isolate()->stub_cache()->FindHandler(
1174
      name, receiver, kind());
1175
  if (!code.is_null()) return code;
1176

  
1177
  code = CompileHandler(lookup, receiver, name, value);
1178

  
1179
  if (code->is_handler() && code->type() != Code::NORMAL) {
1180
    HeapObject::UpdateMapCodeCache(receiver, name, code);
1308 1181
  }
1309 1182

  
1310
  // Compute monomorphic stub.
1183
  return code;
1184
}
1185

  
1186

  
1187
Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
1188
                                    Handle<JSObject> receiver,
1189
                                    Handle<String> name,
1190
                                    Handle<Object> unused) {
1311 1191
  Handle<JSObject> holder(lookup->holder());
1192
  LoadStubCompiler compiler(isolate(), kind());
1193

  
1312 1194
  switch (lookup->type()) {
1313
    case FIELD:
1314
      return isolate()->stub_cache()->ComputeLoadField(
1315
          name, receiver, holder,
1316
          lookup->GetFieldIndex(), lookup->representation());
1195
    case FIELD: {
1196
      PropertyIndex field = lookup->GetFieldIndex();
1197
      if (receiver.is_identical_to(holder)) {
1198
        return SimpleFieldLoad(field.translate(holder),
1199
                               field.is_inobject(holder),
1200
                               lookup->representation());
1201
      }
1202
      return compiler.CompileLoadField(
1203
          receiver, holder, name, field, lookup->representation());
1204
    }
1317 1205
    case CONSTANT: {
1318 1206
      Handle<Object> constant(lookup->GetConstant(), isolate());
1319 1207
      // TODO(2803): Don't compute a stub for cons strings because they cannot
1320 1208
      // be embedded into code.
1321
      if (constant->IsConsString()) return Handle<Code>::null();
1322
      return isolate()->stub_cache()->ComputeLoadConstant(
1323
          name, receiver, holder, constant);
1209
      if (constant->IsConsString()) break;
1210
      return compiler.CompileLoadConstant(receiver, holder, name, constant);
1324 1211
    }
1325 1212
    case NORMAL:
1213
      if (kind() != Code::LOAD_IC) break;
1326 1214
      if (holder->IsGlobalObject()) {
1327 1215
        Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1328 1216
        Handle<PropertyCell> cell(
1329 1217
            global->GetPropertyCell(lookup), isolate());
1218
        // TODO(verwaest): Turn into a handler.
1330 1219
        return isolate()->stub_cache()->ComputeLoadGlobal(
1331 1220
            name, receiver, global, cell, lookup->IsDontDelete());
1332 1221
      }
......
1335 1224
      // property must be found in the receiver for the stub to be
1336 1225
      // applicable.
1337 1226
      if (!holder.is_identical_to(receiver)) break;
1338
      return isolate()->stub_cache()->ComputeLoadNormal(name, receiver);
1227
      return isolate()->builtins()->LoadIC_Normal();
1339 1228
    case CALLBACKS: {
1229
      // Use simple field loads for some well-known callback properties.
1230
      int object_offset;
1231
      Handle<Map> map(receiver->map());
1232
      if (Accessors::IsJSObjectFieldAccessor(map, name, &object_offset)) {
1233
        PropertyIndex index =
1234
            PropertyIndex::NewHeaderIndex(object_offset / kPointerSize);
1235
        return compiler.CompileLoadField(
1236
            receiver, receiver, name, index, Representation::Tagged());
1237
      }
1238

  
1340 1239
      Handle<Object> callback(lookup->GetCallbackObject(), isolate());
1341 1240
      if (callback->IsExecutableAccessorInfo()) {
1342 1241
        Handle<ExecutableAccessorInfo> info =
1343 1242
            Handle<ExecutableAccessorInfo>::cast(callback);
1344 1243
        if (v8::ToCData<Address>(info->getter()) == 0) break;
1345 1244
        if (!info->IsCompatibleReceiver(*receiver)) break;
1346
        return isolate()->stub_cache()->ComputeLoadCallback(
1347
            name, receiver, holder, info);
1245
        return compiler.CompileLoadCallback(receiver, holder, name, info);
1348 1246
      } else if (callback->IsAccessorPair()) {
1349 1247
        Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(),
1350 1248
                              isolate());
......
1354 1252
        Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1355 1253
        CallOptimization call_optimization(function);
1356 1254
        if (call_optimization.is_simple_api_call() &&
1357
            call_optimization.IsCompatibleReceiver(*receiver) &&
1358
            FLAG_js_accessor_ics) {
1359
          return isolate()->stub_cache()->ComputeLoadCallback(
1360
              name, receiver, holder, call_optimization);
1255
            call_optimization.IsCompatibleReceiver(*receiver)) {
1256
          return compiler.CompileLoadCallback(
1257
              receiver, holder, name, call_optimization);
1361 1258
        }
1362
        return isolate()->stub_cache()->ComputeLoadViaGetter(
1363
            name, receiver, holder, function);
1364
      } else if (receiver->IsJSArray() &&
1365
          name->Equals(isolate()->heap()->length_string())) {
1366
        PropertyIndex lengthIndex =
1367
          PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize);
1368
        return isolate()->stub_cache()->ComputeLoadField(
1369
            name, receiver, holder, lengthIndex, Representation::Tagged());
1259
        return compiler.CompileLoadViaGetter(receiver, holder, name, function);
1370 1260
      }
1371 1261
      // TODO(dcarney): Handle correctly.
1372 1262
      if (callback->IsDeclaredAccessorInfo()) break;
......
1376 1266
    }
1377 1267
    case INTERCEPTOR:
1378 1268
      ASSERT(HasInterceptorGetter(*holder));
1379
      return isolate()->stub_cache()->ComputeLoadInterceptor(
1380
          name, receiver, holder);
1269
      return compiler.CompileLoadInterceptor(receiver, holder, name);
1381 1270
    default:
1382 1271
      break;
1383 1272
  }
1384
  return Handle<Code>::null();
1273

  
1274
  return slow_stub();
1385 1275
}
1386 1276

  
1387 1277

  
......
1406 1296

  
1407 1297

  
1408 1298
Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
1409
  State ic_state = target()->ic_state();
1410

  
1411 1299
  // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1412 1300
  // via megamorphic stubs, since they don't have a map in their relocation info
1413 1301
  // and so the stubs can't be harvested for the object needed for a map check.
......
1418 1306

  
1419 1307
  Handle<Map> receiver_map(receiver->map(), isolate());
1420 1308
  MapHandleList target_receiver_maps;
1421
  if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1309
  if (state() == UNINITIALIZED || state() == PREMONOMORPHIC) {
1422 1310
    // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1423 1311
    // yet will do so and stay there.
1424 1312
    return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1425 1313
  }
1426 1314

  
1427
  if (target() == *string_stub()) {
1315
  if (target().is_identical_to(string_stub())) {
1428 1316
    target_receiver_maps.Add(isolate()->factory()->string_map());
1429 1317
  } else {
1430
    GetReceiverMapsForStub(Handle<Code>(target(), isolate()),
1431
                           &target_receiver_maps);
1318
    target()->FindAllMaps(&target_receiver_maps);
1432 1319
    if (target_receiver_maps.length() == 0) {
1433 1320
      return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1434 1321
    }
......
1441 1328
  // monomorphic. If this optimistic assumption is not true, the IC will
1442 1329
  // miss again and it will become polymorphic and support both the
1443 1330
  // untransitioned and transitioned maps.
1444
  if (ic_state == MONOMORPHIC &&
1331
  if (state() == MONOMORPHIC &&
1445 1332
      IsMoreGeneralElementsKindTransition(
1446 1333
          target_receiver_maps.at(0)->elements_kind(),
1447 1334
          receiver->GetElementsKind())) {
1448 1335
    return isolate()->stub_cache()->ComputeKeyedLoadElement(receiver_map);
1449 1336
  }
1450 1337

  
1451
  ASSERT(ic_state != GENERIC);
1338
  ASSERT(state() != GENERIC);
1452 1339

  
1453 1340
  // Determine the list of receiver maps that this call site has seen,
1454 1341
  // adding the map that was just encountered.
......
1471 1358
}
1472 1359

  
1473 1360

  
1474
MaybeObject* KeyedLoadIC::Load(State state,
1475
                               Handle<Object> object,
1361
MaybeObject* KeyedLoadIC::Load(Handle<Object> object,
1476 1362
                               Handle<Object> key,
1477 1363
                               ICMissMode miss_mode) {
1364
  if (MigrateDeprecated(object)) {
1365
    return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1366
  }
1367

  
1368
  MaybeObject* maybe_object = NULL;
1369
  Handle<Code> stub = generic_stub();
1370

  
1478 1371
  // Check for values that can be converted into an internalized string directly
1479 1372
  // or is representable as a smi.
1480 1373
  key = TryConvertKey(key, isolate());
1481 1374

  
1482 1375
  if (key->IsInternalizedString()) {
1483
    return LoadIC::Load(state, object, Handle<String>::cast(key));
1484
  }
1485

  
1486
  bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1487
  ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1488

  
1489
  if (use_ic) {
1490
    Handle<Code> stub = generic_stub();
1376
    maybe_object = LoadIC::Load(object, Handle<String>::cast(key));
1377
    if (maybe_object->IsFailure()) return maybe_object;
1378
  } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
1379
    ASSERT(!object->IsJSGlobalProxy());
1491 1380
    if (miss_mode != MISS_FORCE_GENERIC) {
1492 1381
      if (object->IsString() && key->IsNumber()) {
1493
        if (state == UNINITIALIZED) {
1494
          stub = string_stub();
1495
        }
1382
        if (state() == UNINITIALIZED) stub = string_stub();
1496 1383
      } else if (object->IsJSObject()) {
1497 1384
        Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1498
        if (receiver->map()->is_deprecated()) {
1499
          JSObject::MigrateInstance(receiver);
1500
        }
1501

  
1502 1385
        if (receiver->elements()->map() ==
1503 1386
            isolate()->heap()->non_strict_arguments_elements_map()) {
1504 1387
          stub = non_strict_arguments_stub();
1505 1388
        } else if (receiver->HasIndexedInterceptor()) {
1506 1389
          stub = indexed_interceptor_stub();
1507 1390
        } else if (!key->ToSmi()->IsFailure() &&
1508
                   (target() != *non_strict_arguments_stub())) {
1391
                   (!target().is_identical_to(non_strict_arguments_stub()))) {
1509 1392
          stub = LoadElementStub(receiver);
1510 1393
        }
1511 1394
      }
1512
    } else {
1513
      TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic");
1395
    }
1396
  }
1397

  
1398
  if (!is_target_set()) {
1399
    if (*stub == *generic_stub()) {
1400
      TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic");
1514 1401
    }
1515 1402
    ASSERT(!stub.is_null());
1516 1403
    set_target(*stub);
1517
    TRACE_IC("KeyedLoadIC", key, state, target());
1404
    TRACE_IC("LoadIC", key);
1518 1405
  }
1519 1406

  
1520

  
1407
  if (maybe_object != NULL) return maybe_object;
1521 1408
  return Runtime::GetObjectPropertyOrFail(isolate(), object, key);
1522 1409
}
1523 1410

  
1524 1411

  
1525
Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup,
1526
                                             Handle<JSObject> receiver,
1527
                                             Handle<String> name) {
1528
  // Bail out if we didn't find a result.
1529
  if (!lookup->IsProperty()) return Handle<Code>::null();
1530

  
1531
  // Compute a monomorphic stub.
1532
  Handle<JSObject> holder(lookup->holder(), isolate());
1533
  switch (lookup->type()) {
1534
    case FIELD:
1535
      return isolate()->stub_cache()->ComputeKeyedLoadField(
1536
          name, receiver, holder,
1537
          lookup->GetFieldIndex(), lookup->representation());
1538
    case CONSTANT: {
1539
      Handle<Object> constant(lookup->GetConstant(), isolate());
1540
      // TODO(2803): Don't compute a stub for cons strings because they cannot
1541
      // be embedded into code.
1542
      if (constant->IsConsString()) return Handle<Code>::null();
1543
      return isolate()->stub_cache()->ComputeKeyedLoadConstant(
1544
          name, receiver, holder, constant);
1545
    }
1546
    case CALLBACKS: {
1547
      Handle<Object> callback_object(lookup->GetCallbackObject(), isolate());
1548
      // TODO(dcarney): Handle DeclaredAccessorInfo correctly.
1549
      if (callback_object->IsExecutableAccessorInfo()) {
1550
        Handle<ExecutableAccessorInfo> callback =
1551
            Handle<ExecutableAccessorInfo>::cast(callback_object);
1552
        if (v8::ToCData<Address>(callback->getter()) == 0) break;
1553
        if (!callback->IsCompatibleReceiver(*receiver)) break;
1554
        return isolate()->stub_cache()->ComputeKeyedLoadCallback(
1555
            name, receiver, holder, callback);
1556
      } else if (callback_object->IsAccessorPair()) {
1557
        Handle<Object> getter(
1558
            Handle<AccessorPair>::cast(callback_object)->getter(),
1559
            isolate());
1560
        if (!getter->IsJSFunction()) break;
1561
        if (holder->IsGlobalObject()) break;
1562
        if (!holder->HasFastProperties()) break;
1563
        Handle<JSFunction> function = Handle<JSFunction>::cast(getter);
1564
        CallOptimization call_optimization(function);
1565
        if (call_optimization.is_simple_api_call() &&
1566
            call_optimization.IsCompatibleReceiver(*receiver) &&
1567
            FLAG_js_accessor_ics) {
1568
          return isolate()->stub_cache()->ComputeKeyedLoadCallback(
1569
              name, receiver, holder, call_optimization);
1570
        }
1571
      }
1572
      break;
1573
    }
1574
    case INTERCEPTOR:
1575
      ASSERT(HasInterceptorGetter(lookup->holder()));
1576
      return isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
1577
          name, receiver, holder);
1578
    default:
1579
      // Always rewrite to the generic case so that we do not
1580
      // repeatedly try to rewrite.
1581
      return generic_stub();
1582
  }
1583
  return Handle<Code>::null();
1584
}
1585

  
1586

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff