summaryrefslogtreecommitdiff
path: root/deps/v8/src/fast-codegen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/fast-codegen.cc')
-rw-r--r--deps/v8/src/fast-codegen.cc308
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();
}