diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-07-08 16:40:11 -0700 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-07-08 16:40:11 -0700 |
commit | e5564a3f29e0a818832a97c7c3b28d7c8b3b0460 (patch) | |
tree | 4b48a6577080d5e44da4d2cbebb7fe7951660de8 /deps/v8/src/full-codegen.cc | |
parent | 0df2f74d364826053641395b01c2fcb1345057a9 (diff) | |
download | node-new-e5564a3f29e0a818832a97c7c3b28d7c8b3b0460.tar.gz |
Upgrade V8 to 3.4.10
Diffstat (limited to 'deps/v8/src/full-codegen.cc')
-rw-r--r-- | deps/v8/src/full-codegen.cc | 501 |
1 files changed, 222 insertions, 279 deletions
diff --git a/deps/v8/src/full-codegen.cc b/deps/v8/src/full-codegen.cc index b3dc95bdff..0b91f54468 100644 --- a/deps/v8/src/full-codegen.cc +++ b/deps/v8/src/full-codegen.cc @@ -1,4 +1,4 @@ -// Copyright 2010 the V8 project authors. All rights reserved. +// Copyright 2011 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -27,7 +27,7 @@ #include "v8.h" -#include "codegen-inl.h" +#include "codegen.h" #include "compiler.h" #include "debug.h" #include "full-codegen.h" @@ -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. @@ -213,12 +208,6 @@ void BreakableStatementChecker::VisitThrow(Throw* expr) { } -void BreakableStatementChecker::VisitIncrementOperation( - IncrementOperation* expr) { - UNREACHABLE(); -} - - void BreakableStatementChecker::VisitProperty(Property* expr) { // Property load is breakable. is_breakable_ = true; @@ -253,7 +242,10 @@ void BreakableStatementChecker::VisitCountOperation(CountOperation* expr) { void BreakableStatementChecker::VisitBinaryOperation(BinaryOperation* expr) { Visit(expr->left()); - Visit(expr->right()); + if (expr->op() != Token::AND && + expr->op() != Token::OR) { + Visit(expr->right()); + } } @@ -275,17 +267,18 @@ void BreakableStatementChecker::VisitThisFunction(ThisFunction* expr) { #define __ ACCESS_MASM(masm()) bool FullCodeGenerator::MakeCode(CompilationInfo* info) { + Isolate* isolate = info->isolate(); Handle<Script> script = info->script(); if (!script->IsUndefined() && !script->source()->IsUndefined()) { int len = String::cast(script->source())->length(); - Counters::total_full_codegen_source_size.Increment(len); + isolate->counters()->total_full_codegen_source_size()->Increment(len); } if (FLAG_trace_codegen) { PrintF("Full Compiler - "); } CodeGenerator::MakeCodePrologue(info); const int kInitialBufferSize = 4 * KB; - MacroAssembler masm(NULL, kInitialBufferSize); + MacroAssembler masm(info->isolate(), NULL, kInitialBufferSize); #ifdef ENABLE_GDB_JIT_INTERFACE masm.positions_recorder()->StartGDBJITLineInfoRecording(); #endif @@ -293,7 +286,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) { FullCodeGenerator cgen(&masm); cgen.Generate(info); if (cgen.HasStackOverflow()) { - ASSERT(!Top::has_pending_exception()); + ASSERT(!isolate->has_pending_exception()); return false; } unsigned table_offset = cgen.EmitStackCheckTable(); @@ -343,7 +336,8 @@ void FullCodeGenerator::PopulateDeoptimizationData(Handle<Code> code) { if (!info_->HasDeoptimizationSupport()) return; int length = bailout_entries_.length(); Handle<DeoptimizationOutputData> data = - Factory::NewDeoptimizationOutputData(length, TENURED); + isolate()->factory()-> + NewDeoptimizationOutputData(length, TENURED); for (int i = 0; i < length; i++) { data->SetAstId(i, Smi::FromInt(bailout_entries_[i].id)); data->SetPcAndState(i, Smi::FromInt(bailout_entries_[i].pc_and_state)); @@ -352,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); } @@ -410,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; @@ -450,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); } @@ -472,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); } @@ -522,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(); @@ -545,7 +547,8 @@ void FullCodeGenerator::VisitDeclarations( // Compute array of global variable and function declarations. // Do nothing in case of no declared global functions or variables. if (globals > 0) { - Handle<FixedArray> array = Factory::NewFixedArray(2 * globals, TENURED); + Handle<FixedArray> array = + isolate()->factory()->NewFixedArray(2 * globals, TENURED); for (int j = 0, i = 0; i < length; i++) { Declaration* decl = declarations->at(i); Variable* var = decl->proxy()->var(); @@ -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 (!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 (!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); } } @@ -694,7 +687,7 @@ FullCodeGenerator::InlineFunctionGenerator void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) { ZoneList<Expression*>* args = node->arguments(); Handle<String> name = node->name(); - Runtime::Function* function = node->function(); + const Runtime::Function* function = node->function(); ASSERT(function != NULL); ASSERT(function->intrinsic_type == Runtime::INLINE); InlineFunctionGenerator generator = @@ -704,143 +697,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(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 +819,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 +888,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 +953,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 +1107,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 +1230,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 +1239,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 +1274,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()); @@ -1354,11 +1282,6 @@ void FullCodeGenerator::VisitThrow(Throw* expr) { } -void FullCodeGenerator::VisitIncrementOperation(IncrementOperation* expr) { - UNREACHABLE(); -} - - int FullCodeGenerator::TryFinally::Exit(int stack_depth) { // The macros used here must preserve the result register. __ Drop(stack_depth); @@ -1376,6 +1299,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 __ |