| Index: src/ic.cc
|
| diff --git a/src/ic.cc b/src/ic.cc
|
| index b85265fea7d73180c42645e8cd631d5d12809951..9742e5ef8486ad4943872993a60c729b8cbf97ef 100644
|
| --- a/src/ic.cc
|
| +++ b/src/ic.cc
|
| @@ -368,45 +368,6 @@ static bool HasInterceptorGetter(JSObject* object) {
|
| }
|
|
|
|
|
| -static void LookupForRead(Object* object,
|
| - String* name,
|
| - LookupResult* lookup) {
|
| - AssertNoAllocation no_gc;
|
| - // Skip all the objects with named interceptors, but
|
| - // without actual getter.
|
| - while (true) {
|
| - object->Lookup(name, lookup);
|
| - // Besides normal conditions (property not found or it's not
|
| - // an interceptor), bail out if lookup is not cacheable: we won't
|
| - // be able to IC it anyway and regular lookup should work fine.
|
| - if (!lookup->IsFound()
|
| - || (lookup->type() != INTERCEPTOR)
|
| - || !lookup->IsCacheable()) {
|
| - return;
|
| - }
|
| -
|
| - JSObject* holder = lookup->holder();
|
| - if (HasInterceptorGetter(holder)) {
|
| - return;
|
| - }
|
| -
|
| - holder->LocalLookupRealNamedProperty(name, lookup);
|
| - if (lookup->IsProperty()) {
|
| - ASSERT(lookup->type() != INTERCEPTOR);
|
| - return;
|
| - }
|
| -
|
| - Object* proto = holder->GetPrototype();
|
| - if (proto->IsNull()) {
|
| - lookup->NotFound();
|
| - return;
|
| - }
|
| -
|
| - object = proto;
|
| - }
|
| -}
|
| -
|
| -
|
| static void LookupForRead(Handle<Object> object,
|
| Handle<String> name,
|
| LookupResult* lookup) {
|
| @@ -1107,9 +1068,8 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
| bool force_generic_stub) {
|
| // Check for values that can be converted into a symbol.
|
| // TODO(1295): Remove this code.
|
| - HandleScope scope(isolate());
|
| if (key->IsHeapNumber() &&
|
| - isnan(HeapNumber::cast(*key)->value())) {
|
| + isnan(Handle<HeapNumber>::cast(key)->value())) {
|
| key = isolate()->factory()->nan_symbol();
|
| } else if (key->IsUndefined()) {
|
| key = isolate()->factory()->undefined_symbol();
|
| @@ -1131,13 +1091,11 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
| if (object->IsString() &&
|
| name->Equals(isolate()->heap()->length_symbol())) {
|
| Handle<String> string = Handle<String>::cast(object);
|
| - Object* code = NULL;
|
| - { MaybeObject* maybe_code =
|
| - isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name,
|
| - *string);
|
| - if (!maybe_code->ToObject(&code)) return maybe_code;
|
| - }
|
| - set_target(Code::cast(code));
|
| + Handle<Code> code =
|
| + isolate()->stub_cache()->ComputeKeyedLoadStringLength(name,
|
| + string);
|
| + ASSERT(!code.is_null());
|
| + set_target(*code);
|
| #ifdef DEBUG
|
| TraceIC("KeyedLoadIC", name, state, target());
|
| #endif // DEBUG
|
| @@ -1148,31 +1106,26 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
| if (object->IsJSArray() &&
|
| name->Equals(isolate()->heap()->length_symbol())) {
|
| Handle<JSArray> array = Handle<JSArray>::cast(object);
|
| - Object* code;
|
| - { MaybeObject* maybe_code =
|
| - isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name,
|
| - *array);
|
| - if (!maybe_code->ToObject(&code)) return maybe_code;
|
| - }
|
| - set_target(Code::cast(code));
|
| + Handle<Code> code =
|
| + isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array);
|
| + ASSERT(!code.is_null());
|
| + set_target(*code);
|
| #ifdef DEBUG
|
| TraceIC("KeyedLoadIC", name, state, target());
|
| #endif // DEBUG
|
| - return JSArray::cast(*object)->length();
|
| + return array->length();
|
| }
|
|
|
| // Use specialized code for getting prototype of functions.
|
| if (object->IsJSFunction() &&
|
| name->Equals(isolate()->heap()->prototype_symbol()) &&
|
| - JSFunction::cast(*object)->should_have_prototype()) {
|
| + Handle<JSFunction>::cast(object)->should_have_prototype()) {
|
| Handle<JSFunction> function = Handle<JSFunction>::cast(object);
|
| - Object* code;
|
| - { MaybeObject* maybe_code =
|
| - isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
|
| - *name, *function);
|
| - if (!maybe_code->ToObject(&code)) return maybe_code;
|
| - }
|
| - set_target(Code::cast(code));
|
| + Handle<Code> code =
|
| + isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
|
| + name, function);
|
| + ASSERT(!code.is_null());
|
| + set_target(*code);
|
| #ifdef DEBUG
|
| TraceIC("KeyedLoadIC", name, state, target());
|
| #endif // DEBUG
|
| @@ -1184,15 +1137,14 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
| // the element or char if so.
|
| uint32_t index = 0;
|
| if (name->AsArrayIndex(&index)) {
|
| - HandleScope scope(isolate());
|
| // Rewrite to the generic keyed load stub.
|
| - if (FLAG_use_ic) set_target(generic_stub());
|
| + if (FLAG_use_ic) set_target(*generic_stub());
|
| return Runtime::GetElementOrCharAt(isolate(), object, index);
|
| }
|
|
|
| // Named lookup.
|
| LookupResult lookup(isolate());
|
| - LookupForRead(*object, *name, &lookup);
|
| + LookupForRead(object, name, &lookup);
|
|
|
| // If we did not find a property, check if we need to throw an exception.
|
| if (!lookup.IsProperty() && IsContextual(object)) {
|
| @@ -1206,17 +1158,15 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
| PropertyAttributes attr;
|
| if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
|
| // Get the property.
|
| - Object* result;
|
| - { MaybeObject* maybe_result =
|
| - object->GetProperty(*object, &lookup, *name, &attr);
|
| - if (!maybe_result->ToObject(&result)) return maybe_result;
|
| - }
|
| + Handle<Object> result =
|
| + Object::GetProperty(object, object, &lookup, name, &attr);
|
| + RETURN_IF_EMPTY_HANDLE(isolate(), result);
|
| // If the property is not present, check if we need to throw an
|
| // exception.
|
| if (attr == ABSENT && IsContextual(object)) {
|
| return ReferenceError("not_defined", name);
|
| }
|
| - return result;
|
| + return *result;
|
| }
|
|
|
| return object->GetProperty(*object, &lookup, *name, &attr);
|
| @@ -1227,31 +1177,25 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
| bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
|
|
|
| if (use_ic) {
|
| - Code* stub = generic_stub();
|
| + Handle<Code> stub = generic_stub();
|
| if (!force_generic_stub) {
|
| if (object->IsString() && key->IsNumber()) {
|
| if (state == UNINITIALIZED) {
|
| stub = string_stub();
|
| }
|
| } else if (object->IsJSObject()) {
|
| - JSObject* receiver = JSObject::cast(*object);
|
| - Heap* heap = Handle<JSObject>::cast(object)->GetHeap();
|
| - Map* elements_map = Handle<JSObject>::cast(object)->elements()->map();
|
| - if (elements_map == heap->non_strict_arguments_elements_map()) {
|
| + Handle<JSObject> receiver = Handle<JSObject>::cast(object);
|
| + if (receiver->elements()->map() ==
|
| + isolate()->heap()->non_strict_arguments_elements_map()) {
|
| stub = non_strict_arguments_stub();
|
| } else if (receiver->HasIndexedInterceptor()) {
|
| stub = indexed_interceptor_stub();
|
| - } else if (key->IsSmi() && (target() != non_strict_arguments_stub())) {
|
| - MaybeObject* maybe_stub = ComputeStub(receiver,
|
| - LOAD,
|
| - kNonStrictMode,
|
| - stub);
|
| - stub = maybe_stub->IsFailure() ?
|
| - NULL : Code::cast(maybe_stub->ToObjectUnchecked());
|
| + } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
|
| + stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub);
|
| }
|
| }
|
| }
|
| - if (stub != NULL) set_target(stub);
|
| + if (!stub.is_null()) set_target(*stub);
|
| }
|
|
|
| #ifdef DEBUG
|
| @@ -1263,8 +1207,10 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
| }
|
|
|
|
|
| -void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
|
| - Handle<Object> object, Handle<String> name) {
|
| +void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
|
| + State state,
|
| + Handle<Object> object,
|
| + Handle<String> name) {
|
| // Bail out if we didn't find a result.
|
| if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
|
|
|
| @@ -1274,63 +1220,57 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
|
| if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
|
|
|
| // Compute the code stub for this load.
|
| - MaybeObject* maybe_code = NULL;
|
| - Object* code;
|
| + Handle<Code> code;
|
|
|
| if (state == UNINITIALIZED) {
|
| // This is the first time we execute this inline cache.
|
| // Set the target to the pre monomorphic stub to delay
|
| // setting the monomorphic state.
|
| - maybe_code = pre_monomorphic_stub();
|
| + code = pre_monomorphic_stub();
|
| } else {
|
| // Compute a monomorphic stub.
|
| + Handle<JSObject> holder(lookup->holder());
|
| switch (lookup->type()) {
|
| - case FIELD: {
|
| - maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField(
|
| - *name, *receiver, lookup->holder(), lookup->GetFieldIndex());
|
| + case FIELD:
|
| + code = isolate()->stub_cache()->ComputeKeyedLoadField(
|
| + name, receiver, holder, lookup->GetFieldIndex());
|
| break;
|
| - }
|
| case CONSTANT_FUNCTION: {
|
| - Object* constant = lookup->GetConstantFunction();
|
| - maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
|
| - *name, *receiver, lookup->holder(), constant);
|
| + Handle<Object> constant(lookup->GetConstantFunction());
|
| + code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
|
| + name, receiver, holder, constant);
|
| break;
|
| }
|
| case CALLBACKS: {
|
| - if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
|
| - AccessorInfo* callback =
|
| - AccessorInfo::cast(lookup->GetCallbackObject());
|
| + Handle<Object> callback_object(lookup->GetCallbackObject());
|
| + if (!callback_object->IsAccessorInfo()) return;
|
| + Handle<AccessorInfo> callback =
|
| + Handle<AccessorInfo>::cast(callback_object);
|
| if (v8::ToCData<Address>(callback->getter()) == 0) return;
|
| - maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
|
| - *name, *receiver, lookup->holder(), callback);
|
| + code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
|
| + name, receiver, holder, callback);
|
| break;
|
| }
|
| - case INTERCEPTOR: {
|
| + case INTERCEPTOR:
|
| ASSERT(HasInterceptorGetter(lookup->holder()));
|
| - maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
|
| - *name, *receiver, lookup->holder());
|
| + code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
|
| + name, receiver, holder);
|
| break;
|
| - }
|
| - default: {
|
| + default:
|
| // Always rewrite to the generic case so that we do not
|
| // repeatedly try to rewrite.
|
| - maybe_code = generic_stub();
|
| + code = generic_stub();
|
| break;
|
| - }
|
| }
|
| }
|
|
|
| - // If we're unable to compute the stub (not enough memory left), we
|
| - // simply avoid updating the caches.
|
| - if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
|
| -
|
| // Patch the call site depending on the state of the cache. Make
|
| // sure to always rewrite from monomorphic to megamorphic.
|
| ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
|
| if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
|
| - set_target(Code::cast(code));
|
| + set_target(*code);
|
| } else if (state == MONOMORPHIC) {
|
| - set_target(megamorphic_stub());
|
| + set_target(*megamorphic_stub());
|
| }
|
|
|
| #ifdef DEBUG
|
| @@ -1566,7 +1506,7 @@ static bool AddOneReceiverMapIfMissing(MapList* receiver_maps,
|
|
|
| void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) {
|
| ASSERT(stub->is_inline_cache_stub());
|
| - if (stub == string_stub()) {
|
| + if (!string_stub().is_null() && stub == *string_stub()) {
|
| return result->Add(isolate()->heap()->string_map());
|
| } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
|
| if (stub->ic_state() == MONOMORPHIC) {
|
| @@ -1586,6 +1526,20 @@ void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) {
|
| }
|
|
|
|
|
| +Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
|
| + StubKind stub_kind,
|
| + StrictModeFlag strict_mode,
|
| + Handle<Code> generic_stub) {
|
| + CALL_HEAP_FUNCTION(isolate(),
|
| + ComputeStub(*receiver,
|
| + stub_kind,
|
| + strict_mode,
|
| + *generic_stub),
|
| + Code);
|
| +}
|
| +
|
| +
|
| +
|
| MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
|
| StubKind stub_kind,
|
| StrictModeFlag strict_mode,
|
| @@ -1663,8 +1617,8 @@ MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
|
| Map* receiver_map,
|
| StrictModeFlag strict_mode) {
|
| if ((receiver_map->instance_type() & kNotStringTag) == 0) {
|
| - ASSERT(string_stub() != NULL);
|
| - return string_stub();
|
| + ASSERT(!string_stub().is_null());
|
| + return *string_stub();
|
| } else {
|
| ASSERT(receiver_map->has_dictionary_elements() ||
|
| receiver_map->has_fast_elements() ||
|
| @@ -1993,7 +1947,7 @@ RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
|
|
|
| // Used from ic-<arch>.cc
|
| RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
|
| - NoHandleAllocation na;
|
| + HandleScope scope(isolate);
|
| ASSERT(args.length() == 2);
|
| KeyedLoadIC ic(isolate);
|
| IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
|
| @@ -2002,7 +1956,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
|
|
|
|
|
| RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
|
| - NoHandleAllocation na;
|
| + HandleScope scope(isolate);
|
| ASSERT(args.length() == 2);
|
| KeyedLoadIC ic(isolate);
|
| IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
|
|
|