diff options
Diffstat (limited to 'deps/v8/src/mips/stub-cache-mips.cc')
-rw-r--r-- | deps/v8/src/mips/stub-cache-mips.cc | 164 |
1 files changed, 109 insertions, 55 deletions
diff --git a/deps/v8/src/mips/stub-cache-mips.cc b/deps/v8/src/mips/stub-cache-mips.cc index 294bc0a074..18a5f5f7e1 100644 --- a/deps/v8/src/mips/stub-cache-mips.cc +++ b/deps/v8/src/mips/stub-cache-mips.cc @@ -429,8 +429,10 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, // a0 : value. Label exit; // Check that the map of the object hasn't changed. + CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS + : REQUIRE_EXACT_MAP; __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label, - DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); + DO_SMI_CHECK, mode); // Perform global security token check if needed. if (object->IsJSGlobalProxy()) { @@ -563,6 +565,8 @@ static void PushInterceptorArguments(MacroAssembler* masm, __ Push(scratch, receiver, holder); __ lw(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); __ push(scratch); + __ li(scratch, Operand(ExternalReference::isolate_address())); + __ push(scratch); } @@ -577,7 +581,7 @@ static void CompileCallLoadPropertyWithInterceptor( ExternalReference ref = ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), masm->isolate()); - __ PrepareCEntryArgs(5); + __ PrepareCEntryArgs(6); __ PrepareCEntryFunction(ref); CEntryStub stub(1); @@ -585,10 +589,10 @@ static void CompileCallLoadPropertyWithInterceptor( } -static const int kFastApiCallArguments = 3; +static const int kFastApiCallArguments = 4; -// Reserves space for the extra arguments to FastHandleApiCall in the +// Reserves space for the extra arguments to API function in the // caller's frame. // // These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. @@ -614,7 +618,8 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm, // -- sp[0] : holder (set by CheckPrototypes) // -- sp[4] : callee JS function // -- sp[8] : call data - // -- sp[12] : last JS argument + // -- sp[12] : isolate + // -- sp[16] : last JS argument // -- ... // -- sp[(argc + 3) * 4] : first JS argument // -- sp[(argc + 4) * 4] : receiver @@ -624,7 +629,7 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm, __ LoadHeapObject(t1, function); __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset)); - // Pass the additional arguments FastHandleApiCall expects. + // Pass the additional arguments. Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); Handle<Object> call_data(api_call_info->data()); if (masm->isolate()->heap()->InNewSpace(*call_data)) { @@ -634,14 +639,17 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm, __ li(t2, call_data); } - // Store JS function and call data. + __ li(t3, Operand(ExternalReference::isolate_address())); + // Store JS function, call data and isolate. __ sw(t1, MemOperand(sp, 1 * kPointerSize)); __ sw(t2, MemOperand(sp, 2 * kPointerSize)); + __ sw(t3, MemOperand(sp, 3 * kPointerSize)); - // a2 points to call data as expected by Arguments - // (refer to layout above). - __ Addu(a2, sp, Operand(2 * kPointerSize)); + // Prepare arguments. + __ Addu(a2, sp, Operand(3 * kPointerSize)); + // Allocate the v8::Arguments structure in the arguments' space since + // it's not controlled by GC. const int kApiStackSpace = 4; FrameScope frame_scope(masm, StackFrame::MANUAL); @@ -656,9 +664,9 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm, // Arguments is built at sp + 1 (sp is a reserved spot for ra). __ Addu(a1, sp, kPointerSize); - // v8::Arguments::implicit_args = data + // v8::Arguments::implicit_args_ __ sw(a2, MemOperand(a1, 0 * kPointerSize)); - // v8::Arguments::values = last argument + // v8::Arguments::values_ __ Addu(t0, a2, Operand(argc * kPointerSize)); __ sw(t0, MemOperand(a1, 1 * kPointerSize)); // v8::Arguments::length_ = argc @@ -836,7 +844,7 @@ class CallInterceptorCompiler BASE_EMBEDDED { ExternalReference( IC_Utility(IC::kLoadPropertyWithInterceptorForCall), masm->isolate()), - 5); + 6); // Restore the name_ register. __ pop(name_); // Leave the internal frame. @@ -1168,9 +1176,8 @@ void StubCompiler::GenerateLoadConstant(Handle<JSObject> object, __ JumpIfSmi(receiver, miss, scratch1); // Check that the maps haven't changed. - Register reg = - CheckPrototypes(object, receiver, holder, - scratch1, scratch2, scratch3, name, miss); + CheckPrototypes(object, receiver, holder, + scratch1, scratch2, scratch3, name, miss); // Return the constant value. __ LoadHeapObject(v0, value); @@ -1205,7 +1212,13 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, } else { __ li(scratch3, Handle<Object>(callback->data())); } - __ Push(reg, scratch3, name_reg); + __ Subu(sp, sp, 4 * kPointerSize); + __ sw(reg, MemOperand(sp, 3 * kPointerSize)); + __ sw(scratch3, MemOperand(sp, 2 * kPointerSize)); + __ li(scratch3, Operand(ExternalReference::isolate_address())); + __ sw(scratch3, MemOperand(sp, 1 * kPointerSize)); + __ sw(name_reg, MemOperand(sp, 0 * kPointerSize)); + __ mov(a2, scratch2); // Saved in case scratch2 == a1. __ mov(a1, sp); // a1 (first argument - see note below) = Handle<String> @@ -1224,7 +1237,7 @@ void StubCompiler::GenerateLoadCallback(Handle<JSObject> object, // a2 (second argument - see note above) = AccessorInfo& __ Addu(a2, sp, kPointerSize); - const int kStackUnwindSpace = 4; + const int kStackUnwindSpace = 5; Address getter_address = v8::ToCData<Address>(callback->getter()); ApiFunction fun(getter_address); ExternalReference ref = @@ -1274,12 +1287,19 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, name, miss); ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); + // Preserve the receiver register explicitly whenever it is different from + // the holder and it is needed should the interceptor return without any + // result. The CALLBACKS case needs the receiver to be passed into C++ code, + // the FIELD case might cause a miss during the prototype check. + bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); + bool must_preserve_receiver_reg = !receiver.is(holder_reg) && + (lookup->type() == CALLBACKS || must_perfrom_prototype_check); + // Save necessary data before invoking an interceptor. // Requires a frame to make GC aware of pushed pointers. { FrameScope frame_scope(masm(), StackFrame::INTERNAL); - if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { - // CALLBACKS case needs a receiver to be passed into C++ callback. + if (must_preserve_receiver_reg) { __ Push(receiver, holder_reg, name_reg); } else { __ Push(holder_reg, name_reg); @@ -1303,14 +1323,14 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, __ bind(&interceptor_failed); __ pop(name_reg); __ pop(holder_reg); - if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { + if (must_preserve_receiver_reg) { __ pop(receiver); } // Leave the internal frame. } // Check that the maps from interceptor's holder to lookup's holder // haven't changed. And load lookup's holder into |holder| register. - if (*interceptor_holder != lookup->holder()) { + if (must_perfrom_prototype_check) { holder_reg = CheckPrototypes(interceptor_holder, holder_reg, Handle<JSObject>(lookup->holder()), @@ -1340,24 +1360,17 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, // Important invariant in CALLBACKS case: the code above must be // structured to never clobber |receiver| register. __ li(scratch2, callback); - // holder_reg is either receiver or scratch1. - if (!receiver.is(holder_reg)) { - ASSERT(scratch1.is(holder_reg)); - __ Push(receiver, holder_reg); - __ lw(scratch3, - FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); - __ Push(scratch3, scratch2, name_reg); - } else { - __ push(receiver); - __ lw(scratch3, - FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); - __ Push(holder_reg, scratch3, scratch2, name_reg); - } + + __ Push(receiver, holder_reg); + __ lw(scratch3, + FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); + __ li(scratch1, Operand(ExternalReference::isolate_address())); + __ Push(scratch3, scratch1, scratch2, name_reg); ExternalReference ref = ExternalReference(IC_Utility(IC::kLoadCallbackProperty), masm()->isolate()); - __ TailCallExternalReference(ref, 5, 1); + __ TailCallExternalReference(ref, 6, 1); } } else { // !compile_followup_inline // Call the runtime system to load the interceptor. @@ -1370,7 +1383,7 @@ void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, ExternalReference ref = ExternalReference( IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), masm()->isolate()); - __ TailCallExternalReference(ref, 5, 1); + __ TailCallExternalReference(ref, 6, 1); } } @@ -1737,14 +1750,14 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall( // expensive shift first, and use an offset later on. __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize); __ Addu(elements, elements, t1); - __ lw(v0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); + __ lw(v0, FieldMemOperand(elements, FixedArray::kHeaderSize)); __ Branch(&call_builtin, eq, v0, Operand(t2)); // Set the array's length. __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); // Fill with the hole. - __ sw(t2, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); + __ sw(t2, FieldMemOperand(elements, FixedArray::kHeaderSize)); __ Drop(argc + 1); __ Ret(); @@ -3371,6 +3384,45 @@ static bool IsElementTypeSigned(ElementsKind elements_kind) { } +static void GenerateSmiKeyCheck(MacroAssembler* masm, + Register key, + Register scratch0, + Register scratch1, + FPURegister double_scratch0, + Label* fail) { + if (CpuFeatures::IsSupported(FPU)) { + CpuFeatures::Scope scope(FPU); + Label key_ok; + // Check for smi or a smi inside a heap number. We convert the heap + // number and check if the conversion is exact and fits into the smi + // range. + __ JumpIfSmi(key, &key_ok); + __ CheckMap(key, + scratch0, + Heap::kHeapNumberMapRootIndex, + fail, + DONT_DO_SMI_CHECK); + __ ldc1(double_scratch0, FieldMemOperand(key, HeapNumber::kValueOffset)); + __ EmitFPUTruncate(kRoundToZero, + double_scratch0, + double_scratch0, + scratch0, + scratch1, + kCheckForInexactConversion); + + __ Branch(fail, ne, scratch1, Operand(zero_reg)); + + __ mfc1(scratch0, double_scratch0); + __ SmiTagCheckOverflow(key, scratch0, scratch1); + __ BranchOnOverflow(fail, scratch1); + __ bind(&key_ok); + } else { + // Check that the key is a smi. + __ JumpIfNotSmi(key, fail); + } +} + + void KeyedLoadStubCompiler::GenerateLoadExternalArray( MacroAssembler* masm, ElementsKind elements_kind) { @@ -3387,8 +3439,8 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(key, &miss_force_generic); + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key, t0, t1, f2, &miss_force_generic); __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); // a3: elements array @@ -3496,7 +3548,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( CpuFeatures::Scope scope(FPU); __ mtc1(value, f0); __ cvt_d_w(f0, f0); - __ sdc1(f0, MemOperand(v0, HeapNumber::kValueOffset - kHeapObjectTag)); + __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); __ Ret(); } else { Register dst1 = t2; @@ -3544,7 +3596,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( __ Cvt_d_uw(f0, value, f22); - __ sdc1(f0, MemOperand(v0, HeapNumber::kValueOffset - kHeapObjectTag)); + __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); __ Ret(); } else { @@ -3598,7 +3650,7 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray( __ AllocateHeapNumber(v0, t3, t5, t6, &slow); // The float (single) value is already in fpu reg f0 (if we use float). __ cvt_d_s(f0, f0); - __ sdc1(f0, MemOperand(v0, HeapNumber::kValueOffset - kHeapObjectTag)); + __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); __ Ret(); } else { // Allocate a HeapNumber for the result. Don't use a0 and a1 as @@ -3726,8 +3778,8 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray( // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(key, &miss_force_generic); + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key, t0, t1, f2, &miss_force_generic); __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); @@ -4106,9 +4158,8 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(a0, &miss_force_generic, at, USE_DELAY_SLOT); - // The delay slot can be safely used here, a1 is an object pointer. + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, a0, t0, t1, f2, &miss_force_generic); // Get the elements array. __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset)); @@ -4158,8 +4209,8 @@ void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(key_reg, &miss_force_generic); + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic); // Get the elements array. __ lw(elements_reg, @@ -4228,13 +4279,12 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement( Register elements_reg = a3; Register length_reg = t1; Register scratch2 = t2; - Register scratch3 = t3; // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - // Check that the key is a smi. - __ JumpIfNotSmi(key_reg, &miss_force_generic); + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic); if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { __ JumpIfNotSmi(value_reg, &transition_elements_kind); @@ -4400,7 +4450,9 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( // This stub is meant to be tail-jumped to, the receiver must already // have been verified by the caller to not be a smi. - __ JumpIfNotSmi(key_reg, &miss_force_generic); + + // Check that the key is a smi or a heap number convertible to a smi. + GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic); __ lw(elements_reg, FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); @@ -4492,6 +4544,8 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( // Increment the length of the array. __ li(length_reg, Operand(Smi::FromInt(1))); __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); + __ lw(elements_reg, + FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); __ jmp(&finish_store); __ bind(&check_capacity); |