| Index: src/ic.cc
|
| diff --git a/src/ic.cc b/src/ic.cc
|
| index 2139d5c5fc2d51e8a48f0faa9ade5c1d6b50c691..a008ee6d02506cb7a8ce143c9ef7e949f13ad093 100644
|
| --- a/src/ic.cc
|
| +++ b/src/ic.cc
|
| @@ -105,6 +105,11 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
|
| modifier = GetTransitionMarkModifier(
|
| KeyedStoreIC::GetKeyedAccessStoreMode(extra_state));
|
| }
|
| + if (new_target->kind() == Code::LOAD_IC || new_target->kind() == Code::KEYED_LOAD_IC) {
|
| + LoadIC::PropertyLookupMode lookup_mode = LoadIC::PropertyLookupMode(extra_state);
|
| + PrintF("<%s>", lookup_mode == LoadIC::NORMAL_LOOKUP ? "normal" : "own");
|
| + }
|
| +
|
| PrintF(" (%c->%c%s)", TransitionMarkFromState(old_state),
|
| TransitionMarkFromState(new_state), modifier);
|
| #ifdef OBJECT_PRINT
|
| @@ -114,6 +119,10 @@ void IC::TraceIC(const char* type, Handle<Object> name, State old_state,
|
| name->ShortPrint(stdout);
|
| #endif
|
| PrintF("]\n");
|
| + if (name->IsString() && strcmp(String::cast(*name)->ToCString().get(), "xBase") == 0 &&
|
| + new_state == MEGAMORPHIC) {
|
| + PrintF("Here!\n");
|
| + }
|
| }
|
| }
|
|
|
| @@ -510,7 +519,9 @@ void KeyedLoadIC::Clear(Isolate* isolate,
|
| // Make sure to also clear the map used in inline fast cases. If we
|
| // do not clear these maps, cached code can keep objects alive
|
| // through the embedded maps.
|
| - SetTargetAtAddress(address, *pre_monomorphic_stub(isolate), constant_pool);
|
| + Code* code = PropertyICCompiler::FindPreMonomorphic(isolate, Code::KEYED_LOAD_IC,
|
| + target->extra_ic_state());
|
| + SetTargetAtAddress(address, code, constant_pool);
|
| }
|
|
|
|
|
| @@ -572,11 +583,12 @@ void CompareIC::Clear(Isolate* isolate,
|
|
|
|
|
| // static
|
| -Handle<Code> KeyedLoadIC::generic_stub(Isolate* isolate) {
|
| +Handle<Code> KeyedLoadIC::generic_stub(Isolate* isolate, ExtraICState extra_ic_state) {
|
| + // TODO: plumbing
|
| if (FLAG_compiled_keyed_generic_loads) {
|
| - return KeyedLoadGenericStub(isolate).GetCode();
|
| + return KeyedLoadGenericStub(isolate, GetPropertyLookupMode(extra_ic_state)).GetCode();
|
| } else {
|
| - return isolate->builtins()->KeyedLoadIC_Generic();
|
| + return PropertyICCompiler::ComputeKeyedLoad(isolate, GENERIC, extra_ic_state);
|
| }
|
| }
|
|
|
| @@ -590,7 +602,7 @@ static bool MigrateDeprecated(Handle<Object> object) {
|
| }
|
|
|
|
|
| -MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<String> name) {
|
| +MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<Name> name) {
|
| // If the object is undefined or null it's illegal to try to get any
|
| // of its properties; throw a TypeError in that case.
|
| if (object->IsUndefined() || object->IsNull()) {
|
| @@ -600,10 +612,11 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<String> name) {
|
| // Check if the name is trivially convertible to an index and get
|
| // the element or char if so.
|
| uint32_t index;
|
| - if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
|
| + if (kind() == Code::KEYED_LOAD_IC &&
|
| + name->IsString() && String::cast(*name)->AsArrayIndex(&index)) {
|
| // Rewrite to the generic keyed load stub.
|
| if (FLAG_use_ic) {
|
| - set_target(*KeyedLoadIC::generic_stub(isolate()));
|
| + set_target(*KeyedLoadIC::generic_stub(isolate(), extra_ic_state()));
|
| TRACE_IC("LoadIC", name);
|
| TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index");
|
| }
|
| @@ -619,13 +632,21 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<String> name) {
|
| bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic;
|
|
|
| // Named lookup in the object.
|
| - LookupIterator it(object, name);
|
| - LookupForRead(&it);
|
| + LookupIterator::Configuration lookup_configuration =
|
| + property_lookup_mode() == OWN_PROPERTY_LOOKUP ?
|
| + LookupIterator::CHECK_OWN_REAL :
|
| + LookupIterator::CHECK_ALL;
|
| +
|
| + LookupIterator it(object, name, lookup_configuration);
|
| + LookupForRead(&it);
|
|
|
| // If we did not find a property, check if we need to throw an exception.
|
| if (!it.IsFound()) {
|
| if (IsUndeclaredGlobal(object)) {
|
| - return ReferenceError("not_defined", name);
|
| + return ReferenceError("not_defined",
|
| + name->IsString()
|
| + ? Handle<String>::cast(name)
|
| + : Handle<String>());
|
| }
|
| LOG(isolate(), SuspectReadEvent(*name, *object));
|
| }
|
| @@ -639,7 +660,10 @@ MaybeHandle<Object> LoadIC::Load(Handle<Object> object, Handle<String> name) {
|
| isolate(), result, Object::GetProperty(&it), Object);
|
| // If the property is not present, check if we need to throw an exception.
|
| if (!it.IsFound() && IsUndeclaredGlobal(object)) {
|
| - return ReferenceError("not_defined", name);
|
| + return ReferenceError("not_defined",
|
| + name->IsString()
|
| + ? Handle<String>::cast(name)
|
| + : Handle<String>());
|
| }
|
|
|
| return result;
|
| @@ -660,7 +684,7 @@ static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps,
|
| }
|
|
|
|
|
| -bool IC::UpdatePolymorphicIC(Handle<String> name, Handle<Code> code) {
|
| +bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Code> code) {
|
| if (!code->is_handler()) return false;
|
| if (target()->is_keyed_stub() && state() != PROTOTYPE_FAILURE) return false;
|
| Handle<HeapType> type = receiver_type();
|
| @@ -766,7 +790,7 @@ template
|
| Handle<HeapType> IC::MapToType<HeapType>(Handle<Map> map, Isolate* region);
|
|
|
|
|
| -void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<String> name) {
|
| +void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) {
|
| DCHECK(handler->is_handler());
|
| Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic(
|
| kind(), name, receiver_type(), handler, extra_ic_state());
|
| @@ -774,7 +798,7 @@ void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<String> name) {
|
| }
|
|
|
|
|
| -void IC::CopyICToMegamorphicCache(Handle<String> name) {
|
| +void IC::CopyICToMegamorphicCache(Handle<Name> name) {
|
| TypeHandleList types;
|
| CodeHandleList handlers;
|
| TargetTypes(&types);
|
| @@ -800,7 +824,7 @@ bool IC::IsTransitionOfMonomorphicTarget(Map* source_map, Map* target_map) {
|
| }
|
|
|
|
|
| -void IC::PatchCache(Handle<String> name, Handle<Code> code) {
|
| +void IC::PatchCache(Handle<Name> name, Handle<Code> code) {
|
| switch (state()) {
|
| case UNINITIALIZED:
|
| case PREMONOMORPHIC:
|
| @@ -834,13 +858,19 @@ Handle<Code> LoadIC::initialize_stub(Isolate* isolate,
|
| }
|
|
|
|
|
| +Handle<Code> KeyedLoadIC::initialize_stub(Isolate* isolate,
|
| + ExtraICState extra_state) {
|
| + return PropertyICCompiler::ComputeKeyedLoad(isolate, UNINITIALIZED, extra_state);
|
| +}
|
| +
|
| +
|
| Handle<Code> LoadIC::megamorphic_stub() {
|
| if (kind() == Code::LOAD_IC) {
|
| return PropertyICCompiler::ComputeLoad(isolate(), MEGAMORPHIC,
|
| extra_ic_state());
|
| } else {
|
| DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
|
| - return KeyedLoadIC::generic_stub(isolate());
|
| + return KeyedLoadIC::generic_stub(isolate(), extra_ic_state());
|
| }
|
| }
|
|
|
| @@ -851,8 +881,9 @@ Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate,
|
| }
|
|
|
|
|
| -Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate) {
|
| - return isolate->builtins()->KeyedLoadIC_PreMonomorphic();
|
| +Handle<Code> KeyedLoadIC::pre_monomorphic_stub(Isolate* isolate,
|
| + ExtraICState extra_state) {
|
| + return PropertyICCompiler::ComputeKeyedLoad(isolate, PREMONOMORPHIC, extra_state);
|
| }
|
|
|
|
|
| @@ -861,7 +892,7 @@ Handle<Code> LoadIC::pre_monomorphic_stub() const {
|
| return LoadIC::pre_monomorphic_stub(isolate(), extra_ic_state());
|
| } else {
|
| DCHECK_EQ(Code::KEYED_LOAD_IC, kind());
|
| - return KeyedLoadIC::pre_monomorphic_stub(isolate());
|
| + return KeyedLoadIC::pre_monomorphic_stub(isolate(), extra_ic_state());
|
| }
|
| }
|
|
|
| @@ -873,7 +904,7 @@ Handle<Code> LoadIC::SimpleFieldLoad(FieldIndex index) {
|
|
|
|
|
| void LoadIC::UpdateCaches(LookupIterator* lookup, Handle<Object> object,
|
| - Handle<String> name) {
|
| + Handle<Name> name) {
|
| if (state() == UNINITIALIZED) {
|
| // This is the first time we execute this inline cache.
|
| // Set the target to the pre monomorphic stub to delay
|
| @@ -888,7 +919,7 @@ void LoadIC::UpdateCaches(LookupIterator* lookup, Handle<Object> object,
|
| lookup->state() == LookupIterator::ACCESS_CHECK) {
|
| code = slow_stub();
|
| } else if (!lookup->IsFound()) {
|
| - if (kind() == Code::LOAD_IC) {
|
| + if (kind() == Code::LOAD_IC && property_lookup_mode() == NORMAL_LOOKUP) {
|
| code = NamedLoadHandlerCompiler::ComputeLoadNonexistent(name,
|
| receiver_type());
|
| // TODO(jkummerow/verwaest): Introduce a builtin that handles this case.
|
| @@ -913,7 +944,7 @@ void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) {
|
|
|
|
|
| Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> object,
|
| - Handle<String> name, Handle<Object> value) {
|
| + Handle<Name> name, Handle<Object> value) {
|
| bool receiver_is_holder =
|
| object.is_identical_to(lookup->GetHolder<JSObject>());
|
| CacheHolderFlag flag;
|
| @@ -1001,24 +1032,24 @@ Handle<Code> IC::ComputeStoreHandler(LookupResult* lookup,
|
|
|
|
|
| Handle<Code> LoadIC::CompileHandler(LookupIterator* lookup,
|
| - Handle<Object> object, Handle<String> name,
|
| + Handle<Object> object, Handle<Name> name,
|
| Handle<Object> unused,
|
| CacheHolderFlag cache_holder) {
|
| if (object->IsString() &&
|
| - String::Equals(isolate()->factory()->length_string(), name)) {
|
| + Name::Equals(isolate()->factory()->length_string(), name)) {
|
| FieldIndex index = FieldIndex::ForInObjectOffset(String::kLengthOffset);
|
| return SimpleFieldLoad(index);
|
| }
|
|
|
| if (object->IsStringWrapper() &&
|
| - String::Equals(isolate()->factory()->length_string(), name)) {
|
| + Name::Equals(isolate()->factory()->length_string(), name)) {
|
| StringLengthStub string_length_stub(isolate());
|
| return string_length_stub.GetCode();
|
| }
|
|
|
| // Use specialized code for getting prototype of functions.
|
| if (object->IsJSFunction() &&
|
| - String::Equals(isolate()->factory()->prototype_string(), name) &&
|
| + Name::Equals(isolate()->factory()->prototype_string(), name) &&
|
| Handle<JSFunction>::cast(object)->should_have_prototype() &&
|
| !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) {
|
| Handle<Code> stub;
|
| @@ -1237,11 +1268,11 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object,
|
| // internalized string directly or is representable as a smi.
|
| key = TryConvertKey(key, isolate());
|
|
|
| - if (key->IsInternalizedString()) {
|
| + if (key->IsInternalizedString() || key->IsSymbol()) {
|
| ASSIGN_RETURN_ON_EXCEPTION(
|
| isolate(),
|
| load_handle,
|
| - LoadIC::Load(object, Handle<String>::cast(key)),
|
| + LoadIC::Load(object, Handle<Name>::cast(key)),
|
| Object);
|
| } else if (FLAG_use_ic && !object->IsAccessCheckNeeded()) {
|
| if (object->IsString() && key->IsNumber()) {
|
| @@ -2105,7 +2136,7 @@ RUNTIME_FUNCTION(LoadIC_Miss) {
|
| DCHECK(args.length() == 2);
|
| LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
|
| Handle<Object> receiver = args.at<Object>(0);
|
| - Handle<String> key = args.at<String>(1);
|
| + Handle<Name> key = args.at<Name>(1);
|
| ic.UpdateState(receiver, key);
|
| Handle<Object> result;
|
| ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key));
|
|
|