diff options
| author | Kristian Monsen <kristianm@google.com> | 2010-09-30 15:31:59 +0100 |
|---|---|---|
| committer | Kristian Monsen <kristianm@google.com> | 2010-10-06 14:06:50 +0100 |
| commit | 0d5e116f6aee03185f237311a943491bb079a768 (patch) | |
| tree | e0a80472bc3151e606a32e8d68079579c8143495 /src/full-codegen.cc | |
| parent | 59151504615d929945dc59db37bf1166937748c6 (diff) | |
| download | android_external_v8-0d5e116f6aee03185f237311a943491bb079a768.tar.gz android_external_v8-0d5e116f6aee03185f237311a943491bb079a768.tar.bz2 android_external_v8-0d5e116f6aee03185f237311a943491bb079a768.zip | |
update V8 to r5532 as required by WebKit r68651
Change-Id: I5f75eeffbf64b30dd5080348528d277f293490ad
Diffstat (limited to 'src/full-codegen.cc')
| -rw-r--r-- | src/full-codegen.cc | 323 |
1 files changed, 200 insertions, 123 deletions
diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 7de4a006..fa835cb0 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -324,42 +324,101 @@ int FullCodeGenerator::SlotOffset(Slot* slot) { bool FullCodeGenerator::ShouldInlineSmiCase(Token::Value op) { - // TODO(kasperl): Once the compare stub allows leaving out the - // inlined smi case, we should get rid of this check. - if (Token::IsCompareOp(op)) return true; - // TODO(kasperl): Once the unary bit not stub allows leaving out - // the inlined smi case, we should get rid of this check. - if (op == Token::BIT_NOT) return true; // Inline smi case inside loops, but not division and modulo which // are too complicated and take up too much space. - return (op != Token::DIV) && (op != Token::MOD) && (loop_depth_ > 0); + if (op == Token::DIV ||op == Token::MOD) return false; + if (FLAG_always_inline_smi_code) return true; + return loop_depth_ > 0; } -void FullCodeGenerator::PrepareTest(Label* materialize_true, - Label* materialize_false, - Label** if_true, - Label** if_false, - Label** fall_through) { - switch (context_) { - case Expression::kUninitialized: - UNREACHABLE(); - break; - case Expression::kEffect: - // In an effect context, the true and the false case branch to the - // same label. - *if_true = *if_false = *fall_through = materialize_true; - break; - case Expression::kValue: - *if_true = *fall_through = materialize_true; - *if_false = materialize_false; - break; - case Expression::kTest: - *if_true = true_label_; - *if_false = false_label_; - *fall_through = fall_through_; - break; - } +void FullCodeGenerator::EffectContext::Plug(Register reg) const { +} + + +void FullCodeGenerator::AccumulatorValueContext::Plug(Register reg) const { + // Move value into place. + __ Move(result_register(), reg); +} + + +void FullCodeGenerator::StackValueContext::Plug(Register reg) const { + // Move value into place. + __ push(reg); +} + + +void FullCodeGenerator::TestContext::Plug(Register reg) const { + // For simplicity we always test the accumulator register. + __ Move(result_register(), reg); + codegen()->DoTest(true_label_, false_label_, fall_through_); +} + + +void FullCodeGenerator::EffectContext::PlugTOS() const { + __ Drop(1); +} + + +void FullCodeGenerator::AccumulatorValueContext::PlugTOS() const { + __ pop(result_register()); +} + + +void FullCodeGenerator::StackValueContext::PlugTOS() const { +} + + +void FullCodeGenerator::TestContext::PlugTOS() const { + // For simplicity we always test the accumulator register. + __ pop(result_register()); + codegen()->DoTest(true_label_, false_label_, fall_through_); +} + + +void FullCodeGenerator::EffectContext::PrepareTest( + Label* materialize_true, + Label* materialize_false, + Label** if_true, + Label** if_false, + Label** fall_through) const { + // In an effect context, the true and the false case branch to the + // same label. + *if_true = *if_false = *fall_through = materialize_true; +} + + +void FullCodeGenerator::AccumulatorValueContext::PrepareTest( + Label* materialize_true, + Label* materialize_false, + Label** if_true, + Label** if_false, + Label** fall_through) const { + *if_true = *fall_through = materialize_true; + *if_false = materialize_false; +} + + +void FullCodeGenerator::StackValueContext::PrepareTest( + Label* materialize_true, + Label* materialize_false, + Label** if_true, + Label** if_false, + Label** fall_through) const { + *if_true = *fall_through = materialize_true; + *if_false = materialize_false; +} + + +void FullCodeGenerator::TestContext::PrepareTest( + Label* materialize_true, + Label* materialize_false, + Label** if_true, + Label** if_false, + Label** fall_through) const { + *if_true = true_label_; + *if_false = false_label_; + *fall_through = fall_through_; } @@ -370,7 +429,7 @@ void FullCodeGenerator::VisitDeclarations( for (int i = 0; i < length; i++) { Declaration* decl = declarations->at(i); Variable* var = decl->proxy()->var(); - Slot* slot = var->slot(); + Slot* slot = var->AsSlot(); // If it was not possible to allocate the variable at compile // time, we need to "declare" it at runtime to make sure it @@ -390,7 +449,7 @@ void FullCodeGenerator::VisitDeclarations( for (int j = 0, i = 0; i < length; i++) { Declaration* decl = declarations->at(i); Variable* var = decl->proxy()->var(); - Slot* slot = var->slot(); + Slot* slot = var->AsSlot(); if ((slot == NULL || slot->type() != Slot::LOOKUP) && var->is_global()) { array->set(j++, *(var->name())); @@ -505,18 +564,36 @@ void FullCodeGenerator::SetSourcePosition(int pos) { } -void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* expr) { - Handle<String> name = expr->name(); - SmartPointer<char> cstring = name->ToCString(); +// Lookup table for code generators for special runtime calls which are +// generated inline. +#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ + &FullCodeGenerator::Emit##Name, -#define CHECK_EMIT_INLINE_CALL(name, x, y) \ - if (strcmp("_"#name, *cstring) == 0) { \ - Emit##name(expr->arguments()); \ - return; \ - } - INLINE_RUNTIME_FUNCTION_LIST(CHECK_EMIT_INLINE_CALL) -#undef CHECK_EMIT_INLINE_CALL - UNREACHABLE(); +const FullCodeGenerator::InlineFunctionGenerator + FullCodeGenerator::kInlineFunctionGenerators[] = { + INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) + INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) + }; +#undef INLINE_FUNCTION_GENERATOR_ADDRESS + + +FullCodeGenerator::InlineFunctionGenerator + FullCodeGenerator::FindInlineFunctionGenerator(Runtime::FunctionId id) { + return kInlineFunctionGenerators[ + static_cast<int>(id) - static_cast<int>(Runtime::kFirstInlineFunction)]; +} + + +void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) { + ZoneList<Expression*>* args = node->arguments(); + Handle<String> name = node->name(); + Runtime::Function* function = node->function(); + ASSERT(function != NULL); + ASSERT(function->intrinsic_type == Runtime::INLINE); + InlineFunctionGenerator generator = + FindInlineFunctionGenerator(function->function_id); + ASSERT(generator != NULL); + ((*this).*(generator))(args); } @@ -562,20 +639,20 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { // Load only the operands that we need to materialize. if (constant == kNoConstants) { - VisitForValue(left, kStack); - VisitForValue(right, kAccumulator); + VisitForStackValue(left); + VisitForAccumulatorValue(right); } else if (constant == kRightConstant) { - VisitForValue(left, kAccumulator); + VisitForAccumulatorValue(left); } else { ASSERT(constant == kLeftConstant); - VisitForValue(right, kAccumulator); + VisitForAccumulatorValue(right); } SetSourcePosition(expr->position()); if (ShouldInlineSmiCase(op)) { - EmitInlineSmiBinaryOp(expr, op, context_, mode, left, right, constant); + EmitInlineSmiBinaryOp(expr, op, mode, left, right, constant); } else { - EmitBinaryOp(op, context_, mode); + EmitBinaryOp(op, mode); } break; } @@ -589,39 +666,7 @@ void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) { void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { Label eval_right, done; - // Set up the appropriate context for the left subexpression based - // on the operation and our own context. Initially assume we can - // inherit both true and false labels from our context. - if (expr->op() == Token::OR) { - switch (context_) { - case Expression::kUninitialized: - UNREACHABLE(); - case Expression::kEffect: - VisitForControl(expr->left(), &done, &eval_right, &eval_right); - break; - case Expression::kValue: - VisitLogicalForValue(expr->left(), expr->op(), location_, &done); - break; - case Expression::kTest: - VisitForControl(expr->left(), true_label_, &eval_right, &eval_right); - break; - } - } else { - ASSERT_EQ(Token::AND, expr->op()); - switch (context_) { - case Expression::kUninitialized: - UNREACHABLE(); - case Expression::kEffect: - VisitForControl(expr->left(), &eval_right, &done, &eval_right); - break; - case Expression::kValue: - VisitLogicalForValue(expr->left(), expr->op(), location_, &done); - break; - case Expression::kTest: - VisitForControl(expr->left(), &eval_right, false_label_, &eval_right); - break; - } - } + context()->EmitLogicalLeft(expr, &eval_right, &done); __ bind(&eval_right); Visit(expr->right()); @@ -630,43 +675,75 @@ void FullCodeGenerator::EmitLogicalOperation(BinaryOperation* expr) { } -void FullCodeGenerator::VisitLogicalForValue(Expression* expr, - Token::Value op, - Location where, - Label* done) { - ASSERT(op == Token::AND || op == Token::OR); - VisitForValue(expr, kAccumulator); +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::AccumulatorValueContext::EmitLogicalLeft( + BinaryOperation* expr, + Label* eval_right, + Label* done) const { + codegen()->Visit(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()->DoTest(&restore, &discard, &restore); + } else { + ASSERT(expr->op() == Token::AND); + codegen()->DoTest(&discard, &restore, &restore); + } + __ bind(&restore); + __ pop(result_register()); + __ jmp(done); + __ bind(&discard); + __ Drop(1); +} + +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; - switch (where) { - case kAccumulator: { - Label restore; - if (op == Token::OR) { - DoTest(&restore, &discard, &restore); - } else { - DoTest(&discard, &restore, &restore); - } - __ bind(&restore); - __ pop(result_register()); - __ jmp(done); - break; - } - case kStack: { - if (op == Token::OR) { - DoTest(done, &discard, &discard); - } else { - DoTest(&discard, done, &discard); - } - break; - } + if (expr->op() == Token::OR) { + codegen()->DoTest(done, &discard, &discard); + } else { + ASSERT(expr->op() == Token::AND); + codegen()->DoTest(&discard, done, &discard); } - __ bind(&discard); __ Drop(1); } +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); + } else { + ASSERT(expr->op() == Token::AND); + codegen()->VisitForControl(expr->left(), + eval_right, false_label_, eval_right); + } +} + + void FullCodeGenerator::VisitBlock(Block* stmt) { Comment cmnt(masm_, "[ Block"); Breakable nested_statement(this, stmt); @@ -747,7 +824,7 @@ void FullCodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { Comment cmnt(masm_, "[ ReturnStatement"); SetStatementPosition(stmt); Expression* expr = stmt->expression(); - VisitForValue(expr, kAccumulator); + VisitForAccumulatorValue(expr); // Exit all nested statements. NestedStatement* current = nesting_stack_; @@ -766,7 +843,7 @@ void FullCodeGenerator::VisitWithEnterStatement(WithEnterStatement* stmt) { Comment cmnt(masm_, "[ WithEnterStatement"); SetStatementPosition(stmt); - VisitForValue(stmt->expression(), kStack); + VisitForStackValue(stmt->expression()); if (stmt->is_catch_block()) { __ CallRuntime(Runtime::kPushCatchContext, 1); } else { @@ -941,7 +1018,7 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { // 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->slot(); + Slot* variable_slot = catch_var->AsSlot(); ASSERT_NOT_NULL(variable_slot); ASSERT_EQ(Slot::LOCAL, variable_slot->type()); StoreToFrameField(SlotOffset(variable_slot), result_register()); @@ -1047,7 +1124,7 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) { expr->then_expression_position()); Visit(expr->then_expression()); // If control flow falls through Visit, jump to done. - if (context_ == Expression::kEffect || context_ == Expression::kValue) { + if (!context()->IsTest()) { __ jmp(&done); } @@ -1056,7 +1133,7 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) { expr->else_expression_position()); Visit(expr->else_expression()); // If control flow falls through Visit, merge it with true case here. - if (context_ == Expression::kEffect || context_ == Expression::kValue) { + if (!context()->IsTest()) { __ bind(&done); } } @@ -1070,7 +1147,7 @@ void FullCodeGenerator::VisitSlot(Slot* expr) { void FullCodeGenerator::VisitLiteral(Literal* expr) { Comment cmnt(masm_, "[ Literal"); - Apply(context_, expr); + context()->Plug(expr->handle()); } @@ -1096,17 +1173,17 @@ 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"); - VisitForValue(expr->key(), kStack); - VisitForValue(expr->value(), kStack); + VisitForStackValue(expr->key()); + VisitForStackValue(expr->value()); // Create catch extension object. __ CallRuntime(Runtime::kCreateCatchExtensionObject, 2); - Apply(context_, result_register()); + context()->Plug(result_register()); } void FullCodeGenerator::VisitThrow(Throw* expr) { Comment cmnt(masm_, "[ Throw"); - VisitForValue(expr->exception(), kStack); + VisitForStackValue(expr->exception()); __ CallRuntime(Runtime::kThrow, 1); // Never returns here. } @@ -1136,9 +1213,9 @@ int FullCodeGenerator::TryCatch::Exit(int stack_depth) { void FullCodeGenerator::EmitRegExpCloneResult(ZoneList<Expression*>* args) { ASSERT(args->length() == 1); - VisitForValue(args->at(0), kStack); + VisitForStackValue(args->at(0)); __ CallRuntime(Runtime::kRegExpCloneResult, 1); - Apply(context_, result_register()); + context()->Plug(result_register()); } #undef __ |
