aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter/bytecode-generator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/interpreter/bytecode-generator.cc')
-rw-r--r--deps/v8/src/interpreter/bytecode-generator.cc293
1 files changed, 239 insertions, 54 deletions
diff --git a/deps/v8/src/interpreter/bytecode-generator.cc b/deps/v8/src/interpreter/bytecode-generator.cc
index 9cce681ad4..7257fd4134 100644
--- a/deps/v8/src/interpreter/bytecode-generator.cc
+++ b/deps/v8/src/interpreter/bytecode-generator.cc
@@ -16,7 +16,7 @@ namespace internal {
namespace interpreter {
BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
- : builder_(isolate) {
+ : builder_(isolate, zone) {
InitializeAstVisitor(isolate, zone);
}
@@ -25,11 +25,13 @@ BytecodeGenerator::~BytecodeGenerator() {}
Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
+ set_info(info);
set_scope(info->scope());
// This a temporary guard (oth).
DCHECK(scope()->is_function_scope());
+ builder().set_parameter_count(info->num_parameters_including_this());
builder().set_locals_count(scope()->num_stack_slots());
// Visit implicit declaration of the function name.
@@ -44,11 +46,13 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
VisitStatements(info->literal()->body());
set_scope(nullptr);
+ set_info(nullptr);
return builder_.ToBytecodeArray();
}
void BytecodeGenerator::VisitBlock(Block* node) {
+ builder().EnterBlock();
if (node->scope() == NULL) {
// Visit statements in the same scope, no declarations.
VisitStatements(node->statements());
@@ -61,6 +65,7 @@ void BytecodeGenerator::VisitBlock(Block* node) {
VisitStatements(node->statements());
}
}
+ builder().LeaveBlock();
}
@@ -72,8 +77,6 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
UNIMPLEMENTED();
break;
case VariableLocation::PARAMETER:
- UNIMPLEMENTED();
- break;
case VariableLocation::LOCAL:
// Details stored in scope, i.e. variable index.
break;
@@ -85,17 +88,17 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
}
-void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* node) {
+void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* node) {
+void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* node) {
+void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
UNIMPLEMENTED();
}
@@ -105,36 +108,57 @@ void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
}
-void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* node) {
- UNIMPLEMENTED();
+void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
+ // TODO(oth): For control-flow it could be useful to signal empty paths here.
}
-void BytecodeGenerator::VisitIfStatement(IfStatement* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
+ BytecodeLabel else_start, else_end;
+ // TODO(oth): Spot easy cases where there code would not need to
+ // emit the then block or the else block, e.g. condition is
+ // obviously true/1/false/0.
+ Visit(stmt->condition());
+ builder().CastAccumulatorToBoolean();
+ builder().JumpIfFalse(&else_start);
+
+ Visit(stmt->then_statement());
+ builder().Jump(&else_end);
+ builder().Bind(&else_start);
+
+ Visit(stmt->else_statement());
+ builder().Bind(&else_end);
+}
-void BytecodeGenerator::VisitContinueStatement(ContinueStatement* node) {
+void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
+ SloppyBlockFunctionStatement* stmt) {
+ Visit(stmt->statement());
+}
+
+
+void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitBreakStatement(BreakStatement* node) {
+void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitReturnStatement(ReturnStatement* node) {
- Visit(node->expression());
+void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
+ Visit(stmt->expression());
builder().Return();
}
-void BytecodeGenerator::VisitWithStatement(WithStatement* node) {
+void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
+void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
UNIMPLEMENTED();
}
@@ -142,70 +166,66 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); }
-void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* node) {
+void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitWhileStatement(WhileStatement* node) {
+void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitForStatement(ForStatement* node) {
+void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitForInStatement(ForInStatement* node) {
+void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitForOfStatement(ForOfStatement* node) {
+void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* node) {
+void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* node) {
+void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* node) {
+void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* node) {
+void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitClassLiteral(ClassLiteral* node) {
+void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
UNIMPLEMENTED();
}
void BytecodeGenerator::VisitNativeFunctionLiteral(
- NativeFunctionLiteral* node) {
+ NativeFunctionLiteral* expr) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitConditional(Conditional* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitConditional(Conditional* expr) { UNIMPLEMENTED(); }
void BytecodeGenerator::VisitLiteral(Literal* expr) {
- if (expr->IsPropertyName()) {
- UNIMPLEMENTED();
- }
-
Handle<Object> value = expr->value();
if (value->IsSmi()) {
builder().LoadLiteral(Smi::cast(*value));
@@ -220,37 +240,55 @@ void BytecodeGenerator::VisitLiteral(Literal* expr) {
} else if (value->IsTheHole()) {
builder().LoadTheHole();
} else {
- UNIMPLEMENTED();
+ builder().LoadLiteral(value);
}
}
-void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
+void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
+void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
+void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
UNIMPLEMENTED();
}
void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
- Variable* variable = proxy->var();
+ VisitVariableLoad(proxy->var());
+}
+
+
+void BytecodeGenerator::VisitVariableLoad(Variable* variable) {
switch (variable->location()) {
case VariableLocation::LOCAL: {
Register source(variable->index());
builder().LoadAccumulatorWithRegister(source);
break;
}
- case VariableLocation::GLOBAL:
+ case VariableLocation::PARAMETER: {
+ // The parameter indices are shifted by 1 (receiver is variable
+ // index -1 but is parameter index 0 in BytecodeArrayBuilder).
+ Register source(builder().Parameter(variable->index() + 1));
+ builder().LoadAccumulatorWithRegister(source);
+ break;
+ }
+ case VariableLocation::GLOBAL: {
+ // Global var, const, or let variable.
+ // TODO(rmcilroy): If context chain depth is short enough, do this using
+ // a generic version of LoadGlobalViaContextStub rather than calling the
+ // runtime.
+ DCHECK(variable->IsStaticGlobalObjectProperty());
+ builder().LoadGlobal(variable->index());
+ break;
+ }
case VariableLocation::UNALLOCATED:
- case VariableLocation::PARAMETER:
case VariableLocation::CONTEXT:
case VariableLocation::LOOKUP:
UNIMPLEMENTED();
@@ -260,14 +298,49 @@ void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
void BytecodeGenerator::VisitAssignment(Assignment* expr) {
DCHECK(expr->target()->IsValidReferenceExpression());
+ TemporaryRegisterScope temporary_register_scope(&builder_);
+ Register object, key;
// Left-hand side can only be a property, a global or a variable slot.
Property* property = expr->target()->AsProperty();
LhsKind assign_type = Property::GetAssignType(property);
- DCHECK(!expr->is_compound());
- Visit(expr->value());
+ // Evaluate LHS expression.
+ switch (assign_type) {
+ case VARIABLE:
+ // Nothing to do to evaluate variable assignment LHS.
+ break;
+ case NAMED_PROPERTY:
+ object = temporary_register_scope.NewRegister();
+ key = temporary_register_scope.NewRegister();
+ Visit(property->obj());
+ builder().StoreAccumulatorInRegister(object);
+ builder().LoadLiteral(property->key()->AsLiteral()->AsPropertyName());
+ builder().StoreAccumulatorInRegister(key);
+ break;
+ case KEYED_PROPERTY:
+ object = temporary_register_scope.NewRegister();
+ key = temporary_register_scope.NewRegister();
+ Visit(property->obj());
+ builder().StoreAccumulatorInRegister(object);
+ Visit(property->key());
+ builder().StoreAccumulatorInRegister(key);
+ break;
+ case NAMED_SUPER_PROPERTY:
+ case KEYED_SUPER_PROPERTY:
+ UNIMPLEMENTED();
+ }
+
+ // Evaluate the value and potentially handle compound assignments by loading
+ // the left-hand side value and performing a binary operation.
+ if (expr->is_compound()) {
+ UNIMPLEMENTED();
+ } else {
+ Visit(expr->value());
+ }
+ // Store the value.
+ FeedbackVectorICSlot slot = expr->AssignmentSlot();
switch (assign_type) {
case VARIABLE: {
Variable* variable = expr->target()->AsVariableProxy()->var();
@@ -277,7 +350,13 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
break;
}
case NAMED_PROPERTY:
+ builder().StoreNamedProperty(object, key, feedback_index(slot),
+ language_mode());
+ break;
case KEYED_PROPERTY:
+ builder().StoreKeyedProperty(object, key, feedback_index(slot),
+ language_mode());
+ break;
case NAMED_SUPER_PROPERTY:
case KEYED_SUPER_PROPERTY:
UNIMPLEMENTED();
@@ -285,30 +364,111 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) {
}
-void BytecodeGenerator::VisitYield(Yield* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitYield(Yield* expr) { UNIMPLEMENTED(); }
-void BytecodeGenerator::VisitThrow(Throw* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitThrow(Throw* expr) { UNIMPLEMENTED(); }
-void BytecodeGenerator::VisitProperty(Property* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
+ LhsKind property_kind = Property::GetAssignType(expr);
+ FeedbackVectorICSlot slot = expr->PropertyFeedbackSlot();
+ switch (property_kind) {
+ case VARIABLE:
+ UNREACHABLE();
+ case NAMED_PROPERTY: {
+ builder().LoadLiteral(expr->key()->AsLiteral()->AsPropertyName());
+ builder().LoadNamedProperty(obj, feedback_index(slot), language_mode());
+ break;
+ }
+ case KEYED_PROPERTY: {
+ Visit(expr->key());
+ builder().LoadKeyedProperty(obj, feedback_index(slot), language_mode());
+ break;
+ }
+ case NAMED_SUPER_PROPERTY:
+ case KEYED_SUPER_PROPERTY:
+ UNIMPLEMENTED();
+ }
+}
-void BytecodeGenerator::VisitCall(Call* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitProperty(Property* expr) {
+ TemporaryRegisterScope temporary_register_scope(&builder_);
+ Register obj = temporary_register_scope.NewRegister();
+ Visit(expr->obj());
+ builder().StoreAccumulatorInRegister(obj);
+ VisitPropertyLoad(obj, expr);
+}
-void BytecodeGenerator::VisitCallNew(CallNew* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitCall(Call* expr) {
+ Expression* callee_expr = expr->expression();
+ Call::CallType call_type = expr->GetCallType(isolate());
+ // Prepare the callee and the receiver to the function call. This depends on
+ // the semantics of the underlying call type.
+ TemporaryRegisterScope temporary_register_scope(&builder_);
+ Register callee = temporary_register_scope.NewRegister();
+ Register receiver = temporary_register_scope.NewRegister();
+
+ switch (call_type) {
+ case Call::PROPERTY_CALL: {
+ Property* property = callee_expr->AsProperty();
+ if (property->IsSuperAccess()) {
+ UNIMPLEMENTED();
+ }
+ Visit(property->obj());
+ builder().StoreAccumulatorInRegister(receiver);
+ // Perform a property load of the callee.
+ VisitPropertyLoad(receiver, property);
+ builder().StoreAccumulatorInRegister(callee);
+ break;
+ }
+ case Call::GLOBAL_CALL: {
+ // Receiver is undefined for global calls.
+ builder().LoadUndefined().StoreAccumulatorInRegister(receiver);
+ // Load callee as a global variable.
+ VariableProxy* proxy = callee_expr->AsVariableProxy();
+ VisitVariableLoad(proxy->var());
+ builder().StoreAccumulatorInRegister(callee);
+ break;
+ }
+ case Call::LOOKUP_SLOT_CALL:
+ case Call::SUPER_CALL:
+ case Call::POSSIBLY_EVAL_CALL:
+ case Call::OTHER_CALL:
+ UNIMPLEMENTED();
+ }
+
+ // Evaluate all arguments to the function call and store in sequential
+ // registers.
+ ZoneList<Expression*>* args = expr->arguments();
+ for (int i = 0; i < args->length(); ++i) {
+ Visit(args->at(i));
+ Register arg = temporary_register_scope.NewRegister();
+ DCHECK(arg.index() - i == receiver.index() + 1);
+ builder().StoreAccumulatorInRegister(arg);
+ }
+
+ // TODO(rmcilroy): Deal with possible direct eval here?
+ // TODO(rmcilroy): Use CallIC to allow call type feedback.
+ builder().Call(callee, receiver, args->length());
+}
-void BytecodeGenerator::VisitCallRuntime(CallRuntime* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); }
-void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
+
+void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { UNIMPLEMENTED(); }
+
+
+void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitCountOperation(CountOperation* node) {
+void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
UNIMPLEMENTED();
}
@@ -327,26 +487,41 @@ void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
}
-void BytecodeGenerator::VisitCompareOperation(CompareOperation* node) {
- UNIMPLEMENTED();
+void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
+ Token::Value op = expr->op();
+ Expression* left = expr->left();
+ Expression* right = expr->right();
+
+ TemporaryRegisterScope temporary_register_scope(&builder_);
+ Register temporary = temporary_register_scope.NewRegister();
+
+ Visit(left);
+ builder().StoreAccumulatorInRegister(temporary);
+ Visit(right);
+ builder().CompareOperation(op, temporary, language_mode());
}
-void BytecodeGenerator::VisitSpread(Spread* node) { UNIMPLEMENTED(); }
+void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
+
+void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
+ UNREACHABLE();
+}
-void BytecodeGenerator::VisitThisFunction(ThisFunction* node) {
+
+void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
UNIMPLEMENTED();
}
-void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* node) {
+void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
UNIMPLEMENTED();
}
void BytecodeGenerator::VisitSuperPropertyReference(
- SuperPropertyReference* node) {
+ SuperPropertyReference* expr) {
UNIMPLEMENTED();
}
@@ -365,6 +540,16 @@ void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) {
builder().BinaryOperation(op, temporary);
}
+
+LanguageMode BytecodeGenerator::language_mode() const {
+ return info()->language_mode();
+}
+
+
+int BytecodeGenerator::feedback_index(FeedbackVectorICSlot slot) const {
+ return info()->feedback_vector()->GetIndex(slot);
+}
+
} // namespace interpreter
} // namespace internal
} // namespace v8