Index: src/mips/stub-cache-mips.cc |
=================================================================== |
--- src/mips/stub-cache-mips.cc (revision 11348) |
+++ src/mips/stub-cache-mips.cc (working copy) |
@@ -565,6 +565,8 @@ |
__ Push(scratch, receiver, holder); |
__ lw(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); |
__ push(scratch); |
+ __ li(scratch, Operand(ExternalReference::isolate_address())); |
+ __ push(scratch); |
} |
@@ -579,7 +581,7 @@ |
ExternalReference ref = |
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), |
masm->isolate()); |
- __ PrepareCEntryArgs(5); |
+ __ PrepareCEntryArgs(6); |
__ PrepareCEntryFunction(ref); |
CEntryStub stub(1); |
@@ -587,10 +589,10 @@ |
} |
-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. |
@@ -616,7 +618,8 @@ |
// -- 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 |
@@ -626,7 +629,7 @@ |
__ 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)) { |
@@ -636,14 +639,17 @@ |
__ 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); |
@@ -658,9 +664,9 @@ |
// 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 |
@@ -838,7 +844,7 @@ |
ExternalReference( |
IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
masm->isolate()), |
- 5); |
+ 6); |
// Restore the name_ register. |
__ pop(name_); |
// Leave the internal frame. |
@@ -1207,7 +1213,13 @@ |
} 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> |
@@ -1226,7 +1238,7 @@ |
// 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 = |
@@ -1342,24 +1354,17 @@ |
// 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. |
@@ -1372,7 +1377,7 @@ |
ExternalReference ref = ExternalReference( |
IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), masm()->isolate()); |
- __ TailCallExternalReference(ref, 5, 1); |
+ __ TailCallExternalReference(ref, 6, 1); |
} |
} |
@@ -3373,6 +3378,45 @@ |
} |
+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) { |
@@ -3389,8 +3433,8 @@ |
// 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 |
@@ -3728,8 +3772,8 @@ |
// 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)); |
@@ -4108,9 +4152,8 @@ |
// 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)); |
@@ -4160,8 +4203,8 @@ |
// 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, |
@@ -4235,8 +4278,8 @@ |
// 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); |
@@ -4402,8 +4445,10 @@ |
// 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)); |