Chromium Code Reviews| Index: src/mips/codegen-mips.cc |
| =================================================================== |
| --- src/mips/codegen-mips.cc (revision 4259) |
| +++ src/mips/codegen-mips.cc (working copy) |
| @@ -92,7 +92,7 @@ |
| // ----------------------------------------------------------------------------- |
| -// CodeGenerator implementation |
| +// CodeGenerator implementation. |
| CodeGenerator::CodeGenerator(MacroAssembler* masm) |
| : deferred_(8), |
| @@ -150,6 +150,7 @@ |
| VirtualFrame::SpilledScope spilled_scope; |
| if (scope()->num_heap_slots() > 0) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| { |
| @@ -173,6 +174,7 @@ |
| // context. |
| if (scope()->arguments() != NULL) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| // Generate code to 'execute' declarations and initialize functions |
| @@ -191,6 +193,7 @@ |
| if (FLAG_trace) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| // Compile the body of the function in a vanilla state. Don't |
| @@ -204,6 +207,7 @@ |
| is_builtin ? FLAG_trace_builtin_calls : FLAG_trace_calls; |
| if (should_trace) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| #endif |
| VisitStatementsAndSpill(info->function()->body()); |
| @@ -225,28 +229,18 @@ |
| function_return_.Bind(); |
| if (FLAG_trace) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| - // Add a label for checking the size of the code used for returning. |
| - Label check_exit_codesize; |
| - masm_->bind(&check_exit_codesize); |
| + // We don't check for the return code size. It may differ if the number of |
| + // arguments is too big. |
| + __ mov(sp, fp); |
| + __ lw(fp, MemOperand(sp, 0)); |
| + __ lw(ra, MemOperand(sp, 4)); |
| + __ addiu(sp, sp, 8); |
| - masm_->mov(sp, fp); |
| - masm_->lw(fp, MemOperand(sp, 0)); |
| - masm_->lw(ra, MemOperand(sp, 4)); |
| - masm_->addiu(sp, sp, 8); |
| - |
| - // Here we use masm_-> instead of the __ macro to avoid the code coverage |
| - // tool from instrumenting as we rely on the code size here. |
| - // TODO(MIPS): Should we be able to use more than 0x1ffe parameters? |
| - masm_->addiu(sp, sp, (scope()->num_parameters() + 1) * kPointerSize); |
| - masm_->Jump(ra); |
| - // The Jump automatically generates a nop in the branch delay slot. |
| - |
| - // Check that the size of the code used for returning matches what is |
| - // expected by the debugger. |
| - ASSERT_EQ(kJSReturnSequenceLength, |
| - masm_->InstructionsGeneratedSince(&check_exit_codesize)); |
| + __ Addu(sp, sp, Operand((scope()->num_parameters() + 1) * kPointerSize)); |
| + __ Ret(); |
| } |
| // Code generation state must be reset. |
| @@ -276,7 +270,7 @@ |
| UNIMPLEMENTED_MIPS(); |
| } else if (var != NULL) { |
| // The expression is a variable proxy that does not rewrite to a |
| - // property. Global variables are treated as named property references. |
| + // property. Global variables are treated as named property references. |
| if (var->is_global()) { |
| LoadGlobal(); |
| ref->set_type(Reference::NAMED); |
| @@ -286,6 +280,7 @@ |
| } |
| } else { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| } |
| @@ -317,9 +312,7 @@ |
| int index = slot->index(); |
| switch (slot->type()) { |
| case Slot::PARAMETER: |
| - UNIMPLEMENTED_MIPS(); |
| - return MemOperand(no_reg, 0); |
| - |
| + return frame_->ParameterAt(index); |
| case Slot::LOCAL: |
| return frame_->LocalAt(index); |
| @@ -388,10 +381,12 @@ |
| if (has_cc()) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| if (true_target.is_linked() || false_target.is_linked()) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| ASSERT(has_valid_frame()); |
| ASSERT(!has_cc()); |
| @@ -410,11 +405,13 @@ |
| VirtualFrame::SpilledScope spilled_scope; |
| if (slot->type() == Slot::LOOKUP) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } else { |
| - __ lw(a0, SlotOperand(slot, a2)); |
| - frame_->EmitPush(a0); |
| + __ lw(v0, SlotOperand(slot, a2)); |
| + frame_->EmitPush(v0); |
| if (slot->var()->mode() == Variable::CONST) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| } |
| } |
| @@ -424,12 +421,14 @@ |
| ASSERT(slot != NULL); |
| if (slot->type() == Slot::LOOKUP) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } else { |
| ASSERT(!slot->var()->is_dynamic()); |
| JumpTarget exit; |
| if (init_state == CONST_INIT) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| // We must execute the store. Storing a variable must keep the |
| @@ -446,6 +445,7 @@ |
| frame_->EmitPush(a0); |
| if (slot->type() == Slot::CONTEXT) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| // If we definitely did not jump over the assignment, we do not need |
| // to bind the exit label. Doing so can defeat peephole |
| @@ -466,7 +466,19 @@ |
| void CodeGenerator::VisitBlock(Block* node) { |
| - UNIMPLEMENTED_MIPS(); |
| +#ifdef DEBUG |
| + int original_height = frame_->height(); |
| +#endif |
| + VirtualFrame::SpilledScope spilled_scope; |
| + Comment cmnt(masm_, "[ Block"); |
| + CodeForStatementPosition(node); |
| + node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| + VisitStatementsAndSpill(node->statements()); |
| + if (node->break_target()->is_linked()) { |
| + node->break_target()->Bind(); |
| + } |
| + node->break_target()->Unuse(); |
| + ASSERT(!has_valid_frame() || frame_->height() == original_height); |
| } |
| @@ -483,7 +495,48 @@ |
| void CodeGenerator::VisitDeclaration(Declaration* node) { |
| - UNIMPLEMENTED_MIPS(); |
| +#ifdef DEBUG |
| + int original_height = frame_->height(); |
| +#endif |
| + VirtualFrame::SpilledScope spilled_scope; |
| + Comment cmnt(masm_, "[ Declaration"); |
| + Variable* var = node->proxy()->var(); |
| + ASSERT(var != NULL); // Must have been resolved. |
| + Slot* slot = var->slot(); |
| + |
| + // If it was not possible to allocate the variable at compile time, |
| + // we need to "declare" it at runtime to make sure it actually |
| + // exists in the local context. |
| + if (slot != NULL && slot->type() == Slot::LOOKUP) { |
| + UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| + return; |
| + } |
| + |
| + ASSERT(!var->is_global()); |
| + |
| + // If we have a function or a constant, we need to initialize the variable. |
| + Expression* val = NULL; |
| + if (node->mode() == Variable::CONST) { |
| + UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| + } else { |
| + val = node->fun(); // NULL if we don't have a function. |
| + } |
| + |
| + if (val != NULL) { |
| + { |
| + // Set initial value. |
| + Reference target(this, node->proxy()); |
| + LoadAndSpill(val); |
| + target.SetValue(NOT_CONST_INIT); |
| + // The reference is removed from the stack (preserving TOS) when |
| + // it goes out of scope. |
| + } |
| + // Get rid of the assigned value (declarations are statements). |
| + frame_->Drop(); |
| + } |
| + ASSERT(frame_->height() == original_height); |
| } |
| @@ -504,21 +557,25 @@ |
| void CodeGenerator::VisitEmptyStatement(EmptyStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitIfStatement(IfStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitContinueStatement(ContinueStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitBreakStatement(BreakStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| @@ -544,67 +601,80 @@ |
| void CodeGenerator::VisitWithEnterStatement(WithEnterStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitWithExitStatement(WithExitStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitWhileStatement(WhileStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitForStatement(ForStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitForInStatement(ForInStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitSharedFunctionInfoLiteral( |
| SharedFunctionInfoLiteral* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitConditional(Conditional* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| @@ -653,21 +723,25 @@ |
| void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| @@ -678,7 +752,7 @@ |
| VirtualFrame::SpilledScope spilled_scope; |
| Comment cmnt(masm_, "[ Assignment"); |
| - { Reference target(this, node->target()); |
| + { Reference target(this, node->target(), node->is_compound()); |
| if (target.is_illegal()) { |
| // Fool the virtual frame into thinking that we left the assignment's |
| // value on the frame. |
| @@ -693,6 +767,7 @@ |
| LoadAndSpill(node->value()); |
| } else { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| Variable* var = node->target()->AsVariableProxy()->AsVariable(); |
| @@ -718,11 +793,13 @@ |
| void CodeGenerator::VisitThrow(Throw* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitProperty(Property* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| @@ -752,22 +829,19 @@ |
| if (var != NULL && var->is_possibly_eval()) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } else if (var != NULL && !var->is_this() && var->is_global()) { |
| - // ---------------------------------- |
| - // JavaScript example: 'foo(1, 2, 3)' // foo is global |
| - // ---------------------------------- |
| + // ----------------------------------------------------- |
| + // JavaScript example: 'foo(1, 2, 3)' // foo is global. |
| + // ----------------------------------------------------- |
| - int arg_count = args->length(); |
| - |
| - // We need sp to be 8 bytes aligned when calling the stub. |
| - __ SetupAlignedCall(t0, arg_count); |
| - |
| // Pass the global object as the receiver and let the IC stub |
| // patch the stack to use the global proxy as 'this' in the |
| // invoked function. |
| LoadGlobal(); |
| // Load the arguments. |
| + int arg_count = args->length(); |
| for (int i = 0; i < arg_count; i++) { |
| LoadAndSpill(args->at(i)); |
| } |
| @@ -779,7 +853,6 @@ |
| CodeForSourcePosition(node->position()); |
| frame_->CallCodeObject(stub, RelocInfo::CODE_TARGET_CONTEXT, |
| arg_count + 1); |
| - __ ReturnFromAlignedCall(); |
| __ lw(cp, frame_->Context()); |
| // Remove the function from the stack. |
| frame_->EmitPush(v0); |
| @@ -789,8 +862,10 @@ |
| UNIMPLEMENTED_MIPS(); |
| } else if (property != NULL) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } else { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| ASSERT(frame_->height() == original_height + 1); |
| @@ -799,174 +874,204 @@ |
| void CodeGenerator::VisitCallNew(CallNew* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateValueOf(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateSetValueOf(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateLog(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateMathPow(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| -// This should generate code that performs a charCodeAt() call or returns |
| -// undefined in order to trigger the slow case, Runtime_StringCharCodeAt. |
| -// It is not yet implemented on ARM, so it always goes to the slow case. |
| void CodeGenerator::GenerateFastCharCodeAt(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateCharFromCode(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateIsArray(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateIsRegExp(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateIsConstructCall(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateArgumentsLength(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateArguments(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateRandomPositiveSmi(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateIsFunction(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateIsUndetectableObject(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateStringAdd(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateSubString(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateStringCompare(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateRegExpExec(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitCallRuntime(CallRuntime* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitCountOperation(CountOperation* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitBinaryOperation(BinaryOperation* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| - |
| void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| @@ -979,7 +1084,7 @@ |
| #define __ ACCESS_MASM(masm) |
| // ----------------------------------------------------------------------------- |
| -// Reference support |
| +// Reference support. |
| Reference::Reference(CodeGenerator* cgen, |
| Expression* expression, |
| @@ -1079,11 +1184,9 @@ |
| } |
| -// On entry a0 and a1 are the things to be compared. On exit v0 is 0, |
| -// positive or negative to indicate the result of the comparison. |
| void CompareStub::Generate(MacroAssembler* masm) { |
| UNIMPLEMENTED_MIPS(); |
| - __ break_(0x765); |
| + __ break_(__LINE__); |
| } |
| @@ -1095,20 +1198,57 @@ |
| void StackCheckStub::Generate(MacroAssembler* masm) { |
| UNIMPLEMENTED_MIPS(); |
| - __ break_(0x790); |
| + __ break_(__LINE__); |
| } |
| -void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| +void GenericUnaryOpStub::Generate(MacroAssembler* masm) { |
| UNIMPLEMENTED_MIPS(); |
| - __ break_(0x808); |
| + __ break_(__LINE__); |
| } |
| +void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { |
| + // v0 holds the exception. |
| + |
| + // Adjust this code if not the case. |
| + ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| + |
| + // Drop the sp to the top of the handler. |
| + __ li(a3, Operand(ExternalReference(Top::k_handler_address))); |
| + __ lw(sp, MemOperand(a3)); |
| + |
| + // Restore the next handler and frame pointer, discard handler state. |
| + ASSERT(StackHandlerConstants::kNextOffset == 0); |
| + __ Pop(a2); |
| + __ sw(a2, MemOperand(a3)); |
| + ASSERT(StackHandlerConstants::kFPOffset == 2 * kPointerSize); |
| + __ MultiPop(a3.bit() | fp.bit()); |
| + |
| + // Before returning we restore the context from the frame pointer if |
| + // not NULL. The frame pointer is NULL in the exception handler of a |
| + // JS entry frame. |
| + // Set cp to NULL if fp is NULL. |
| + Label done; |
| + __ Branch(false, &done, eq, fp, Operand(zero_reg)); |
| + __ mov(cp, zero_reg); // Use the branch delay slot. |
| + __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
| + __ bind(&done); |
| + |
| +#ifdef DEBUG |
| + // TODO(MIPS): Implement debug code. |
| +#endif |
| + |
| + ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize); |
| + __ Pop(t9); |
| + __ Jump(t9); |
| +} |
| + |
| + |
| void CEntryStub::GenerateThrowUncatchable(MacroAssembler* masm, |
| UncatchableExceptionType type) { |
| UNIMPLEMENTED_MIPS(); |
| - __ break_(0x815); |
| + __ break_(__LINE__); |
| } |
| void CEntryStub::GenerateCore(MacroAssembler* masm, |
| @@ -1117,18 +1257,21 @@ |
| Label* throw_out_of_memory_exception, |
| bool do_gc, |
| bool always_allocate) { |
| + // v0: result parameter for PerformGC, if any |
| // s0: number of arguments including receiver (C callee-saved) |
| // s1: pointer to the first argument (C callee-saved) |
| // s2: pointer to builtin function (C callee-saved) |
| if (do_gc) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| ExternalReference scope_depth = |
| ExternalReference::heap_always_allocate_scope_depth(); |
| if (always_allocate) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| // Call C built-in. |
| @@ -1136,10 +1279,15 @@ |
| __ mov(a0, s0); |
| __ mov(a1, s1); |
| - __ CallBuiltin(s2); |
| + // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We |
| + // also need the argument slots. |
| + __ jalr(s2); |
| + __ addiu(sp, sp, -StandardFrameConstants::kCArgsSlotsSize); |
|
Søren Thygesen Gjesse
2010/05/25 09:00:56
Please add a comment on the usage of the branch de
|
| + __ addiu(sp, sp, StandardFrameConstants::kCArgsSlotsSize); |
| if (always_allocate) { |
| UNIMPLEMENTED_MIPS(); |
| + __ break_(__LINE__); |
| } |
| // Check for failure result. |
| @@ -1147,7 +1295,7 @@ |
| ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); |
| __ addiu(a2, v0, 1); |
| __ andi(t0, a2, kFailureTagMask); |
| - __ Branch(eq, &failure_returned, t0, Operand(zero_reg)); |
| + __ Branch(&failure_returned, eq, t0, Operand(zero_reg)); |
| // Exit C frame and return. |
| // v0:v1: result |
| @@ -1160,11 +1308,11 @@ |
| __ bind(&failure_returned); |
| ASSERT(Failure::RETRY_AFTER_GC == 0); |
| __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize); |
| - __ Branch(eq, &retry, t0, Operand(zero_reg)); |
| + __ Branch(&retry, eq, t0, Operand(zero_reg)); |
| // Special handling of out of memory exceptions. |
| Failure* out_of_memory = Failure::OutOfMemoryException(); |
| - __ Branch(eq, throw_out_of_memory_exception, |
| + __ Branch(throw_out_of_memory_exception, eq, |
| v0, Operand(reinterpret_cast<int32_t>(out_of_memory))); |
| // Retrieve the pending exception and clear the variable. |
| @@ -1177,14 +1325,14 @@ |
| // Special handling of termination exceptions which are uncatchable |
| // by javascript code. |
| - __ Branch(eq, throw_termination_exception, |
| + __ Branch(throw_termination_exception, eq, |
| v0, Operand(Factory::termination_exception())); |
| // Handle normal exception. |
| - __ b(throw_normal_exception); |
| - __ nop(); // Branch delay slot nop. |
| + __ jmp(throw_normal_exception); |
| - __ bind(&retry); // pass last failure (r0) as parameter (r0) when retrying |
| + __ bind(&retry); |
| + // Last failure (v0) will be moved to (a0) for parameter when retrying. |
| } |
| void CEntryStub::Generate(MacroAssembler* masm) { |
| @@ -1263,6 +1411,10 @@ |
| // Save callee saved registers on the stack. |
| __ MultiPush((kCalleeSaved | ra.bit()) & ~sp.bit()); |
| + // Load argv in s0 register. |
| + __ lw(s0, MemOperand(sp, kNumCalleeSaved * kPointerSize + |
| + StandardFrameConstants::kCArgsSlotsSize)); |
| + |
| // We build an EntryFrame. |
| __ li(t3, Operand(-1)); // Push a bad frame pointer to fail if it is used. |
| int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; |
| @@ -1275,10 +1427,6 @@ |
| // Setup frame pointer for the frame to be pushed. |
| __ addiu(fp, sp, -EntryFrameConstants::kCallerFPOffset); |
| - // Load argv in s0 register. |
| - __ lw(s0, MemOperand(sp, (kNumCalleeSaved + 1) * kPointerSize + |
| - StandardFrameConstants::kCArgsSlotsSize)); |
| - |
| // Registers: |
| // a0: entry_address |
| // a1: function |
| @@ -1350,7 +1498,7 @@ |
| ExternalReference entry(Builtins::JSEntryTrampoline); |
| __ LoadExternalReference(t0, entry); |
| } |
| - __ lw(t9, MemOperand(t0)); // deref address |
| + __ lw(t9, MemOperand(t0)); // Deref address. |
| // Call JSEntryTrampoline. |
| __ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag); |
| @@ -1367,7 +1515,7 @@ |
| // This restores sp to its position before PushTryHandler. |
| __ addiu(sp, sp, StackHandlerConstants::kSize); |
| - __ bind(&exit); // v0 holds result |
| + __ bind(&exit); // v0 holds result. |
| // Restore the top frame descriptors from the stack. |
| __ Pop(t1); |
| __ LoadExternalReference(t0, ExternalReference(Top::k_c_entry_fp_address)); |
| @@ -1394,25 +1542,25 @@ |
| void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { |
| UNIMPLEMENTED_MIPS(); |
| - __ break_(0x851); |
| + __ break_(__LINE__); |
| } |
| void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { |
| UNIMPLEMENTED_MIPS(); |
| - __ break_(0x857); |
| + __ break_(__LINE__); |
| } |
| void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { |
| UNIMPLEMENTED_MIPS(); |
| - __ break_(0x863); |
| + __ break_(__LINE__); |
| } |
| const char* CompareStub::GetName() { |
| UNIMPLEMENTED_MIPS(); |
| - return NULL; // UNIMPLEMENTED RETURN |
| + return NULL; // UNIMPLEMENTED RETURN. |
| } |