diff options
| author | Ben Murdoch <benm@google.com> | 2011-12-02 17:19:32 +0000 |
|---|---|---|
| committer | Ben Murdoch <benm@google.com> | 2011-12-02 17:27:49 +0000 |
| commit | 3fb3ca8c7ca439d408449a395897395c0faae8d1 (patch) | |
| tree | 5cb33db083ae7ebe431e2a460fb3806c54531f9c /src/full-codegen.cc | |
| parent | 257744e915dfc84d6d07a6b2accf8402d9ffc708 (diff) | |
| download | android_external_v8-3fb3ca8c7ca439d408449a395897395c0faae8d1.tar.gz android_external_v8-3fb3ca8c7ca439d408449a395897395c0faae8d1.tar.bz2 android_external_v8-3fb3ca8c7ca439d408449a395897395c0faae8d1.zip | |
Upgrade to V8 3.4
Merge 3.4.14.35
Simple merge required updates to makefiles only.
Bug: 568872
Change-Id: I403a38452c547e06fcfa951c12eca12a1bc40978
Diffstat (limited to 'src/full-codegen.cc')
| -rw-r--r-- | src/full-codegen.cc | 467 |
1 files changed, 207 insertions, 260 deletions
diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 2b43e897..8c2f0d17 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -90,14 +90,14 @@ void BreakableStatementChecker::VisitReturnStatement(ReturnStatement* stmt) { } -void BreakableStatementChecker::VisitWithEnterStatement( - WithEnterStatement* stmt) { +void BreakableStatementChecker::VisitEnterWithContextStatement( + EnterWithContextStatement* stmt) { Visit(stmt->expression()); } -void BreakableStatementChecker::VisitWithExitStatement( - WithExitStatement* stmt) { +void BreakableStatementChecker::VisitExitContextStatement( + ExitContextStatement* stmt) { } @@ -187,11 +187,6 @@ void BreakableStatementChecker::VisitArrayLiteral(ArrayLiteral* expr) { } -void BreakableStatementChecker::VisitCatchExtensionObject( - CatchExtensionObject* expr) { -} - - void BreakableStatementChecker::VisitAssignment(Assignment* expr) { // If assigning to a property (including a global property) the assignment is // breakable. @@ -351,7 +346,7 @@ void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { } -void FullCodeGenerator::PrepareForBailout(AstNode* node, State state) { +void FullCodeGenerator::PrepareForBailout(Expression* node, State state) { PrepareForBailoutForId(node->id(), state); } @@ -409,7 +404,7 @@ int FullCodeGenerator::SlotOffset(Slot* slot) { // Adjust by a (parameter or local) base offset. switch (slot->type()) { case Slot::PARAMETER: - offset += (scope()->num_parameters() + 1) * kPointerSize; + offset += (info_->scope()->num_parameters() + 1) * kPointerSize; break; case Slot::LOCAL: offset += JavaScriptFrameConstants::kLocal0Offset; @@ -449,7 +444,7 @@ void FullCodeGenerator::TestContext::Plug(Register reg) const { // For simplicity we always test the accumulator register. __ Move(result_register(), reg); codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); - codegen()->DoTest(true_label_, false_label_, fall_through_); + codegen()->DoTest(this); } @@ -471,7 +466,7 @@ void FullCodeGenerator::TestContext::PlugTOS() const { // For simplicity we always test the accumulator register. __ pop(result_register()); codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); - codegen()->DoTest(true_label_, false_label_, fall_through_); + codegen()->DoTest(this); } @@ -521,6 +516,14 @@ void FullCodeGenerator::TestContext::PrepareTest( } +void FullCodeGenerator::DoTest(const TestContext* context) { + DoTest(context->condition(), + context->true_label(), + context->false_label(), + context->fall_through()); +} + + void FullCodeGenerator::VisitDeclarations( ZoneList<Declaration*>* declarations) { int length = declarations->length(); @@ -580,88 +583,78 @@ void FullCodeGenerator::VisitDeclarations( void FullCodeGenerator::SetFunctionPosition(FunctionLiteral* fun) { - if (FLAG_debug_info) { - CodeGenerator::RecordPositions(masm_, fun->start_position()); - } + CodeGenerator::RecordPositions(masm_, fun->start_position()); } void FullCodeGenerator::SetReturnPosition(FunctionLiteral* fun) { - if (FLAG_debug_info) { - CodeGenerator::RecordPositions(masm_, fun->end_position() - 1); - } + CodeGenerator::RecordPositions(masm_, fun->end_position() - 1); } void FullCodeGenerator::SetStatementPosition(Statement* stmt) { - if (FLAG_debug_info) { #ifdef ENABLE_DEBUGGER_SUPPORT - if (!isolate()->debugger()->IsDebuggerActive()) { - CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); - } else { - // Check if the statement will be breakable without adding a debug break - // slot. - BreakableStatementChecker checker; - checker.Check(stmt); - // Record the statement position right here if the statement is not - // breakable. For breakable statements the actual recording of the - // position will be postponed to the breakable code (typically an IC). - bool position_recorded = CodeGenerator::RecordPositions( - masm_, stmt->statement_pos(), !checker.is_breakable()); - // If the position recording did record a new position generate a debug - // break slot to make the statement breakable. - if (position_recorded) { - Debug::GenerateSlot(masm_); - } + if (!isolate()->debugger()->IsDebuggerActive()) { + CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); + } else { + // Check if the statement will be breakable without adding a debug break + // slot. + BreakableStatementChecker checker; + checker.Check(stmt); + // Record the statement position right here if the statement is not + // breakable. For breakable statements the actual recording of the + // position will be postponed to the breakable code (typically an IC). + bool position_recorded = CodeGenerator::RecordPositions( + masm_, stmt->statement_pos(), !checker.is_breakable()); + // If the position recording did record a new position generate a debug + // break slot to make the statement breakable. + if (position_recorded) { + Debug::GenerateSlot(masm_); } + } #else - CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); + CodeGenerator::RecordPositions(masm_, stmt->statement_pos()); #endif - } } void FullCodeGenerator::SetExpressionPosition(Expression* expr, int pos) { - if (FLAG_debug_info) { #ifdef ENABLE_DEBUGGER_SUPPORT - if (!isolate()->debugger()->IsDebuggerActive()) { - CodeGenerator::RecordPositions(masm_, pos); - } else { - // Check if the expression will be breakable without adding a debug break - // slot. - BreakableStatementChecker checker; - checker.Check(expr); - // Record a statement position right here if the expression is not - // breakable. For breakable expressions the actual recording of the - // position will be postponed to the breakable code (typically an IC). - // NOTE this will record a statement position for something which might - // not be a statement. As stepping in the debugger will only stop at - // statement positions this is used for e.g. the condition expression of - // a do while loop. - bool position_recorded = CodeGenerator::RecordPositions( - masm_, pos, !checker.is_breakable()); - // If the position recording did record a new position generate a debug - // break slot to make the statement breakable. - if (position_recorded) { - Debug::GenerateSlot(masm_); - } + if (!isolate()->debugger()->IsDebuggerActive()) { + CodeGenerator::RecordPositions(masm_, pos); + } else { + // Check if the expression will be breakable without adding a debug break + // slot. + BreakableStatementChecker checker; + checker.Check(expr); + // Record a statement position right here if the expression is not + // breakable. For breakable expressions the actual recording of the + // position will be postponed to the breakable code (typically an IC). + // NOTE this will record a statement position for something which might + // not be a statement. As stepping in the debugger will only stop at + // statement positions this is used for e.g. the condition expression of + // a do while loop. + bool position_recorded = CodeGenerator::RecordPositions( + masm_, pos, !checker.is_breakable()); + // If the position recording did record a new position generate a debug + // break slot to make the statement breakable. + if (position_recorded) { + Debug::GenerateSlot(masm_); } + } #else - CodeGenerator::RecordPositions(masm_, pos); + CodeGenerator::RecordPositions(masm_, pos); #endif - } } void FullCodeGenerator::SetStatementPosition(int pos) { - if (FLAG_debug_info) { - CodeGenerator::RecordPositions(masm_, pos); - } + CodeGenerator::RecordPositions(masm_, pos); } void FullCodeGenerator::SetSourcePosition(int pos) { - if (FLAG_debug_info && pos != RelocInfo::kNoPosition) { + if (pos != RelocInfo::kNoPosition) { masm_->positions_recorder()->RecordPosition(pos); } } @@ -693,7 +686,6 @@ FullCodeGenerator::InlineFunctionGenerator void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) { ZoneList<Expression*>* args = node->arguments(); - Handle<String> name = node->name(); const Runtime::Function* function = node->function(); ASSERT(function != NULL); ASSERT(function->intrinsic_type == Runtime::INLINE); @@ -704,143 +696,116 @@ void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) { void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { - Comment cmnt(masm_, "[ BinaryOperation"); - Token::Value op = expr->op(); - Expression* left = expr->left(); - Expression* right = expr->right(); - - OverwriteMode mode = NO_OVERWRITE; - if (left->ResultOverwriteAllowed()) { - mode = OVERWRITE_LEFT; - } else if (right->ResultOverwriteAllowed()) { - mode = OVERWRITE_RIGHT; - } - - switch (op) { + switch (expr->op()) { case Token::COMMA: - VisitForEffect(left); - if (context()->IsTest()) ForwardBailoutToChild(expr); - context()->HandleExpression(right); - break; - + return VisitComma(expr); case Token::OR: case Token::AND: - EmitLogicalOperation(expr); - break; - - case Token::ADD: - case Token::SUB: - case Token::DIV: - case Token::MOD: - case Token::MUL: - case Token::BIT_OR: - case Token::BIT_AND: - case Token::BIT_XOR: - case Token::SHL: - case Token::SHR: - case Token::SAR: { - // Load both operands. - VisitForStackValue(left); - VisitForAccumulatorValue(right); - - SetSourcePosition(expr->position()); - if (ShouldInlineSmiCase(op)) { - EmitInlineSmiBinaryOp(expr, op, mode, left, right); - } else { - EmitBinaryOp(expr, op, mode); - } - break; - } - + return VisitLogicalExpression(expr); default: - UNREACHABLE(); + return VisitArithmeticExpression(expr); } } -void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { - Label eval_right, done; - - context()->EmitLogicalLeft(expr, &eval_right, &done); - - PrepareForBailoutForId(expr->RightId(), NO_REGISTERS); - __ bind(&eval_right); +void FullCodeGenerator::VisitComma(BinaryOperation* expr) { + Comment cmnt(masm_, "[ Comma"); + VisitForEffect(expr->left()); if (context()->IsTest()) ForwardBailoutToChild(expr); - context()->HandleExpression(expr->right()); - - __ bind(&done); + VisitInCurrentContext(expr->right()); } -void FullCodeGenerator::EffectContext::EmitLogicalLeft(BinaryOperation* expr, - Label* eval_right, - Label* done) const { - if (expr->op() == Token::OR) { - codegen()->VisitForControl(expr->left(), done, eval_right, eval_right); - } else { - ASSERT(expr->op() == Token::AND); - codegen()->VisitForControl(expr->left(), eval_right, done, eval_right); - } -} +void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) { + bool is_logical_and = expr->op() == Token::AND; + Comment cmnt(masm_, is_logical_and ? "[ Logical AND" : "[ Logical OR"); + Expression* left = expr->left(); + Expression* right = expr->right(); + int right_id = expr->RightId(); + Label done; + if (context()->IsTest()) { + Label eval_right; + const TestContext* test = TestContext::cast(context()); + if (is_logical_and) { + VisitForControl(left, &eval_right, test->false_label(), &eval_right); + } else { + VisitForControl(left, test->true_label(), &eval_right, &eval_right); + } + PrepareForBailoutForId(right_id, NO_REGISTERS); + __ bind(&eval_right); + ForwardBailoutToChild(expr); + + } else if (context()->IsAccumulatorValue()) { + VisitForAccumulatorValue(left); + // We want the value in the accumulator for the test, and on the stack in + // case we need it. + __ push(result_register()); + Label discard, restore; + PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + if (is_logical_and) { + DoTest(left, &discard, &restore, &restore); + } else { + DoTest(left, &restore, &discard, &restore); + } + __ bind(&restore); + __ pop(result_register()); + __ jmp(&done); + __ bind(&discard); + __ Drop(1); + PrepareForBailoutForId(right_id, NO_REGISTERS); + + } else if (context()->IsStackValue()) { + VisitForAccumulatorValue(left); + // We want the value in the accumulator for the test, and on the stack in + // case we need it. + __ push(result_register()); + Label discard; + PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); + if (is_logical_and) { + DoTest(left, &discard, &done, &discard); + } else { + DoTest(left, &done, &discard, &discard); + } + __ bind(&discard); + __ Drop(1); + PrepareForBailoutForId(right_id, NO_REGISTERS); -void FullCodeGenerator::AccumulatorValueContext::EmitLogicalLeft( - BinaryOperation* expr, - Label* eval_right, - Label* done) const { - HandleExpression(expr->left()); - // We want the value in the accumulator for the test, and on the stack in case - // we need it. - __ push(result_register()); - Label discard, restore; - if (expr->op() == Token::OR) { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); - codegen()->DoTest(&restore, &discard, &restore); } else { - ASSERT(expr->op() == Token::AND); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); - codegen()->DoTest(&discard, &restore, &restore); + ASSERT(context()->IsEffect()); + Label eval_right; + if (is_logical_and) { + VisitForControl(left, &eval_right, &done, &eval_right); + } else { + VisitForControl(left, &done, &eval_right, &eval_right); + } + PrepareForBailoutForId(right_id, NO_REGISTERS); + __ bind(&eval_right); } - __ bind(&restore); - __ pop(result_register()); - __ jmp(done); - __ bind(&discard); - __ Drop(1); + + VisitInCurrentContext(right); + __ bind(&done); } -void FullCodeGenerator::StackValueContext::EmitLogicalLeft( - BinaryOperation* expr, - Label* eval_right, - Label* done) const { - codegen()->VisitForAccumulatorValue(expr->left()); - // We want the value in the accumulator for the test, and on the stack in case - // we need it. - __ push(result_register()); - Label discard; - if (expr->op() == Token::OR) { - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); - codegen()->DoTest(done, &discard, &discard); - } else { - ASSERT(expr->op() == Token::AND); - codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); - codegen()->DoTest(&discard, done, &discard); - } - __ bind(&discard); - __ Drop(1); -} +void FullCodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { + Token::Value op = expr->op(); + Comment cmnt(masm_, "[ ArithmeticExpression"); + Expression* left = expr->left(); + Expression* right = expr->right(); + OverwriteMode mode = + left->ResultOverwriteAllowed() + ? OVERWRITE_LEFT + : (right->ResultOverwriteAllowed() ? OVERWRITE_RIGHT : NO_OVERWRITE); + VisitForStackValue(left); + VisitForAccumulatorValue(right); -void FullCodeGenerator::TestContext::EmitLogicalLeft(BinaryOperation* expr, - Label* eval_right, - Label* done) const { - if (expr->op() == Token::OR) { - codegen()->VisitForControl(expr->left(), - true_label_, eval_right, eval_right); + SetSourcePosition(expr->position()); + if (ShouldInlineSmiCase(op)) { + EmitInlineSmiBinaryOp(expr, op, mode, left, right); } else { - ASSERT(expr->op() == Token::AND); - codegen()->VisitForControl(expr->left(), - eval_right, false_label_, eval_right); + EmitBinaryOp(expr, op, mode); } } @@ -853,46 +818,23 @@ void FullCodeGenerator::ForwardBailoutToChild(Expression* expr) { } -void FullCodeGenerator::EffectContext::HandleExpression( - Expression* expr) const { - codegen()->HandleInNonTestContext(expr, NO_REGISTERS); -} - - -void FullCodeGenerator::AccumulatorValueContext::HandleExpression( - Expression* expr) const { - codegen()->HandleInNonTestContext(expr, TOS_REG); -} - - -void FullCodeGenerator::StackValueContext::HandleExpression( - Expression* expr) const { - codegen()->HandleInNonTestContext(expr, NO_REGISTERS); -} - - -void FullCodeGenerator::TestContext::HandleExpression(Expression* expr) const { - codegen()->VisitInTestContext(expr); -} - - -void FullCodeGenerator::HandleInNonTestContext(Expression* expr, State state) { - ASSERT(forward_bailout_pending_ == NULL); - AstVisitor::Visit(expr); - PrepareForBailout(expr, state); - // Forwarding bailouts to children is a one shot operation. It - // should have been processed at this point. - ASSERT(forward_bailout_pending_ == NULL); -} - - -void FullCodeGenerator::VisitInTestContext(Expression* expr) { - ForwardBailoutStack stack(expr, forward_bailout_pending_); - ForwardBailoutStack* saved = forward_bailout_stack_; - forward_bailout_pending_ = NULL; - forward_bailout_stack_ = &stack; - AstVisitor::Visit(expr); - forward_bailout_stack_ = saved; +void FullCodeGenerator::VisitInCurrentContext(Expression* expr) { + if (context()->IsTest()) { + ForwardBailoutStack stack(expr, forward_bailout_pending_); + ForwardBailoutStack* saved = forward_bailout_stack_; + forward_bailout_pending_ = NULL; + forward_bailout_stack_ = &stack; + Visit(expr); + forward_bailout_stack_ = saved; + } else { + ASSERT(forward_bailout_pending_ == NULL); + Visit(expr); + State state = context()->IsAccumulatorValue() ? TOS_REG : NO_REGISTERS; + PrepareForBailout(expr, state); + // Forwarding bailouts to children is a one shot operation. It should have + // been processed at this point. + ASSERT(forward_bailout_pending_ == NULL); + } } @@ -945,7 +887,7 @@ void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) { PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS); } __ bind(&done); - PrepareForBailoutForId(stmt->id(), NO_REGISTERS); + PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS); } @@ -1010,26 +952,20 @@ void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { } -void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { - Comment cmnt(masm_, "[ WithEnterStatement"); +void FullCodeGenerator::VisitEnterWithContextStatement( + EnterWithContextStatement* stmt) { + Comment cmnt(masm_, "[ EnterWithContextStatement"); SetStatementPosition(stmt); VisitForStackValue(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. + PushFunctionArgumentForContextAllocation(); + __ CallRuntime(Runtime::kPushWithContext, 2); StoreToFrameField(StandardFrameConstants::kContextOffset, context_register()); } -void FullCodeGenerator::VisitWithExitStatement(WithExitStatement* stmt) { - Comment cmnt(masm_, "[ WithExitStatement"); +void FullCodeGenerator::VisitExitContextStatement(ExitContextStatement* stmt) { + Comment cmnt(masm_, "[ ExitContextStatement"); SetStatementPosition(stmt); // Pop context. @@ -1170,18 +1106,21 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { __ Call(&try_handler_setup); // Try handler code, exception in result register. - // Store exception in local .catch variable before executing catch block. - { - // The catch variable is *always* a variable proxy for a local variable. - Variable* catch_var = stmt->catch_var()->AsVariableProxy()->AsVariable(); - ASSERT_NOT_NULL(catch_var); - Slot* variable_slot = catch_var->AsSlot(); - ASSERT_NOT_NULL(variable_slot); - ASSERT_EQ(Slot::LOCAL, variable_slot->type()); - StoreToFrameField(SlotOffset(variable_slot), result_register()); + // Extend the context before executing the catch block. + { Comment cmnt(masm_, "[ Extend catch context"); + __ Push(stmt->variable()->name()); + __ push(result_register()); + PushFunctionArgumentForContextAllocation(); + __ CallRuntime(Runtime::kPushCatchContext, 3); + StoreToFrameField(StandardFrameConstants::kContextOffset, + context_register()); } + Scope* saved_scope = scope(); + scope_ = stmt->scope(); + ASSERT(scope_->declarations()->is_empty()); Visit(stmt->catch_block()); + scope_ = saved_scope; __ jmp(&done); // Try block code. Sets up the exception handler chain. @@ -1290,7 +1229,7 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) { for_test->false_label(), NULL); } else { - context()->HandleExpression(expr->then_expression()); + VisitInCurrentContext(expr->then_expression()); __ jmp(&done); } @@ -1299,7 +1238,7 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) { if (context()->IsTest()) ForwardBailoutToChild(expr); SetExpressionPosition(expr->else_expression(), expr->else_expression_position()); - context()->HandleExpression(expr->else_expression()); + VisitInCurrentContext(expr->else_expression()); // If control flow falls through Visit, merge it with true case here. if (!context()->IsTest()) { __ bind(&done); @@ -1334,18 +1273,6 @@ void FullCodeGenerator::VisitSharedFunctionInfoLiteral( } -void FullCodeGenerator::VisitCatchExtensionObject(CatchExtensionObject* expr) { - // Call runtime routine to allocate the catch extension object and - // assign the exception value to the catch variable. - Comment cmnt(masm_, "[ CatchExtensionObject"); - VisitForStackValue(expr->key()); - VisitForStackValue(expr->value()); - // Create catch extension object. - __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); - context()->Plug(result_register()); -} - - void FullCodeGenerator::VisitThrow(Throw* expr) { Comment cmnt(masm_, "[ Throw"); VisitForStackValue(expr->exception()); @@ -1371,6 +1298,26 @@ int FullCodeGenerator::TryCatch::Exit(int stack_depth) { } +bool FullCodeGenerator::TryLiteralCompare(CompareOperation* compare, + Label* if_true, + Label* if_false, + Label* fall_through) { + Expression *expr; + Handle<String> check; + if (compare->IsLiteralCompareTypeof(&expr, &check)) { + EmitLiteralCompareTypeof(expr, check, if_true, if_false, fall_through); + return true; + } + + if (compare->IsLiteralCompareUndefined(&expr)) { + EmitLiteralCompareUndefined(expr, if_true, if_false, fall_through); + return true; + } + + return false; +} + + #undef __ |
