| Index: src/mips/stub-cache-mips.cc
|
| ===================================================================
|
| --- src/mips/stub-cache-mips.cc (revision 9531)
|
| +++ src/mips/stub-cache-mips.cc (working copy)
|
| @@ -554,9 +554,10 @@
|
| }
|
|
|
|
|
| -static MaybeObject* GenerateFastApiDirectCall(MacroAssembler* masm,
|
| - const CallOptimization& optimization,
|
| - int argc) {
|
| +static MaybeObject* GenerateFastApiDirectCall(
|
| + MacroAssembler* masm,
|
| + const CallOptimization& optimization,
|
| + int argc) {
|
| // ----------- S t a t e -------------
|
| // -- sp[0] : holder (set by CheckPrototypes)
|
| // -- sp[4] : callee js function
|
| @@ -595,6 +596,7 @@
|
|
|
| const int kApiStackSpace = 4;
|
|
|
| + FrameScope frame_scope(masm, StackFrame::MANUAL);
|
| __ EnterExitFrame(false, kApiStackSpace);
|
|
|
| // NOTE: the O32 abi requires a0 to hold a special pointer when returning a
|
| @@ -626,6 +628,7 @@
|
| ExternalReference(&fun,
|
| ExternalReference::DIRECT_API_CALL,
|
| masm->isolate());
|
| + AllowExternalCallThatCantCauseGC scope(masm);
|
| return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
|
| }
|
|
|
| @@ -804,7 +807,7 @@
|
| miss_label);
|
|
|
| // Call a runtime function to load the interceptor property.
|
| - __ EnterInternalFrame();
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
| // Save the name_ register across the call.
|
| __ push(name_);
|
|
|
| @@ -822,7 +825,8 @@
|
|
|
| // Restore the name_ register.
|
| __ pop(name_);
|
| - __ LeaveInternalFrame();
|
| +
|
| + // Leave the internal frame.
|
| }
|
|
|
| void LoadWithInterceptor(MacroAssembler* masm,
|
| @@ -831,19 +835,20 @@
|
| JSObject* holder_obj,
|
| Register scratch,
|
| Label* interceptor_succeeded) {
|
| - __ EnterInternalFrame();
|
| + {
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
|
|
| - __ Push(holder, name_);
|
| + __ Push(holder, name_);
|
|
|
| - CompileCallLoadPropertyWithInterceptor(masm,
|
| - receiver,
|
| - holder,
|
| - name_,
|
| - holder_obj);
|
| + CompileCallLoadPropertyWithInterceptor(masm,
|
| + receiver,
|
| + holder,
|
| + name_,
|
| + holder_obj);
|
|
|
| - __ pop(name_); // Restore the name.
|
| - __ pop(receiver); // Restore the holder.
|
| - __ LeaveInternalFrame();
|
| + __ pop(name_); // Restore the name.
|
| + __ pop(receiver); // Restore the holder.
|
| + }
|
|
|
| // If interceptor returns no-result sentinel, call the constant function.
|
| __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
|
| @@ -1256,7 +1261,9 @@
|
|
|
| const int kApiStackSpace = 1;
|
|
|
| + FrameScope frame_scope(masm(), StackFrame::MANUAL);
|
| __ EnterExitFrame(false, kApiStackSpace);
|
| +
|
| // Create AccessorInfo instance on the stack above the exit frame with
|
| // scratch2 (internal::Object **args_) as the data.
|
| __ sw(a2, MemOperand(sp, kPointerSize));
|
| @@ -1317,41 +1324,43 @@
|
|
|
| // Save necessary data before invoking an interceptor.
|
| // Requires a frame to make GC aware of pushed pointers.
|
| - __ EnterInternalFrame();
|
| + {
|
| + 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.
|
| - __ Push(receiver, holder_reg, name_reg);
|
| - } else {
|
| - __ Push(holder_reg, name_reg);
|
| - }
|
| + if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
|
| + // CALLBACKS case needs a receiver to be passed into C++ callback.
|
| + __ Push(receiver, holder_reg, name_reg);
|
| + } else {
|
| + __ Push(holder_reg, name_reg);
|
| + }
|
|
|
| - // Invoke an interceptor. Note: map checks from receiver to
|
| - // interceptor's holder has been compiled before (see a caller
|
| - // of this method).
|
| - CompileCallLoadPropertyWithInterceptor(masm(),
|
| - receiver,
|
| - holder_reg,
|
| - name_reg,
|
| - interceptor_holder);
|
| + // Invoke an interceptor. Note: map checks from receiver to
|
| + // interceptor's holder has been compiled before (see a caller
|
| + // of this method).
|
| + CompileCallLoadPropertyWithInterceptor(masm(),
|
| + receiver,
|
| + holder_reg,
|
| + name_reg,
|
| + interceptor_holder);
|
|
|
| - // Check if interceptor provided a value for property. If it's
|
| - // the case, return immediately.
|
| - Label interceptor_failed;
|
| - __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
|
| - __ Branch(&interceptor_failed, eq, v0, Operand(scratch1));
|
| - __ LeaveInternalFrame();
|
| - __ Ret();
|
| + // Check if interceptor provided a value for property. If it's
|
| + // the case, return immediately.
|
| + Label interceptor_failed;
|
| + __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex);
|
| + __ Branch(&interceptor_failed, eq, v0, Operand(scratch1));
|
| + frame_scope.GenerateLeaveFrame();
|
| + __ Ret();
|
|
|
| - __ bind(&interceptor_failed);
|
| - __ pop(name_reg);
|
| - __ pop(holder_reg);
|
| - if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
|
| - __ pop(receiver);
|
| + __ bind(&interceptor_failed);
|
| + __ pop(name_reg);
|
| + __ pop(holder_reg);
|
| + if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
|
| + __ pop(receiver);
|
| + }
|
| +
|
| + // Leave the internal frame.
|
| }
|
|
|
| - __ LeaveInternalFrame();
|
| -
|
| // 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()) {
|
| @@ -1605,8 +1614,8 @@
|
| __ Addu(end_elements, elements, end_elements);
|
| const int kEndElementsOffset =
|
| FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize;
|
| - __ sw(t0, MemOperand(end_elements, kEndElementsOffset));
|
| - __ Addu(end_elements, end_elements, kPointerSize);
|
| + __ Addu(end_elements, end_elements, kEndElementsOffset);
|
| + __ sw(t0, MemOperand(end_elements));
|
|
|
| // Check for a smi.
|
| __ JumpIfNotSmi(t0, &with_write_barrier);
|
| @@ -2551,7 +2560,12 @@
|
| ? CALL_AS_FUNCTION
|
| : CALL_AS_METHOD;
|
| if (V8::UseCrankshaft()) {
|
| - UNIMPLEMENTED_MIPS();
|
| + // TODO(kasperl): For now, we always call indirectly through the
|
| + // code field in the function to allow recompilation to take effect
|
| + // without changing any of the call sites.
|
| + __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
|
| + __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION,
|
| + NullCallWrapper(), call_kind);
|
| } else {
|
| __ InvokeCode(code, expected, arguments(), RelocInfo::CODE_TARGET,
|
| JUMP_FUNCTION, call_kind);
|
| @@ -3457,6 +3471,7 @@
|
|
|
| case EXTERNAL_FLOAT_ELEMENTS:
|
| case EXTERNAL_DOUBLE_ELEMENTS:
|
| + case FAST_SMI_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| case FAST_DOUBLE_ELEMENTS:
|
| case DICTIONARY_ELEMENTS:
|
| @@ -3828,7 +3843,6 @@
|
| __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
|
|
| // Check that the index is in range.
|
| - __ SmiUntag(t0, key);
|
| __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset));
|
| // Unsigned comparison catches both negative and too-large values.
|
| __ Branch(&miss_force_generic, Ugreater_equal, key, Operand(t1));
|
| @@ -3836,7 +3850,6 @@
|
| // Handle both smis and HeapNumbers in the fast path. Go to the
|
| // runtime for all other kinds of values.
|
| // a3: external array.
|
| - // t0: key (integer).
|
|
|
| if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) {
|
| // Double to pixel conversion is only implemented in the runtime for now.
|
| @@ -3848,7 +3861,6 @@
|
| __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset));
|
|
|
| // a3: base pointer of external storage.
|
| - // t0: key (integer).
|
| // t1: value (integer).
|
|
|
| switch (elements_kind) {
|
| @@ -3865,33 +3877,36 @@
|
| __ mov(v0, t1); // Value is in range 0..255.
|
| __ bind(&done);
|
| __ mov(t1, v0);
|
| - __ addu(t8, a3, t0);
|
| +
|
| + __ srl(t8, key, 1);
|
| + __ addu(t8, a3, t8);
|
| __ sb(t1, MemOperand(t8, 0));
|
| }
|
| break;
|
| case EXTERNAL_BYTE_ELEMENTS:
|
| case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| - __ addu(t8, a3, t0);
|
| + __ srl(t8, key, 1);
|
| + __ addu(t8, a3, t8);
|
| __ sb(t1, MemOperand(t8, 0));
|
| break;
|
| case EXTERNAL_SHORT_ELEMENTS:
|
| case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| - __ sll(t8, t0, 1);
|
| - __ addu(t8, a3, t8);
|
| + __ addu(t8, a3, key);
|
| __ sh(t1, MemOperand(t8, 0));
|
| break;
|
| case EXTERNAL_INT_ELEMENTS:
|
| case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| - __ sll(t8, t0, 2);
|
| + __ sll(t8, key, 1);
|
| __ addu(t8, a3, t8);
|
| __ sw(t1, MemOperand(t8, 0));
|
| break;
|
| case EXTERNAL_FLOAT_ELEMENTS:
|
| // Perform int-to-float conversion and store to memory.
|
| + __ SmiUntag(t0, key);
|
| StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4);
|
| break;
|
| case EXTERNAL_DOUBLE_ELEMENTS:
|
| - __ sll(t8, t0, 3);
|
| + __ sll(t8, key, 2);
|
| __ addu(a3, a3, t8);
|
| // a3: effective address of the double element
|
| FloatingPointHelper::Destination destination;
|
| @@ -3921,12 +3936,11 @@
|
| }
|
|
|
| // Entry registers are intact, a0 holds the value which is the return value.
|
| - __ mov(v0, value);
|
| + __ mov(v0, a0);
|
| __ Ret();
|
|
|
| if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
|
| // a3: external array.
|
| - // t0: index (integer).
|
| __ bind(&check_heap_number);
|
| __ GetObjectType(value, t1, t2);
|
| __ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE));
|
| @@ -3934,7 +3948,6 @@
|
| __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset));
|
|
|
| // a3: base pointer of external storage.
|
| - // t0: key (integer).
|
|
|
| // The WebGL specification leaves the behavior of storing NaN and
|
| // +/-Infinity into integer arrays basically undefined. For more
|
| @@ -3947,11 +3960,11 @@
|
|
|
| if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
|
| __ cvt_s_d(f0, f0);
|
| - __ sll(t8, t0, 2);
|
| + __ sll(t8, key, 1);
|
| __ addu(t8, a3, t8);
|
| __ swc1(f0, MemOperand(t8, 0));
|
| } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
|
| - __ sll(t8, t0, 3);
|
| + __ sll(t8, key, 2);
|
| __ addu(t8, a3, t8);
|
| __ sdc1(f0, MemOperand(t8, 0));
|
| } else {
|
| @@ -3960,18 +3973,18 @@
|
| switch (elements_kind) {
|
| case EXTERNAL_BYTE_ELEMENTS:
|
| case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| - __ addu(t8, a3, t0);
|
| + __ srl(t8, key, 1);
|
| + __ addu(t8, a3, t8);
|
| __ sb(t3, MemOperand(t8, 0));
|
| break;
|
| case EXTERNAL_SHORT_ELEMENTS:
|
| case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| - __ sll(t8, t0, 1);
|
| - __ addu(t8, a3, t8);
|
| + __ addu(t8, a3, key);
|
| __ sh(t3, MemOperand(t8, 0));
|
| break;
|
| case EXTERNAL_INT_ELEMENTS:
|
| case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| - __ sll(t8, t0, 2);
|
| + __ sll(t8, key, 1);
|
| __ addu(t8, a3, t8);
|
| __ sw(t3, MemOperand(t8, 0));
|
| break;
|
| @@ -3989,7 +4002,7 @@
|
|
|
| // Entry registers are intact, a0 holds the value
|
| // which is the return value.
|
| - __ mov(v0, value);
|
| + __ mov(v0, a0);
|
| __ Ret();
|
| } else {
|
| // FPU is not available, do manual conversions.
|
| @@ -4044,13 +4057,13 @@
|
| __ or_(t3, t7, t6);
|
|
|
| __ bind(&done);
|
| - __ sll(t9, a1, 2);
|
| + __ sll(t9, key, 1);
|
| __ addu(t9, a2, t9);
|
| __ sw(t3, MemOperand(t9, 0));
|
|
|
| // Entry registers are intact, a0 holds the value which is the return
|
| // value.
|
| - __ mov(v0, value);
|
| + __ mov(v0, a0);
|
| __ Ret();
|
|
|
| __ bind(&nan_or_infinity_or_zero);
|
| @@ -4068,6 +4081,7 @@
|
| // t8: effective address of destination element.
|
| __ sw(t4, MemOperand(t8, 0));
|
| __ sw(t3, MemOperand(t8, Register::kSizeInBytes));
|
| + __ mov(v0, a0);
|
| __ Ret();
|
| } else {
|
| bool is_signed_type = IsElementTypeSigned(elements_kind);
|
| @@ -4130,18 +4144,18 @@
|
| switch (elements_kind) {
|
| case EXTERNAL_BYTE_ELEMENTS:
|
| case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| - __ addu(t8, a3, t0);
|
| + __ srl(t8, key, 1);
|
| + __ addu(t8, a3, t8);
|
| __ sb(t3, MemOperand(t8, 0));
|
| break;
|
| case EXTERNAL_SHORT_ELEMENTS:
|
| case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| - __ sll(t8, t0, 1);
|
| - __ addu(t8, a3, t8);
|
| + __ addu(t8, a3, key);
|
| __ sh(t3, MemOperand(t8, 0));
|
| break;
|
| case EXTERNAL_INT_ELEMENTS:
|
| case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| - __ sll(t8, t0, 2);
|
| + __ sll(t8, key, 1);
|
| __ addu(t8, a3, t8);
|
| __ sw(t3, MemOperand(t8, 0));
|
| break;
|
|
|