diff options
Diffstat (limited to 'src/ic.cc')
-rw-r--r-- | src/ic.cc | 430 |
1 files changed, 240 insertions, 190 deletions
@@ -65,8 +65,8 @@ void IC::TraceIC(const char* type, const char* extra_info) { if (FLAG_trace_ic) { State new_state = StateFrom(new_target, - Heap::undefined_value(), - Heap::undefined_value()); + HEAP->undefined_value(), + HEAP->undefined_value()); PrintF("[%s (%c->%c)%s", type, TransitionMarkFromState(old_state), TransitionMarkFromState(new_state), @@ -78,11 +78,13 @@ void IC::TraceIC(const char* type, #endif -IC::IC(FrameDepth depth) { +IC::IC(FrameDepth depth, Isolate* isolate) : isolate_(isolate) { + ASSERT(isolate == Isolate::Current()); // To improve the performance of the (much used) IC code, we unfold // a few levels of the stack frame iteration code. This yields a // ~35% speedup when running DeltaBlue with the '--nouse-ic' flag. - const Address entry = Top::c_entry_fp(Top::GetCurrentThread()); + const Address entry = + Isolate::c_entry_fp(isolate->thread_local_top()); Address* pc_address = reinterpret_cast<Address*>(entry + ExitFrameConstants::kCallerPCOffset); Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); @@ -136,9 +138,11 @@ Address IC::OriginalCodeAddress() { #endif -static bool HasNormalObjectsInPrototypeChain(LookupResult* lookup, +static bool HasNormalObjectsInPrototypeChain(Isolate* isolate, + LookupResult* lookup, Object* receiver) { - Object* end = lookup->IsProperty() ? lookup->holder() : Heap::null_value(); + Object* end = lookup->IsProperty() + ? lookup->holder() : isolate->heap()->null_value(); for (Object* current = receiver; current != end; current = current->GetPrototype()) { @@ -231,7 +235,7 @@ IC::State IC::StateFrom(Code* target, Object* receiver, Object* name) { RelocInfo::Mode IC::ComputeMode() { Address addr = address(); - Code* code = Code::cast(Heap::FindCodeObject(addr)); + Code* code = Code::cast(isolate()->heap()->FindCodeObject(addr)); for (RelocIterator it(code, RelocInfo::kCodeTargetMask); !it.done(); it.next()) { RelocInfo* info = it.rinfo(); @@ -245,18 +249,19 @@ RelocInfo::Mode IC::ComputeMode() { Failure* IC::TypeError(const char* type, Handle<Object> object, Handle<Object> key) { - HandleScope scope; + HandleScope scope(isolate()); Handle<Object> args[2] = { key, object }; - Handle<Object> error = Factory::NewTypeError(type, HandleVector(args, 2)); - return Top::Throw(*error); + Handle<Object> error = isolate()->factory()->NewTypeError( + type, HandleVector(args, 2)); + return isolate()->Throw(*error); } Failure* IC::ReferenceError(const char* type, Handle<String> name) { - HandleScope scope; - Handle<Object> error = - Factory::NewReferenceError(type, HandleVector(&name, 1)); - return Top::Throw(*error); + HandleScope scope(isolate()); + Handle<Object> error = isolate()->factory()->NewReferenceError( + type, HandleVector(&name, 1)); + return isolate()->Throw(*error); } @@ -268,9 +273,13 @@ void IC::Clear(Address address) { switch (target->kind()) { case Code::LOAD_IC: return LoadIC::Clear(address, target); - case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target); + case Code::KEYED_LOAD_IC: + case Code::KEYED_EXTERNAL_ARRAY_LOAD_IC: + return KeyedLoadIC::Clear(address, target); case Code::STORE_IC: return StoreIC::Clear(address, target); - case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target); + case Code::KEYED_STORE_IC: + case Code::KEYED_EXTERNAL_ARRAY_STORE_IC: + return KeyedStoreIC::Clear(address, target); case Code::CALL_IC: return CallIC::Clear(address, target); case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target); case Code::BINARY_OP_IC: @@ -288,9 +297,10 @@ void CallICBase::Clear(Address address, Code* target) { State state = target->ic_state(); if (state == UNINITIALIZED) return; Code* code = - StubCache::FindCallInitialize(target->arguments_count(), - target->ic_in_loop(), - target->kind()); + Isolate::Current()->stub_cache()->FindCallInitialize( + target->arguments_count(), + target->ic_in_loop(), + target->kind()); SetTargetAtAddress(address, code); } @@ -298,7 +308,7 @@ void CallICBase::Clear(Address address, Code* target) { void KeyedLoadIC::ClearInlinedVersion(Address address) { // Insert null as the map to check for to make sure the map check fails // sending control flow to the IC instead of the inlined version. - PatchInlinedLoad(address, Heap::null_value()); + PatchInlinedLoad(address, HEAP->null_value()); } @@ -316,10 +326,11 @@ void LoadIC::ClearInlinedVersion(Address address) { // Reset the map check of the inlined inobject property load (if // present) to guarantee failure by holding an invalid map (the null // value). The offset can be patched to anything. - PatchInlinedLoad(address, Heap::null_value(), 0); + Heap* heap = HEAP; + PatchInlinedLoad(address, heap->null_value(), 0); PatchInlinedContextualLoad(address, - Heap::null_value(), - Heap::null_value(), + heap->null_value(), + heap->null_value(), true); } @@ -335,7 +346,7 @@ void StoreIC::ClearInlinedVersion(Address address) { // Reset the map check of the inlined inobject property store (if // present) to guarantee failure by holding an invalid map (the null // value). The offset can be patched to anything. - PatchInlinedStore(address, Heap::null_value(), 0); + PatchInlinedStore(address, HEAP->null_value(), 0); } @@ -353,14 +364,14 @@ void KeyedStoreIC::ClearInlinedVersion(Address address) { // Insert null as the elements map to check for. This will make // sure that the elements fast-case map check fails so that control // flows to the IC instead of the inlined version. - PatchInlinedStore(address, Heap::null_value()); + PatchInlinedStore(address, HEAP->null_value()); } void KeyedStoreIC::RestoreInlinedVersion(Address address) { // Restore the fast-case elements map check so that the inlined // version can be used again. - PatchInlinedStore(address, Heap::fixed_array_map()); + PatchInlinedStore(address, HEAP->fixed_array_map()); } @@ -419,8 +430,8 @@ static void LookupForRead(Object* object, Object* CallICBase::TryCallAsFunction(Object* object) { - HandleScope scope; - Handle<Object> target(object); + HandleScope scope(isolate()); + Handle<Object> target(object, isolate()); Handle<Object> delegate = Execution::GetFunctionDelegate(target); if (delegate->IsJSFunction()) { @@ -455,7 +466,7 @@ void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee, StackFrameLocator locator; JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); int index = frame->ComputeExpressionsCount() - (argc + 1); - frame->SetExpression(index, *Factory::ToObject(object)); + frame->SetExpression(index, *isolate()->factory()->ToObject(object)); } } @@ -527,7 +538,7 @@ MaybeObject* CallICBase::LoadFunction(State state, ASSERT(!result->IsTheHole()); - HandleScope scope; + HandleScope scope(isolate()); // Wrap result in a handle because ReceiverToObjectIfRequired may allocate // new object and cause GC. Handle<Object> result_handle(result); @@ -539,11 +550,12 @@ MaybeObject* CallICBase::LoadFunction(State state, if (result_handle->IsJSFunction()) { #ifdef ENABLE_DEBUGGER_SUPPORT // Handle stepping into a function if step into is active. - if (Debug::StepInActive()) { + Debug* debug = isolate()->debug(); + if (debug->StepInActive()) { // Protect the result in a handle as the debugger can allocate and might // cause GC. - Handle<JSFunction> function(JSFunction::cast(*result_handle)); - Debug::HandleStepIn(function, object, fp(), false); + Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate()); + debug->HandleStepIn(function, object, fp(), false); return *function; } #endif @@ -569,7 +581,7 @@ bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, // Fetch the arguments passed to the called function. const int argc = target()->arguments_count(); - Address entry = Top::c_entry_fp(Top::GetCurrentThread()); + Address entry = isolate()->c_entry_fp(isolate()->thread_local_top()); Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); Arguments args(argc + 1, &Memory::Object_at(fp + @@ -619,13 +631,13 @@ MaybeObject* CallICBase::ComputeMonomorphicStub( switch (lookup->type()) { case FIELD: { int index = lookup->GetFieldIndex(); - maybe_code = StubCache::ComputeCallField(argc, - in_loop, - kind_, - *name, - *object, - lookup->holder(), - index); + maybe_code = isolate()->stub_cache()->ComputeCallField(argc, + in_loop, + kind_, + *name, + *object, + lookup->holder(), + index); break; } case CONSTANT_FUNCTION: { @@ -633,14 +645,15 @@ MaybeObject* CallICBase::ComputeMonomorphicStub( // call; used for rewriting to monomorphic state and making sure // that the code stub is in the stub cache. JSFunction* function = lookup->GetConstantFunction(); - maybe_code = StubCache::ComputeCallConstant(argc, - in_loop, - kind_, - extra_ic_state, - *name, - *object, - lookup->holder(), - function); + maybe_code = + isolate()->stub_cache()->ComputeCallConstant(argc, + in_loop, + kind_, + extra_ic_state, + *name, + *object, + lookup->holder(), + function); break; } case NORMAL: { @@ -653,35 +666,36 @@ MaybeObject* CallICBase::ComputeMonomorphicStub( JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); if (!cell->value()->IsJSFunction()) return NULL; JSFunction* function = JSFunction::cast(cell->value()); - maybe_code = StubCache::ComputeCallGlobal(argc, - in_loop, - kind_, - *name, - *receiver, - global, - cell, - function); + maybe_code = isolate()->stub_cache()->ComputeCallGlobal(argc, + in_loop, + kind_, + *name, + *receiver, + global, + cell, + function); } else { // There is only one shared stub for calling normalized // properties. It does not traverse the prototype chain, so the // property must be found in the receiver for the stub to be // applicable. if (lookup->holder() != *receiver) return NULL; - maybe_code = StubCache::ComputeCallNormal(argc, - in_loop, - kind_, - *name, - *receiver); + maybe_code = isolate()->stub_cache()->ComputeCallNormal(argc, + in_loop, + kind_, + *name, + *receiver); } break; } case INTERCEPTOR: { ASSERT(HasInterceptorGetter(lookup->holder())); - maybe_code = StubCache::ComputeCallInterceptor(argc, - kind_, - *name, - *object, - lookup->holder()); + maybe_code = isolate()->stub_cache()->ComputeCallInterceptor( + argc, + kind_, + *name, + *object, + lookup->holder()); break; } default: @@ -701,7 +715,8 @@ void CallICBase::UpdateCaches(LookupResult* lookup, if (!lookup->IsProperty() || !lookup->IsCacheable()) return; if (lookup->holder() != *object && - HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) { + HasNormalObjectsInPrototypeChain( + isolate(), lookup, object->GetPrototype())) { // Suppress optimization for prototype chains with slow properties objects // in the middle. return; @@ -716,7 +731,9 @@ void CallICBase::UpdateCaches(LookupResult* lookup, // 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 = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); + maybe_code = isolate()->stub_cache()->ComputeCallPreMonomorphic(argc, + in_loop, + kind_); } else if (state == MONOMORPHIC) { if (kind_ == Code::CALL_IC && TryUpdateExtraICState(lookup, object, &extra_ic_state)) { @@ -736,7 +753,9 @@ void CallICBase::UpdateCaches(LookupResult* lookup, object, name); } else { - maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); + maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic(argc, + in_loop, + kind_); } } else { maybe_code = ComputeMonomorphicStub(lookup, @@ -764,7 +783,7 @@ void CallICBase::UpdateCaches(LookupResult* lookup, object->GetPrototype())->map(); // Update the stub cache. - StubCache::Set(*name, map, Code::cast(code)); + isolate()->stub_cache()->Set(*name, map, Code::cast(code)); } USE(had_proto_failure); @@ -793,7 +812,7 @@ MaybeObject* KeyedCallIC::LoadFunction(State state, if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { int argc = target()->arguments_count(); InLoopFlag in_loop = target()->ic_in_loop(); - MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic( + MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( argc, in_loop, Code::KEYED_CALL_IC); Object* code; if (maybe_code->ToObject(&code)) { @@ -805,9 +824,9 @@ MaybeObject* KeyedCallIC::LoadFunction(State state, } } - HandleScope scope; + HandleScope scope(isolate()); Handle<Object> result = GetProperty(object, key); - RETURN_IF_EMPTY_HANDLE(result); + RETURN_IF_EMPTY_HANDLE(isolate(), result); // Make receiver an object if the callee requires it. Strict mode or builtin // functions do not wrap the receiver, non-strict functions and objects @@ -848,8 +867,8 @@ MaybeObject* LoadIC::Load(State state, // objects is read-only and therefore always returns the length of // the underlying string value. See ECMA-262 15.5.5.1. if ((object->IsString() || object->IsStringWrapper()) && - name->Equals(Heap::length_symbol())) { - HandleScope scope; + name->Equals(isolate()->heap()->length_symbol())) { + HandleScope scope(isolate()); #ifdef DEBUG if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); #endif @@ -858,24 +877,29 @@ MaybeObject* LoadIC::Load(State state, Map* map = HeapObject::cast(*object)->map(); const int offset = String::kLengthOffset; PatchInlinedLoad(address(), map, offset); - set_target(Builtins::builtin(Builtins::LoadIC_StringLength)); + set_target(isolate()->builtins()->builtin( + Builtins::kLoadIC_StringLength)); } else { - set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength)); + set_target(isolate()->builtins()->builtin( + Builtins::kLoadIC_StringWrapperLength)); } } else if (state == MONOMORPHIC && object->IsStringWrapper()) { - set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength)); + set_target(isolate()->builtins()->builtin( + Builtins::kLoadIC_StringWrapperLength)); } else { set_target(non_monomorphic_stub); } // Get the string if we have a string wrapper object. if (object->IsJSValue()) { - object = Handle<Object>(Handle<JSValue>::cast(object)->value()); + object = Handle<Object>(Handle<JSValue>::cast(object)->value(), + isolate()); } return Smi::FromInt(String::cast(*object)->length()); } // Use specialized code for getting the length of arrays. - if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { + if (object->IsJSArray() && + name->Equals(isolate()->heap()->length_symbol())) { #ifdef DEBUG if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); #endif @@ -883,7 +907,8 @@ MaybeObject* LoadIC::Load(State state, Map* map = HeapObject::cast(*object)->map(); const int offset = JSArray::kLengthOffset; PatchInlinedLoad(address(), map, offset); - set_target(Builtins::builtin(Builtins::LoadIC_ArrayLength)); + set_target(isolate()->builtins()->builtin( + Builtins::kLoadIC_ArrayLength)); } else { set_target(non_monomorphic_stub); } @@ -891,13 +916,15 @@ MaybeObject* LoadIC::Load(State state, } // Use specialized code for getting prototype of functions. - if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && + if (object->IsJSFunction() && + name->Equals(isolate()->heap()->prototype_symbol()) && JSFunction::cast(*object)->should_have_prototype()) { #ifdef DEBUG if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); #endif if (state == PREMONOMORPHIC) { - set_target(Builtins::builtin(Builtins::LoadIC_FunctionPrototype)); + set_target(isolate()->builtins()->builtin( + Builtins::kLoadIC_FunctionPrototype)); } else { set_target(non_monomorphic_stub); } @@ -919,7 +946,7 @@ MaybeObject* LoadIC::Load(State state, if (FLAG_strict || IsContextual(object)) { return ReferenceError("not_defined", name); } - LOG(SuspectReadEvent(*name, *object)); + LOG(isolate(), SuspectReadEvent(*name, *object)); } bool can_be_inlined_precheck = @@ -970,7 +997,7 @@ MaybeObject* LoadIC::Load(State state, lookup.IsDontDelete())) { set_target(megamorphic_stub()); TRACE_IC_NAMED("[LoadIC : inline contextual patch %s]\n", name); - ASSERT(cell->value() != Heap::the_hole_value()); + ASSERT(cell->value() != isolate()->heap()->the_hole_value()); return cell->value(); } } else { @@ -1017,7 +1044,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup, if (!object->IsJSObject()) return; Handle<JSObject> receiver = Handle<JSObject>::cast(object); - if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; + if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; // Compute the code stub for this load. MaybeObject* maybe_code = NULL; @@ -1029,20 +1056,23 @@ void LoadIC::UpdateCaches(LookupResult* lookup, maybe_code = pre_monomorphic_stub(); } else if (!lookup->IsProperty()) { // Nonexistent property. The result is undefined. - maybe_code = StubCache::ComputeLoadNonexistent(*name, *receiver); + maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name, + *receiver); } else { // Compute monomorphic stub. switch (lookup->type()) { case FIELD: { - maybe_code = StubCache::ComputeLoadField(*name, *receiver, - lookup->holder(), - lookup->GetFieldIndex()); + maybe_code = isolate()->stub_cache()->ComputeLoadField( + *name, + *receiver, + lookup->holder(), + lookup->GetFieldIndex()); break; } case CONSTANT_FUNCTION: { Object* constant = lookup->GetConstantFunction(); - maybe_code = StubCache::ComputeLoadConstant(*name, *receiver, - lookup->holder(), constant); + maybe_code = isolate()->stub_cache()->ComputeLoadConstant( + *name, *receiver, lookup->holder(), constant); break; } case NORMAL: { @@ -1050,7 +1080,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup, GlobalObject* global = GlobalObject::cast(lookup->holder()); JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); - maybe_code = StubCache::ComputeLoadGlobal(*name, + maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name, *receiver, global, cell, @@ -1061,7 +1091,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup, // property must be found in the receiver for the stub to be // applicable. if (lookup->holder() != *receiver) return; - maybe_code = StubCache::ComputeLoadNormal(); + maybe_code = isolate()->stub_cache()->ComputeLoadNormal(); } break; } @@ -1070,14 +1100,14 @@ void LoadIC::UpdateCaches(LookupResult* lookup, AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); if (v8::ToCData<Address>(callback->getter()) == 0) return; - maybe_code = StubCache::ComputeLoadCallback(*name, *receiver, - lookup->holder(), callback); + maybe_code = isolate()->stub_cache()->ComputeLoadCallback( + *name, *receiver, lookup->holder(), callback); break; } case INTERCEPTOR: { ASSERT(HasInterceptorGetter(lookup->holder())); - maybe_code = StubCache::ComputeLoadInterceptor(*name, *receiver, - lookup->holder()); + maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor( + *name, *receiver, lookup->holder()); break; } default: @@ -1101,7 +1131,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup, Map* map = JSObject::cast(object->IsJSObject() ? *object : object->GetPrototype())->map(); - StubCache::Set(*name, map, Code::cast(code)); + isolate()->stub_cache()->Set(*name, map, Code::cast(code)); } #ifdef DEBUG @@ -1126,11 +1156,13 @@ MaybeObject* KeyedLoadIC::Load(State state, // TODO(1073): don't ignore the current stub state. // Use specialized code for getting the length of strings. - if (object->IsString() && name->Equals(Heap::length_symbol())) { + if (object->IsString() && + name->Equals(isolate()->heap()->length_symbol())) { Handle<String> string = Handle<String>::cast(object); Object* code = NULL; { MaybeObject* maybe_code = - StubCache::ComputeKeyedLoadStringLength(*name, *string); + isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name, + *string); if (!maybe_code->ToObject(&code)) return maybe_code; } set_target(Code::cast(code)); @@ -1141,11 +1173,13 @@ MaybeObject* KeyedLoadIC::Load(State state, } // Use specialized code for getting the length of arrays. - if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { + if (object->IsJSArray() && + name->Equals(isolate()->heap()->length_symbol())) { Handle<JSArray> array = Handle<JSArray>::cast(object); Object* code; { MaybeObject* maybe_code = - StubCache::ComputeKeyedLoadArrayLength(*name, *array); + isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name, + *array); if (!maybe_code->ToObject(&code)) return maybe_code; } set_target(Code::cast(code)); @@ -1156,12 +1190,14 @@ MaybeObject* KeyedLoadIC::Load(State state, } // Use specialized code for getting prototype of functions. - if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && + if (object->IsJSFunction() && + name->Equals(isolate()->heap()->prototype_symbol()) && JSFunction::cast(*object)->should_have_prototype()) { Handle<JSFunction> function = Handle<JSFunction>::cast(object); Object* code; { MaybeObject* maybe_code = - StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); + isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype( + *name, *function); if (!maybe_code->ToObject(&code)) return maybe_code; } set_target(Code::cast(code)); @@ -1176,10 +1212,10 @@ MaybeObject* KeyedLoadIC::Load(State state, // the element or char if so. uint32_t index = 0; if (name->AsArrayIndex(&index)) { - HandleScope scope; + HandleScope scope(isolate()); // Rewrite to the generic keyed load stub. if (FLAG_use_ic) set_target(generic_stub()); - return Runtime::GetElementOrCharAt(object, index); + return Runtime::GetElementOrCharAt(isolate(), object, index); } // Named lookup. @@ -1229,22 +1265,16 @@ MaybeObject* KeyedLoadIC::Load(State state, Handle<JSObject> receiver = Handle<JSObject>::cast(object); if (receiver->HasExternalArrayElements()) { MaybeObject* probe = - StubCache::ComputeKeyedLoadOrStoreExternalArray(*receiver, - false, - kNonStrictMode); + isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( + *receiver, false, kNonStrictMode); stub = probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked()); } else if (receiver->HasIndexedInterceptor()) { stub = indexed_interceptor_stub(); - } else if (receiver->HasPixelElements()) { - MaybeObject* probe = - StubCache::ComputeKeyedLoadPixelArray(*receiver); - stub = probe->IsFailure() ? - NULL : Code::cast(probe->ToObjectUnchecked()); } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { MaybeObject* probe = - StubCache::ComputeKeyedLoadSpecialized(*receiver); + isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver); stub = probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked()); } @@ -1270,7 +1300,7 @@ MaybeObject* KeyedLoadIC::Load(State state, } // Get the property. - return Runtime::GetObjectProperty(object, key); + return Runtime::GetObjectProperty(isolate(), object, key); } @@ -1282,7 +1312,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, if (!object->IsJSObject()) return; Handle<JSObject> receiver = Handle<JSObject>::cast(object); - if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; + if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; // Compute the code stub for this load. MaybeObject* maybe_code = NULL; @@ -1297,17 +1327,14 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, // Compute a monomorphic stub. switch (lookup->type()) { case FIELD: { - maybe_code = StubCache::ComputeKeyedLoadField(*name, *receiver, - lookup->holder(), - lookup->GetFieldIndex()); + maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField( + *name, *receiver, lookup->holder(), lookup->GetFieldIndex()); break; } case CONSTANT_FUNCTION: { Object* constant = lookup->GetConstantFunction(); - maybe_code = StubCache::ComputeKeyedLoadConstant(*name, - *receiver, - lookup->holder(), - constant); + maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant( + *name, *receiver, lookup->holder(), constant); break; } case CALLBACKS: { @@ -1315,16 +1342,14 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); if (v8::ToCData<Address>(callback->getter()) == 0) return; - maybe_code = StubCache::ComputeKeyedLoadCallback(*name, - *receiver, - lookup->holder(), - callback); + maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback( + *name, *receiver, lookup->holder(), callback); break; } case INTERCEPTOR: { ASSERT(HasInterceptorGetter(lookup->holder())); - maybe_code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver, - lookup->holder()); + maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor( + *name, *receiver, lookup->holder()); break; } default: { @@ -1400,7 +1425,7 @@ MaybeObject* StoreIC::Store(State state, if (!object->IsJSObject()) { // The length property of string values is read-only. Throw in strict mode. if (strict_mode == kStrictMode && object->IsString() && - name->Equals(Heap::length_symbol())) { + name->Equals(isolate()->heap()->length_symbol())) { return TypeError("strict_read_only_property", object, name); } // Ignore stores where the receiver is not a JSObject. @@ -1412,7 +1437,7 @@ MaybeObject* StoreIC::Store(State state, // Check if the given name is an array index. uint32_t index; if (name->AsArrayIndex(&index)) { - HandleScope scope; + HandleScope scope(isolate()); Handle<Object> result = SetElement(receiver, index, value, strict_mode); if (result.is_null()) return Failure::Exception(); return *value; @@ -1420,15 +1445,15 @@ MaybeObject* StoreIC::Store(State state, // Use specialized code for setting the length of arrays. if (receiver->IsJSArray() - && name->Equals(Heap::length_symbol()) + && name->Equals(isolate()->heap()->length_symbol()) && receiver->AllowsSetElementsLength()) { #ifdef DEBUG if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); #endif Builtins::Name target = (strict_mode == kStrictMode) - ? Builtins::StoreIC_ArrayLength_Strict - : Builtins::StoreIC_ArrayLength; - set_target(Builtins::builtin(target)); + ? Builtins::kStoreIC_ArrayLength_Strict + : Builtins::kStoreIC_ArrayLength; + set_target(isolate()->builtins()->builtin(target)); return receiver->SetProperty(*name, *value, NONE, strict_mode); } @@ -1544,17 +1569,17 @@ void StoreIC::UpdateCaches(LookupResult* lookup, Object* code = NULL; switch (type) { case FIELD: { - maybe_code = StubCache::ComputeStoreField( + maybe_code = isolate()->stub_cache()->ComputeStoreField( *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); break; } case MAP_TRANSITION: { if (lookup->GetAttributes() != NONE) return; - HandleScope scope; + HandleScope scope(isolate()); ASSERT(type == MAP_TRANSITION); Handle<Map> transition(lookup->GetTransitionMap()); int index = transition->PropertyIndexFor(*name); - maybe_code = StubCache::ComputeStoreField( + maybe_code = isolate()->stub_cache()->ComputeStoreField( *name, *receiver, index, *transition, strict_mode); break; } @@ -1566,11 +1591,11 @@ void StoreIC::UpdateCaches(LookupResult* lookup, Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); - maybe_code = StubCache::ComputeStoreGlobal( + maybe_code = isolate()->stub_cache()->ComputeStoreGlobal( *name, *global, cell, strict_mode); } else { if (lookup->holder() != *receiver) return; - maybe_code = StubCache::ComputeStoreNormal(strict_mode); + maybe_code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode); } break; } @@ -1578,13 +1603,13 @@ void StoreIC::UpdateCaches(LookupResult* lookup, if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); if (v8::ToCData<Address>(callback->setter()) == 0) return; - maybe_code = StubCache::ComputeStoreCallback( + maybe_code = isolate()->stub_cache()->ComputeStoreCallback( *name, *receiver, callback, strict_mode); break; } case INTERCEPTOR: { ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); - maybe_code = StubCache::ComputeStoreInterceptor( + maybe_code = isolate()->stub_cache()->ComputeStoreInterceptor( *name, *receiver, strict_mode); break; } @@ -1608,7 +1633,9 @@ void StoreIC::UpdateCaches(LookupResult* lookup, } } else if (state == MEGAMORPHIC) { // Update the stub cache. - StubCache::Set(*name, receiver->map(), Code::cast(code)); + isolate()->stub_cache()->Set(*name, + receiver->map(), + Code::cast(code)); } #ifdef DEBUG @@ -1638,7 +1665,7 @@ MaybeObject* KeyedStoreIC::Store(State state, // Check if the given name is an array index. uint32_t index; if (name->AsArrayIndex(&index)) { - HandleScope scope; + HandleScope scope(isolate()); Handle<Object> result = SetElement(receiver, index, value, strict_mode); if (result.is_null()) return Failure::Exception(); return *value; @@ -1670,18 +1697,14 @@ MaybeObject* KeyedStoreIC::Store(State state, Handle<JSObject> receiver = Handle<JSObject>::cast(object); if (receiver->HasExternalArrayElements()) { MaybeObject* probe = - StubCache::ComputeKeyedLoadOrStoreExternalArray( + isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( *receiver, true, strict_mode); stub = probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked()); - } else if (receiver->HasPixelElements()) { - MaybeObject* probe = - StubCache::ComputeKeyedStorePixelArray(*receiver, strict_mode); - stub = probe->IsFailure() ? - NULL : Code::cast(probe->ToObjectUnchecked()); } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { MaybeObject* probe = - StubCache::ComputeKeyedStoreSpecialized(*receiver, strict_mode); + isolate()->stub_cache()->ComputeKeyedStoreSpecialized( + *receiver, strict_mode); stub = probe->IsFailure() ? NULL : Code::cast(probe->ToObjectUnchecked()); } @@ -1691,7 +1714,8 @@ MaybeObject* KeyedStoreIC::Store(State state, } // Set the property. - return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode); + return Runtime::SetObjectProperty( + isolate(), object , key, value, NONE, strict_mode); } @@ -1724,17 +1748,17 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup, switch (type) { case FIELD: { - maybe_code = StubCache::ComputeKeyedStoreField( + maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( *name, *receiver, lookup->GetFieldIndex(), NULL, strict_mode); break; } case MAP_TRANSITION: { if (lookup->GetAttributes() == NONE) { - HandleScope scope; + HandleScope scope(isolate()); ASSERT(type == MAP_TRANSITION); Handle<Map> transition(lookup->GetTransitionMap()); int index = transition->PropertyIndexFor(*name); - maybe_code = StubCache::ComputeKeyedStoreField( + maybe_code = isolate()->stub_cache()->ComputeKeyedStoreField( *name, *receiver, index, *transition, strict_mode); break; } @@ -1775,11 +1799,12 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup, // Static IC stub generators. // -static JSFunction* CompileFunction(JSFunction* function, +static JSFunction* CompileFunction(Isolate* isolate, + JSFunction* function, InLoopFlag in_loop) { // Compile now with optimization. - HandleScope scope; - Handle<JSFunction> function_handle(function); + HandleScope scope(isolate); + Handle<JSFunction> function_handle(function, isolate); if (in_loop == IN_LOOP) { CompileLazyInLoop(function_handle, CLEAR_EXCEPTION); } else { @@ -1790,10 +1815,11 @@ static JSFunction* CompileFunction(JSFunction* function, // Used from ic-<arch>.cc. -MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* CallIC_Miss(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; NoHandleAllocation na; ASSERT(args.length() == 2); - CallIC ic; + CallIC ic(isolate); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); MaybeObject* maybe_result = ic.LoadFunction(state, @@ -1813,15 +1839,18 @@ MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) { if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { return result; } - return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop()); + return CompileFunction(isolate, + JSFunction::cast(result), + ic.target()->ic_in_loop()); } // Used from ic-<arch>.cc. -MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; NoHandleAllocation na; ASSERT(args.length() == 2); - KeyedCallIC ic; + KeyedCallIC ic(isolate); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); Object* result; { MaybeObject* maybe_result = @@ -1832,35 +1861,40 @@ MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(Arguments args) { if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { return result; } - return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop()); + return CompileFunction(isolate, + JSFunction::cast(result), + ic.target()->ic_in_loop()); } // Used from ic-<arch>.cc. -MUST_USE_RESULT MaybeObject* LoadIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* LoadIC_Miss(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; NoHandleAllocation na; ASSERT(args.length() == 2); - LoadIC ic; + LoadIC ic(isolate); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); return ic.Load(state, args.at<Object>(0), args.at<String>(1)); } // Used from ic-<arch>.cc -MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; NoHandleAllocation na; ASSERT(args.length() == 2); - KeyedLoadIC ic; + KeyedLoadIC ic(isolate); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); } // Used from ic-<arch>.cc. -MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* StoreIC_Miss(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; NoHandleAllocation na; ASSERT(args.length() == 3); - StoreIC ic; + StoreIC ic(isolate); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); return ic.Store(state, @@ -1871,7 +1905,8 @@ MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) { } -MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) { +MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; NoHandleAllocation nha; ASSERT(args.length() == 2); @@ -1892,7 +1927,9 @@ MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) { // Extend storage is called in a store inline cache when // it is necessary to extend the properties array of a // JSObject. -MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(Arguments args) { +MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage( + RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; NoHandleAllocation na; ASSERT(args.length() == 3); @@ -1926,10 +1963,11 @@ MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(Arguments args) { // Used from ic-<arch>.cc. -MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; NoHandleAllocation na; ASSERT(args.length() == 3); - KeyedStoreIC ic; + KeyedStoreIC ic(isolate); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); return ic.Store(state, @@ -1999,10 +2037,11 @@ BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Object* left, Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info); -MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) { +MUST_USE_RESULT MaybeObject* BinaryOp_Patch(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; ASSERT(args.length() == 5); - HandleScope scope; + HandleScope scope(isolate); Handle<Object> left = args.at<Object>(0); Handle<Object> right = args.at<Object>(1); int key = Smi::cast(args[2])->value(); @@ -2013,7 +2052,7 @@ MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) { BinaryOpIC::TypeInfo type = BinaryOpIC::GetTypeInfo(*left, *right); Handle<Code> code = GetBinaryOpStub(key, type); if (!code.is_null()) { - BinaryOpIC ic; + BinaryOpIC ic(isolate); ic.patch(*code); if (FLAG_trace_ic) { PrintF("[BinaryOpIC (%s->%s)#%s]\n", @@ -2023,7 +2062,8 @@ MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) { } } - Handle<JSBuiltinsObject> builtins = Top::builtins(); + Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( + isolate->thread_local_top()->context_->builtins(), isolate); Object* builtin = NULL; // Initialization calms down the compiler. switch (op) { case Token::ADD: @@ -2063,7 +2103,8 @@ MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) { UNREACHABLE(); } - Handle<JSFunction> builtin_function(JSFunction::cast(builtin)); + Handle<JSFunction> builtin_function(JSFunction::cast(builtin), + isolate); bool caught_exception; Object** builtin_args[] = { right.location() }; @@ -2090,6 +2131,7 @@ const char* TRBinaryOpIC::GetName(TypeInfo type_info) { case SMI: return "SMI"; case INT32: return "Int32s"; case HEAP_NUMBER: return "HeapNumbers"; + case ODDBALL: return "Oddball"; case STRING: return "Strings"; case GENERIC: return "Generic"; default: return "Invalid"; @@ -2104,6 +2146,7 @@ TRBinaryOpIC::State TRBinaryOpIC::ToState(TypeInfo type_info) { case SMI: case INT32: case HEAP_NUMBER: + case ODDBALL: case STRING: return MONOMORPHIC; case GENERIC: @@ -2151,6 +2194,10 @@ TRBinaryOpIC::TypeInfo TRBinaryOpIC::GetTypeInfo(Handle<Object> left, return STRING; } + // Check for oddball objects. + if (left->IsUndefined() && right->IsNumber()) return ODDBALL; + if (left->IsNumber() && right->IsUndefined()) return ODDBALL; + return GENERIC; } @@ -2162,10 +2209,11 @@ Handle<Code> GetTypeRecordingBinaryOpStub(int key, TRBinaryOpIC::TypeInfo result_type); -MaybeObject* TypeRecordingBinaryOp_Patch(Arguments args) { +MaybeObject* TypeRecordingBinaryOp_Patch(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; ASSERT(args.length() == 5); - HandleScope scope; + HandleScope scope(isolate); Handle<Object> left = args.at<Object>(0); Handle<Object> right = args.at<Object>(1); int key = Smi::cast(args[2])->value(); @@ -2207,7 +2255,7 @@ MaybeObject* TypeRecordingBinaryOp_Patch(Arguments args) { TRBinaryOpIC::GetName(result_type), Token::Name(op)); } - TRBinaryOpIC ic; + TRBinaryOpIC ic(isolate); ic.patch(*code); // Activate inlined smi code. @@ -2216,7 +2264,8 @@ MaybeObject* TypeRecordingBinaryOp_Patch(Arguments args) { } } - Handle<JSBuiltinsObject> builtins = Top::builtins(); + Handle<JSBuiltinsObject> builtins = Handle<JSBuiltinsObject>( + isolate->thread_local_top()->context_->builtins(), isolate); Object* builtin = NULL; // Initialization calms down the compiler. switch (op) { case Token::ADD: @@ -2256,7 +2305,7 @@ MaybeObject* TypeRecordingBinaryOp_Patch(Arguments args) { UNREACHABLE(); } - Handle<JSFunction> builtin_function(JSFunction::cast(builtin)); + Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate); bool caught_exception; Object** builtin_args[] = { right.location() }; @@ -2316,16 +2365,17 @@ CompareIC::State CompareIC::TargetState(State state, // Used from ic_<arch>.cc. -Code* CompareIC_Miss(Arguments args) { +Code* CompareIC_Miss(RUNTIME_CALLING_CONVENTION) { + RUNTIME_GET_ISOLATE; NoHandleAllocation na; ASSERT(args.length() == 3); - CompareIC ic(static_cast<Token::Value>(Smi::cast(args[2])->value())); + CompareIC ic(isolate, static_cast<Token::Value>(Smi::cast(args[2])->value())); ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1)); return ic.target(); } -static Address IC_utilities[] = { +static const Address IC_utilities[] = { #define ADDR(name) FUNCTION_ADDR(name), IC_UTIL_LIST(ADDR) NULL |