diff options
Diffstat (limited to 'deps/v8/src/fast-codegen.cc')
-rw-r--r-- | deps/v8/src/fast-codegen.cc | 308 |
1 files changed, 85 insertions, 223 deletions
diff --git a/deps/v8/src/fast-codegen.cc b/deps/v8/src/fast-codegen.cc index b15a673552..20de808530 100644 --- a/deps/v8/src/fast-codegen.cc +++ b/deps/v8/src/fast-codegen.cc @@ -36,7 +36,7 @@ namespace v8 { namespace internal { -#define __ ACCESS_MASM(masm()) +#define __ ACCESS_MASM(masm_) Handle<Code> FastCodeGenerator::MakeCode(FunctionLiteral* fun, Handle<Script> script, @@ -232,10 +232,8 @@ void FastCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { void FastCodeGenerator::VisitBlock(Block* stmt) { Comment cmnt(masm_, "[ Block"); - Breakable nested_statement(this, stmt); SetStatementPosition(stmt); VisitStatements(stmt->statements()); - __ bind(nested_statement.break_target()); } @@ -280,88 +278,22 @@ void FastCodeGenerator::VisitIfStatement(IfStatement* stmt) { void FastCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { - Comment cmnt(masm_, "[ ContinueStatement"); - NestedStatement* current = nesting_stack_; - int stack_depth = 0; - while (!current->IsContinueTarget(stmt->target())) { - stack_depth = current->Exit(stack_depth); - current = current->outer(); - } - __ Drop(stack_depth); - - Iteration* loop = current->AsIteration(); - __ jmp(loop->continue_target()); + UNREACHABLE(); } void FastCodeGenerator::VisitBreakStatement(BreakStatement* stmt) { - Comment cmnt(masm_, "[ BreakStatement"); - NestedStatement* current = nesting_stack_; - int stack_depth = 0; - while (!current->IsBreakTarget(stmt->target())) { - stack_depth = current->Exit(stack_depth); - current = current->outer(); - } - __ Drop(stack_depth); - - Breakable* target = current->AsBreakable(); - __ jmp(target->break_target()); -} - - -void FastCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { - Comment cmnt(masm_, "[ ReturnStatement"); - Expression* expr = stmt->expression(); - // Complete the statement based on the type of the subexpression. - if (expr->AsLiteral() != NULL) { - __ Move(result_register(), expr->AsLiteral()->handle()); - } else { - ASSERT_EQ(Expression::kValue, expr->context()); - Visit(expr); - __ pop(result_register()); - } - - // Exit all nested statements. - NestedStatement* current = nesting_stack_; - int stack_depth = 0; - while (current != NULL) { - stack_depth = current->Exit(stack_depth); - current = current->outer(); - } - __ Drop(stack_depth); - - EmitReturnSequence(stmt->statement_pos()); + UNREACHABLE(); } - - void FastCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { - Comment cmnt(masm_, "[ WithEnterStatement"); - SetStatementPosition(stmt); - - Visit(stmt->expression()); - if (stmt->is_catch_block()) { - __ CallRuntime(Runtime::kPushCatchContext, 1); - } else { - __ CallRuntime(Runtime::kPushContext, 1); - } - // Both runtime calls return the new context in both the context and the - // result registers. - - // Update local stack frame context field. - StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); + UNREACHABLE(); } void FastCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { - Comment cmnt(masm_, "[ WithExitStatement"); - SetStatementPosition(stmt); - - // Pop context. - LoadContextField(context_register(), Context::PREVIOUS_INDEX); - // Update local stack frame context field. - StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); + UNREACHABLE(); } @@ -372,10 +304,8 @@ void FastCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { Comment cmnt(masm_, "[ DoWhileStatement"); - Label body, stack_limit_hit, stack_check_success; - - Iteration loop_statement(this, stmt); increment_loop_depth(); + Label body, exit, stack_limit_hit, stack_check_success; __ bind(&body); Visit(stmt->body()); @@ -386,11 +316,10 @@ void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { // We are not in an expression context because we have been compiling // statements. Set up a test expression context for the condition. - __ bind(loop_statement.continue_target()); ASSERT_EQ(NULL, true_label_); ASSERT_EQ(NULL, false_label_); true_label_ = &body; - false_label_ = loop_statement.break_target(); + false_label_ = &exit; ASSERT(stmt->cond()->context() == Expression::kTest); Visit(stmt->cond()); true_label_ = NULL; @@ -401,7 +330,7 @@ void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { __ CallStub(&stack_stub); __ jmp(&stack_check_success); - __ bind(loop_statement.break_target()); + __ bind(&exit); decrement_loop_depth(); } @@ -409,18 +338,16 @@ void FastCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { Comment cmnt(masm_, "[ WhileStatement"); - Label body, stack_limit_hit, stack_check_success; - - Iteration loop_statement(this, stmt); increment_loop_depth(); + Label test, body, exit, stack_limit_hit, stack_check_success; // Emit the test at the bottom of the loop. - __ jmp(loop_statement.continue_target()); + __ jmp(&test); __ bind(&body); Visit(stmt->body()); - __ bind(loop_statement.continue_target()); + __ bind(&test); // Check stack before looping. __ StackLimitCheck(&stack_limit_hit); __ bind(&stack_check_success); @@ -430,7 +357,7 @@ void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { ASSERT_EQ(NULL, true_label_); ASSERT_EQ(NULL, false_label_); true_label_ = &body; - false_label_ = loop_statement.break_target(); + false_label_ = &exit; ASSERT(stmt->cond()->context() == Expression::kTest); Visit(stmt->cond()); true_label_ = NULL; @@ -441,13 +368,55 @@ void FastCodeGenerator::VisitWhileStatement(WhileStatement* stmt) { __ CallStub(&stack_stub); __ jmp(&stack_check_success); - __ bind(loop_statement.break_target()); + __ bind(&exit); + decrement_loop_depth(); } void FastCodeGenerator::VisitForStatement(ForStatement* stmt) { - UNREACHABLE(); + Comment cmnt(masm_, "[ ForStatement"); + Label test, body, exit, stack_limit_hit, stack_check_success; + if (stmt->init() != NULL) Visit(stmt->init()); + + increment_loop_depth(); + // Emit the test at the bottom of the loop (even if empty). + __ jmp(&test); + __ bind(&body); + Visit(stmt->body()); + + // Check stack before looping. + __ StackLimitCheck(&stack_limit_hit); + __ bind(&stack_check_success); + + if (stmt->next() != NULL) Visit(stmt->next()); + + __ bind(&test); + + if (stmt->cond() == NULL) { + // For an empty test jump to the top of the loop. + __ jmp(&body); + } else { + // We are not in an expression context because we have been compiling + // statements. Set up a test expression context for the condition. + ASSERT_EQ(NULL, true_label_); + ASSERT_EQ(NULL, false_label_); + + true_label_ = &body; + false_label_ = &exit; + ASSERT(stmt->cond()->context() == Expression::kTest); + Visit(stmt->cond()); + true_label_ = NULL; + false_label_ = NULL; + } + + __ bind(&stack_limit_hit); + StackCheckStub stack_stub; + __ CallStub(&stack_stub); + __ jmp(&stack_check_success); + + __ bind(&exit); + decrement_loop_depth(); } @@ -462,63 +431,7 @@ void FastCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { void FastCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) { - // Try finally is compiled by setting up a try-handler on the stack while - // executing the try body, and removing it again afterwards. - // - // The try-finally construct can enter the finally block in three ways: - // 1. By exiting the try-block normally. This removes the try-handler and - // calls the finally block code before continuing. - // 2. By exiting the try-block with a function-local control flow transfer - // (break/continue/return). The site of the, e.g., break removes the - // try handler and calls the finally block code before continuing - // its outward control transfer. - // 3. by exiting the try-block with a thrown exception. - // This can happen in nested function calls. It traverses the try-handler - // chaing and consumes the try-handler entry before jumping to the - // handler code. The handler code then calls the finally-block before - // rethrowing the exception. - // - // The finally block must assume a return address on top of the stack - // (or in the link register on ARM chips) and a value (return value or - // exception) in the result register (rax/eax/r0), both of which must - // be preserved. The return address isn't GC-safe, so it should be - // cooked before GC. - Label finally_entry; - Label try_handler_setup; - - // Setup the try-handler chain. Use a call to - // Jump to try-handler setup and try-block code. Use call to put try-handler - // address on stack. - __ Call(&try_handler_setup); - // Try handler code. Return address of call is pushed on handler stack. - { - // This code is only executed during stack-handler traversal when an - // exception is thrown. The execption is in the result register, which - // is retained by the finally block. - // Call the finally block and then rethrow the exception. - __ Call(&finally_entry); - ThrowException(); - } - - __ bind(&finally_entry); - { - // Finally block implementation. - EnterFinallyBlock(); - Finally finally_block(this); - Visit(stmt->finally_block()); - ExitFinallyBlock(); // Return to the calling code. - } - - __ bind(&try_handler_setup); - { - // Setup try handler (stack pointer registers). - __ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER); - TryFinally try_block(this, &finally_entry); - VisitStatements(stmt->try_block()->statements()); - __ PopTryHandler(); - } - // Execute the finally block on the way out. - __ Call(&finally_entry); + UNREACHABLE(); } @@ -587,79 +500,40 @@ void FastCodeGenerator::VisitLiteral(Literal* expr) { void FastCodeGenerator::VisitAssignment(Assignment* expr) { Comment cmnt(masm_, "[ Assignment"); + ASSERT(expr->op() == Token::ASSIGN || expr->op() == Token::INIT_VAR); // Record source code position of the (possible) IC call. SetSourcePosition(expr->position()); - // Left-hand side can only be a property, a global or a (parameter or local) - // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. - enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; - LhsKind assign_type = VARIABLE; + Expression* rhs = expr->value(); + // Left-hand side can only be a property, a global or a (parameter or + // local) slot. + Variable* var = expr->target()->AsVariableProxy()->AsVariable(); Property* prop = expr->target()->AsProperty(); - // In case of a property we use the uninitialized expression context - // of the key to detect a named property. - if (prop != NULL) { - assign_type = (prop->key()->context() == Expression::kUninitialized) - ? NAMED_PROPERTY - : KEYED_PROPERTY; - } - - // Evaluate LHS expression. - switch (assign_type) { - case VARIABLE: - // Nothing to do here. - break; - case NAMED_PROPERTY: - Visit(prop->obj()); - ASSERT_EQ(Expression::kValue, prop->obj()->context()); - break; - case KEYED_PROPERTY: - Visit(prop->obj()); - ASSERT_EQ(Expression::kValue, prop->obj()->context()); + if (var != NULL) { + Visit(rhs); + ASSERT_EQ(Expression::kValue, rhs->context()); + EmitVariableAssignment(expr); + } else if (prop != NULL) { + // Assignment to a property. + Visit(prop->obj()); + ASSERT_EQ(Expression::kValue, prop->obj()->context()); + // Use the expression context of the key subexpression to detect whether + // we have decided to us a named or keyed IC. + if (prop->key()->context() == Expression::kUninitialized) { + ASSERT(prop->key()->AsLiteral() != NULL); + Visit(rhs); + ASSERT_EQ(Expression::kValue, rhs->context()); + EmitNamedPropertyAssignment(expr); + } else { Visit(prop->key()); ASSERT_EQ(Expression::kValue, prop->key()->context()); - break; - } - - // If we have a compound assignment: Get value of LHS expression and - // store in on top of the stack. - // Note: Relies on kValue context being 'stack'. - if (expr->is_compound()) { - switch (assign_type) { - case VARIABLE: - EmitVariableLoad(expr->target()->AsVariableProxy()->var(), - Expression::kValue); - break; - case NAMED_PROPERTY: - EmitNamedPropertyLoad(prop, Expression::kValue); - break; - case KEYED_PROPERTY: - EmitKeyedPropertyLoad(Expression::kValue); - break; - } - } - - // Evaluate RHS expression. - Expression* rhs = expr->value(); - ASSERT_EQ(Expression::kValue, rhs->context()); - Visit(rhs); - - // If we have a compount assignment: Apply operator. - if (expr->is_compound()) { - EmitCompoundAssignmentOp(expr->binary_op(), Expression::kValue); - } - - // Store the value. - switch (assign_type) { - case VARIABLE: - EmitVariableAssignment(expr); - break; - case NAMED_PROPERTY: - EmitNamedPropertyAssignment(expr); - break; - case KEYED_PROPERTY: + Visit(rhs); + ASSERT_EQ(Expression::kValue, rhs->context()); EmitKeyedPropertyAssignment(expr); - break; + } + } else { + UNREACHABLE(); } } @@ -674,20 +548,8 @@ void FastCodeGenerator::VisitThrow(Throw* expr) { } -int FastCodeGenerator::TryFinally::Exit(int stack_depth) { - // The macros used here must preserve the result register. - __ Drop(stack_depth); - __ PopTryHandler(); - __ Call(finally_entry_); - return 0; -} - - -int FastCodeGenerator::TryCatch::Exit(int stack_depth) { - // The macros used here must preserve the result register. - __ Drop(stack_depth); - __ PopTryHandler(); - return 0; +void FastCodeGenerator::VisitThisFunction(ThisFunction* expr) { + UNREACHABLE(); } |