Index: src/ppc/code-stubs-ppc.cc |
diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc |
index d88077aefe1a9ddfd3798904b312747aaf9fd119..635a7fc9e6b0e067e348e94d2617bc68cf31b4cd 100644 |
--- a/src/ppc/code-stubs-ppc.cc |
+++ b/src/ppc/code-stubs-ppc.cc |
@@ -995,6 +995,60 @@ void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { |
} |
+static void ThrowPendingException(MacroAssembler* masm) { |
+ Isolate* isolate = masm->isolate(); |
+ |
+ ExternalReference pending_handler_context_address( |
+ Isolate::kPendingHandlerContextAddress, isolate); |
+ ExternalReference pending_handler_code_address( |
+ Isolate::kPendingHandlerCodeAddress, isolate); |
+ ExternalReference pending_handler_offset_address( |
+ Isolate::kPendingHandlerOffsetAddress, isolate); |
+ ExternalReference pending_handler_fp_address( |
+ Isolate::kPendingHandlerFPAddress, isolate); |
+ ExternalReference pending_handler_sp_address( |
+ Isolate::kPendingHandlerSPAddress, isolate); |
+ |
+ // Ask the runtime for help to determine the handler. This will set r3 to |
+ // contain the current pending exception, don't clobber it. |
+ ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate); |
+ { |
+ FrameScope scope(masm, StackFrame::MANUAL); |
+ __ PrepareCallCFunction(3, 0, r3); |
+ __ li(r3, Operand::Zero()); |
+ __ li(r4, Operand::Zero()); |
+ __ mov(r5, Operand(ExternalReference::isolate_address(isolate))); |
+ __ CallCFunction(find_handler, 3); |
+ } |
+ |
+ // Retrieve the handler context, SP and FP. |
+ __ mov(cp, Operand(pending_handler_context_address)); |
+ __ LoadP(cp, MemOperand(cp)); |
+ __ mov(sp, Operand(pending_handler_sp_address)); |
+ __ LoadP(sp, MemOperand(sp)); |
+ __ mov(fp, Operand(pending_handler_fp_address)); |
+ __ LoadP(fp, MemOperand(fp)); |
+ |
+ // If the handler is a JS frame, restore the context to the frame. |
+ // (kind == ENTRY) == (fp == 0) == (cp == 0), so we could test either fp |
+ // or cp. |
+ Label skip; |
+ __ cmpi(cp, Operand::Zero()); |
+ __ beq(&skip); |
+ __ StoreP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ __ bind(&skip); |
+ |
+ // Compute the handler entry address and jump to it. |
+ __ mov(r4, Operand(pending_handler_code_address)); |
+ __ LoadP(r4, MemOperand(r4)); |
+ __ mov(r5, Operand(pending_handler_offset_address)); |
+ __ LoadP(r5, MemOperand(r5)); |
+ __ addi(r4, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); // Code start |
+ __ add(ip, r4, r5); |
+ __ Jump(ip); |
+} |
+ |
+ |
void CEntryStub::Generate(MacroAssembler* masm) { |
// Called from JavaScript; parameters are on stack as if calling JS function. |
// r3: number of arguments including receiver |
@@ -1070,11 +1124,22 @@ void CEntryStub::Generate(MacroAssembler* masm) { |
// know where the return address is. The CEntryStub is unmovable, so |
// we can store the address on the stack to be able to find it again and |
// we never have to restore it, because it will not change. |
- Label after_call; |
- __ mov_label_addr(r0, &after_call); |
- __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); |
- __ Call(target); |
- __ bind(&after_call); |
+ // Compute the return address in lr to return to after the jump below. Pc is |
+ // already at '+ 8' from the current instruction but return is after three |
+ // instructions so add another 4 to pc to get the return address. |
+ { |
+ Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm); |
+ Label here; |
+ __ b(&here, SetLK); |
+ __ bind(&here); |
+ __ mflr(r8); |
+ |
+ // Constant used below is dependent on size of Call() macro instructions |
+ __ addi(r0, r8, Operand(20)); |
+ |
+ __ StoreP(r0, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize)); |
+ __ Call(target); |
+ } |
#if !ABI_RETURNS_OBJECT_PAIRS_IN_REGS |
// If return value is on the stack, pop it to registers. |
@@ -1099,13 +1164,13 @@ void CEntryStub::Generate(MacroAssembler* masm) { |
__ CompareRoot(r3, Heap::kExceptionRootIndex); |
__ beq(&exception_returned); |
- ExternalReference pending_exception_address(Isolate::kPendingExceptionAddress, |
- isolate()); |
- |
// Check that there is no pending exception, otherwise we |
// should have returned the exception sentinel. |
if (FLAG_debug_code) { |
Label okay; |
+ ExternalReference pending_exception_address( |
+ Isolate::kPendingExceptionAddress, isolate()); |
+ |
__ mov(r5, Operand(pending_exception_address)); |
__ LoadP(r5, MemOperand(r5)); |
__ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
@@ -1126,25 +1191,7 @@ void CEntryStub::Generate(MacroAssembler* masm) { |
// Handling of exception. |
__ bind(&exception_returned); |
- // Retrieve the pending exception. |
- __ mov(r5, Operand(pending_exception_address)); |
- __ LoadP(r3, MemOperand(r5)); |
- |
- // Clear the pending exception. |
- __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); |
- __ StoreP(r6, MemOperand(r5)); |
- |
- // Special handling of termination exceptions which are uncatchable |
- // by javascript code. |
- Label throw_termination_exception; |
- __ CompareRoot(r3, Heap::kTerminationExceptionRootIndex); |
- __ beq(&throw_termination_exception); |
- |
- // Handle normal exception. |
- __ Throw(r3); |
- |
- __ bind(&throw_termination_exception); |
- __ ThrowUncatchable(r3); |
+ ThrowPendingException(masm); |
} |
@@ -2364,18 +2411,9 @@ void RegExpExecStub::Generate(MacroAssembler* masm) { |
__ cmp(r3, r4); |
__ beq(&runtime); |
- __ StoreP(r4, MemOperand(r5, 0)); // Clear pending exception. |
- |
- // Check if the exception is a termination. If so, throw as uncatchable. |
- __ CompareRoot(r3, Heap::kTerminationExceptionRootIndex); |
- |
- Label termination_exception; |
- __ beq(&termination_exception); |
- |
- __ Throw(r3); |
- |
- __ bind(&termination_exception); |
- __ ThrowUncatchable(r3); |
+ // For exception, throw the exception again. |
+ __ EnterExitFrame(false); |
+ ThrowPendingException(masm); |
__ bind(&failure); |
// For failure and exception return null. |
@@ -2843,6 +2881,7 @@ void CallIC_ArrayStub::Generate(MacroAssembler* masm) { |
__ bne(&miss); |
__ mr(r5, r7); |
+ __ mr(r6, r4); |
ArrayConstructorStub stub(masm->isolate(), arg_count()); |
__ TailCallStub(&stub); |
@@ -4822,6 +4861,7 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
// -- r3 : argc (only if argument_count() == ANY) |
// -- r4 : constructor |
// -- r5 : AllocationSite or undefined |
+ // -- r6 : original constructor |
// -- sp[0] : return address |
// -- sp[4] : last argument |
// ----------------------------------- |
@@ -4842,6 +4882,10 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
__ AssertUndefinedOrAllocationSite(r5, r7); |
} |
+ Label subclassing; |
+ __ cmp(r6, r4); |
+ __ bne(&subclassing); |
+ |
Label no_info; |
// Get the elements kind and case on that. |
__ CompareRoot(r5, Heap::kUndefinedValueRootIndex); |
@@ -4855,6 +4899,27 @@ void ArrayConstructorStub::Generate(MacroAssembler* masm) { |
__ bind(&no_info); |
GenerateDispatchToArrayStub(masm, DISABLE_ALLOCATION_SITES); |
+ |
+ __ bind(&subclassing); |
+ __ push(r4); |
+ __ push(r6); |
+ |
+ // Adjust argc. |
+ switch (argument_count()) { |
+ case ANY: |
+ case MORE_THAN_ONE: |
+ __ addi(r3, r3, Operand(2)); |
+ break; |
+ case NONE: |
+ __ li(r3, Operand(2)); |
+ break; |
+ case ONE: |
+ __ li(r3, Operand(3)); |
+ break; |
+ } |
+ |
+ __ JumpToExternalReference( |
+ ExternalReference(Runtime::kArrayConstructorWithSubclassing, isolate())); |
} |
@@ -5017,7 +5082,6 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm, |
} |
Label promote_scheduled_exception; |
- Label exception_handled; |
Label delete_allocated_handles; |
Label leave_exit_frame; |
Label return_value_loaded; |
@@ -5039,15 +5103,8 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm, |
__ cmp(r15, r0); |
__ bne(&delete_allocated_handles); |
- // Check if the function scheduled an exception. |
+ // Leave the API exit frame. |
__ bind(&leave_exit_frame); |
- __ LoadRoot(r14, Heap::kTheHoleValueRootIndex); |
- __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate))); |
- __ LoadP(r15, MemOperand(r15)); |
- __ cmp(r14, r15); |
- __ bne(&promote_scheduled_exception); |
- __ bind(&exception_handled); |
- |
bool restore_context = context_restore_operand != NULL; |
if (restore_context) { |
__ LoadP(cp, *context_restore_operand); |
@@ -5059,15 +5116,19 @@ static void CallApiFunctionAndReturn(MacroAssembler* masm, |
__ mov(r14, Operand(stack_space)); |
} |
__ LeaveExitFrame(false, r14, !restore_context, stack_space_operand != NULL); |
+ |
+ // Check if the function scheduled an exception. |
+ __ LoadRoot(r14, Heap::kTheHoleValueRootIndex); |
+ __ mov(r15, Operand(ExternalReference::scheduled_exception_address(isolate))); |
+ __ LoadP(r15, MemOperand(r15)); |
+ __ cmp(r14, r15); |
+ __ bne(&promote_scheduled_exception); |
+ |
__ blr(); |
+ // Re-throw by promoting a scheduled exception. |
__ bind(&promote_scheduled_exception); |
- { |
- FrameScope frame(masm, StackFrame::INTERNAL); |
- __ CallExternalReference( |
- ExternalReference(Runtime::kPromoteScheduledException, isolate), 0); |
- } |
- __ jmp(&exception_handled); |
+ __ TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
// HandleScope limit has changed. Delete allocated extensions. |
__ bind(&delete_allocated_handles); |