| Index: src/ic.cc
|
| ===================================================================
|
| --- src/ic.cc (revision 7267)
|
| +++ src/ic.cc (working copy)
|
| @@ -65,8 +65,8 @@
|
| 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 @@
|
| #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 @@
|
| #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 @@
|
|
|
| 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 @@
|
| 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);
|
| }
|
|
|
|
|
| @@ -292,9 +297,10 @@
|
| 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);
|
| }
|
|
|
| @@ -302,7 +308,7 @@
|
| 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());
|
| }
|
|
|
|
|
| @@ -320,10 +326,11 @@
|
| // 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);
|
| }
|
|
|
| @@ -339,7 +346,7 @@
|
| // 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);
|
| }
|
|
|
|
|
| @@ -357,14 +364,14 @@
|
| // 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());
|
| }
|
|
|
|
|
| @@ -423,8 +430,8 @@
|
|
|
|
|
| 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()) {
|
| @@ -459,7 +466,7 @@
|
| 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));
|
| }
|
| }
|
|
|
| @@ -531,7 +538,7 @@
|
|
|
| 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);
|
| @@ -543,11 +550,12 @@
|
| 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
|
| @@ -573,7 +581,7 @@
|
|
|
| // 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 +
|
| @@ -623,13 +631,13 @@
|
| 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: {
|
| @@ -637,14 +645,15 @@
|
| // 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: {
|
| @@ -657,35 +666,36 @@
|
| 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:
|
| @@ -705,7 +715,8 @@
|
| 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;
|
| @@ -720,7 +731,9 @@
|
| // 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)) {
|
| @@ -740,7 +753,9 @@
|
| 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,
|
| @@ -768,7 +783,7 @@
|
| 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);
|
| @@ -797,7 +812,7 @@
|
| 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)) {
|
| @@ -809,9 +824,9 @@
|
| }
|
| }
|
|
|
| - 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
|
| @@ -852,8 +867,8 @@
|
| // 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
|
| @@ -862,24 +877,29 @@
|
| 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::LoadIC_StringLength));
|
| } else {
|
| - set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength));
|
| + set_target(isolate()->builtins()->builtin(
|
| + Builtins::LoadIC_StringWrapperLength));
|
| }
|
| } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
|
| - set_target(Builtins::builtin(Builtins::LoadIC_StringWrapperLength));
|
| + set_target(isolate()->builtins()->builtin(
|
| + Builtins::LoadIC_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
|
| @@ -887,7 +907,8 @@
|
| 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::LoadIC_ArrayLength));
|
| } else {
|
| set_target(non_monomorphic_stub);
|
| }
|
| @@ -895,13 +916,15 @@
|
| }
|
|
|
| // 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::LoadIC_FunctionPrototype));
|
| } else {
|
| set_target(non_monomorphic_stub);
|
| }
|
| @@ -923,7 +946,7 @@
|
| if (FLAG_strict || IsContextual(object)) {
|
| return ReferenceError("not_defined", name);
|
| }
|
| - LOG(SuspectReadEvent(*name, *object));
|
| + LOG(isolate(), SuspectReadEvent(*name, *object));
|
| }
|
|
|
| bool can_be_inlined_precheck =
|
| @@ -974,7 +997,7 @@
|
| 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 {
|
| @@ -1021,7 +1044,7 @@
|
| 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;
|
| @@ -1033,20 +1056,23 @@
|
| 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: {
|
| @@ -1054,7 +1080,7 @@
|
| 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,
|
| @@ -1065,7 +1091,7 @@
|
| // 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;
|
| }
|
| @@ -1074,14 +1100,14 @@
|
| 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:
|
| @@ -1105,7 +1131,7 @@
|
| 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
|
| @@ -1130,11 +1156,13 @@
|
| // 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));
|
| @@ -1145,11 +1173,13 @@
|
| }
|
|
|
| // 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));
|
| @@ -1160,12 +1190,14 @@
|
| }
|
|
|
| // 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));
|
| @@ -1180,10 +1212,10 @@
|
| // 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.
|
| @@ -1233,9 +1265,8 @@
|
| 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()) {
|
| @@ -1243,7 +1274,7 @@
|
| } 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());
|
| }
|
| @@ -1269,7 +1300,7 @@
|
| }
|
|
|
| // Get the property.
|
| - return Runtime::GetObjectProperty(object, key);
|
| + return Runtime::GetObjectProperty(isolate(), object, key);
|
| }
|
|
|
|
|
| @@ -1281,7 +1312,7 @@
|
| 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;
|
| @@ -1296,17 +1327,14 @@
|
| // 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: {
|
| @@ -1314,16 +1342,14 @@
|
| 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: {
|
| @@ -1399,7 +1425,7 @@
|
| 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.
|
| @@ -1411,7 +1437,7 @@
|
| // 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;
|
| @@ -1419,7 +1445,7 @@
|
|
|
| // 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");
|
| @@ -1427,7 +1453,7 @@
|
| Builtins::Name target = (strict_mode == kStrictMode)
|
| ? Builtins::StoreIC_ArrayLength_Strict
|
| : Builtins::StoreIC_ArrayLength;
|
| - set_target(Builtins::builtin(target));
|
| + set_target(isolate()->builtins()->builtin(target));
|
| return receiver->SetProperty(*name, *value, NONE, strict_mode);
|
| }
|
|
|
| @@ -1543,17 +1569,17 @@
|
| 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;
|
| }
|
| @@ -1565,11 +1591,11 @@
|
| 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;
|
| }
|
| @@ -1577,13 +1603,13 @@
|
| 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;
|
| }
|
| @@ -1607,7 +1633,9 @@
|
| }
|
| } 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
|
| @@ -1637,7 +1665,7 @@
|
| // 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;
|
| @@ -1669,13 +1697,14 @@
|
| 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 (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());
|
| }
|
| @@ -1685,7 +1714,8 @@
|
| }
|
|
|
| // Set the property.
|
| - return Runtime::SetObjectProperty(object, key, value, NONE, strict_mode);
|
| + return Runtime::SetObjectProperty(
|
| + isolate(), object , key, value, NONE, strict_mode);
|
| }
|
|
|
|
|
| @@ -1718,17 +1748,17 @@
|
|
|
| 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;
|
| }
|
| @@ -1769,11 +1799,12 @@
|
| // 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 {
|
| @@ -1784,10 +1815,11 @@
|
|
|
|
|
| // 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,
|
| @@ -1807,15 +1839,18 @@
|
| 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 =
|
| @@ -1826,35 +1861,40 @@
|
| 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,
|
| @@ -1865,7 +1905,8 @@
|
| }
|
|
|
|
|
| -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);
|
| @@ -1886,7 +1927,9 @@
|
| // 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);
|
|
|
| @@ -1920,10 +1963,11 @@
|
|
|
|
|
| // 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,
|
| @@ -1993,10 +2037,11 @@
|
| 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();
|
| @@ -2007,7 +2052,7 @@
|
| 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",
|
| @@ -2017,7 +2062,8 @@
|
| }
|
| }
|
|
|
| - 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:
|
| @@ -2057,7 +2103,8 @@
|
| UNREACHABLE();
|
| }
|
|
|
| - Handle<JSFunction> builtin_function(JSFunction::cast(builtin));
|
| + Handle<JSFunction> builtin_function(JSFunction::cast(builtin),
|
| + isolate);
|
|
|
| bool caught_exception;
|
| Object** builtin_args[] = { right.location() };
|
| @@ -2156,10 +2203,11 @@
|
| 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();
|
| @@ -2201,7 +2249,7 @@
|
| TRBinaryOpIC::GetName(result_type),
|
| Token::Name(op));
|
| }
|
| - TRBinaryOpIC ic;
|
| + TRBinaryOpIC ic(isolate);
|
| ic.patch(*code);
|
|
|
| // Activate inlined smi code.
|
| @@ -2210,7 +2258,8 @@
|
| }
|
| }
|
|
|
| - 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:
|
| @@ -2250,7 +2299,7 @@
|
| UNREACHABLE();
|
| }
|
|
|
| - Handle<JSFunction> builtin_function(JSFunction::cast(builtin));
|
| + Handle<JSFunction> builtin_function(JSFunction::cast(builtin), isolate);
|
|
|
| bool caught_exception;
|
| Object** builtin_args[] = { right.location() };
|
| @@ -2310,16 +2359,17 @@
|
|
|
|
|
| // 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
|
|
|