diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc index 7c5ad0ea54..958842d2c8 100644 --- a/src/arm/stub-cache-arm.cc +++ b/src/arm/stub-cache-arm.cc @@ -777,8 +777,26 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); // Check that the cell contains the same function. - __ cmp(r1, Operand(Handle(function))); - __ b(ne, &miss); + if (Heap::InNewSpace(function)) { + // We can't embed a pointer to a function in new space so we have + // to verify that the shared function info is unchanged. This has + // the nice side effect that multiple closures based on the same + // function can all use this call IC. Before we load through the + // function, we have to verify that it still is a function. + __ tst(r1, Operand(kSmiTagMask)); + __ b(eq, &miss); + __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); + __ b(ne, &miss); + + // Check the shared function info. Make sure it hasn't changed. + __ mov(r3, Operand(Handle(function->shared()))); + __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); + __ cmp(r2, r3); + __ b(ne, &miss); + } else { + __ cmp(r1, Operand(Handle(function))); + __ b(ne, &miss); + } // Patch the receiver on the stack with the global proxy if // necessary. diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc index 9c42f02056..49cfa3ada8 100644 --- a/src/ia32/codegen-ia32.cc +++ b/src/ia32/codegen-ia32.cc @@ -3595,7 +3595,7 @@ void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { void CodeGenerator::InstantiateBoilerplate(Handle boilerplate) { ASSERT(boilerplate->IsBoilerplate()); - // Use the fast case closure allocation code that allocated in new + // Use the fast case closure allocation code that allocates in new // space for nested functions that don't need literals cloning. if (scope()->is_function_scope() && boilerplate->NumberOfLiterals() == 0) { FastNewClosureStub stub; diff --git a/src/objects.h b/src/objects.h index 1545bbf198..0750525ffc 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1804,7 +1804,7 @@ class DescriptorArray: public FixedArray { } static int ToDetailsIndex(int descriptor_number) { - return( descriptor_number << 1) + 1; + return (descriptor_number << 1) + 1; } static int ToValueIndex(int descriptor_number) { diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc index 81e5dae648..32bd3450fb 100644 --- a/src/x64/stub-cache-x64.cc +++ b/src/x64/stub-cache-x64.cc @@ -956,8 +956,24 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); // Check that the cell contains the same function. - __ Cmp(rdi, Handle(function)); - __ j(not_equal, &miss); + if (Heap::InNewSpace(function)) { + // We can't embed a pointer to a function in new space so we have + // to verify that the shared function info is unchanged. This has + // the nice side effect that multiple closures based on the same + // function can all use this call IC. Before we load through the + // function, we have to verify that it still is a function. + __ JumpIfSmi(rdi, &miss); + __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); + __ j(not_equal, &miss); + + // Check the shared function info. Make sure it hasn't changed. + __ Move(rcx, Handle(function->shared())); + __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rcx); + __ j(not_equal, &miss); + } else { + __ Cmp(rdi, Handle(function)); + __ j(not_equal, &miss); + } // Patch the receiver on the stack with the global proxy. if (object->IsGlobalObject()) {