summaryrefslogtreecommitdiffstats
path: root/src/full-codegen.cc
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-09-30 15:31:59 +0100
committerKristian Monsen <kristianm@google.com>2010-10-06 14:06:50 +0100
commit0d5e116f6aee03185f237311a943491bb079a768 (patch)
treee0a80472bc3151e606a32e8d68079579c8143495 /src/full-codegen.cc
parent59151504615d929945dc59db37bf1166937748c6 (diff)
downloadandroid_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.cc323
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 __