Index: src/interpreter/bytecode-generator.cc |
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc |
index 86d417160ef67d6462b980b8614e19523a3432a5..373baf958ca0701acb46dbc911862316301d56ae 100644 |
--- a/src/interpreter/bytecode-generator.cc |
+++ b/src/interpreter/bytecode-generator.cc |
@@ -16,7 +16,9 @@ namespace internal { |
namespace interpreter { |
BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) |
- : builder_(isolate, zone) { |
+ : builder_(isolate, zone), |
+ globals_(0, zone), |
+ current_context_(Register::function_context()) { |
InitializeAstVisitor(isolate, zone); |
} |
@@ -68,11 +70,19 @@ void BytecodeGenerator::VisitBlock(Block* node) { |
void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
Variable* variable = decl->proxy()->var(); |
+ VariableMode mode = decl->mode(); |
+ bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; |
+ DCHECK(!hole_init); // TODO(rmcilroy): Implement hole_init support. |
oth
2015/10/01 12:02:26
if (!hole_init) UNIMPLEMENTED().
rmcilroy
2015/10/06 14:10:26
Done.
|
switch (variable->location()) { |
case VariableLocation::GLOBAL: |
- case VariableLocation::UNALLOCATED: |
- UNIMPLEMENTED(); |
+ case VariableLocation::UNALLOCATED: { |
+ Handle<Oddball> value = variable->binding_needs_init() |
+ ? isolate()->factory()->the_hole_value() |
+ : isolate()->factory()->undefined_value(); |
+ globals()->push_back(variable->name()); |
+ globals()->push_back(value); |
break; |
+ } |
case VariableLocation::PARAMETER: |
case VariableLocation::LOCAL: |
// Details stored in scope, i.e. variable index. |
@@ -86,7 +96,24 @@ void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { |
void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { |
- UNIMPLEMENTED(); |
+ Variable* variable = decl->proxy()->var(); |
+ switch (variable->location()) { |
+ case VariableLocation::GLOBAL: |
+ case VariableLocation::UNALLOCATED: { |
+ Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo( |
+ decl->fun(), info()->script(), info()); |
+ // Check for stack-overflow exception. |
+ if (function.is_null()) return SetStackOverflow(); |
+ globals()->push_back(variable->name()); |
+ globals()->push_back(function); |
+ break; |
+ } |
+ case VariableLocation::PARAMETER: |
+ case VariableLocation::LOCAL: |
+ case VariableLocation::CONTEXT: |
+ case VariableLocation::LOOKUP: |
+ UNIMPLEMENTED(); |
+ } |
} |
@@ -100,6 +127,34 @@ void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) { |
} |
+void BytecodeGenerator::VisitDeclarations( |
+ ZoneList<Declaration*>* declarations) { |
+ DCHECK(globals()->empty()); |
+ AstVisitor::VisitDeclarations(declarations); |
+ if (globals()->empty()) return; |
+ int array_index = 0; |
+ Handle<FixedArray> data = isolate()->factory()->NewFixedArray( |
+ static_cast<int>(globals()->size()), TENURED); |
+ for (Handle<Object> obj : *globals()) data->set(array_index++, *obj); |
+ int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | |
+ DeclareGlobalsNativeFlag::encode(info()->is_native()) | |
+ DeclareGlobalsLanguageMode::encode(language_mode()); |
+ |
+ TemporaryRegisterScope temporary_register_scope(&builder_); |
+ Register pairs = temporary_register_scope.NewRegister(); |
+ builder().LoadLiteral(data); |
+ builder().StoreAccumulatorInRegister(pairs); |
+ |
+ Register flags = temporary_register_scope.NewRegister(); |
+ builder().LoadLiteral(Smi::FromInt(encoded_flags)); |
+ builder().StoreAccumulatorInRegister(flags); |
+ DCHECK(flags.index() == pairs.index() + 1); |
+ |
+ builder().CallRuntime(Runtime::kDeclareGlobals, pairs, 2); |
+ globals()->clear(); |
+} |
+ |
+ |
void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
Visit(stmt->expression()); |
} |
@@ -258,11 +313,12 @@ void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
- VisitVariableLoad(proxy->var()); |
+ VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
} |
-void BytecodeGenerator::VisitVariableLoad(Variable* variable) { |
+void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
+ FeedbackVectorICSlot slot) { |
switch (variable->location()) { |
case VariableLocation::LOCAL: { |
Register source(variable->index()); |
@@ -285,7 +341,66 @@ void BytecodeGenerator::VisitVariableLoad(Variable* variable) { |
builder().LoadGlobal(variable->index()); |
break; |
} |
- case VariableLocation::UNALLOCATED: |
+ case VariableLocation::UNALLOCATED: { |
+ TemporaryRegisterScope temporary_register_scope(&builder_); |
+ Register obj = temporary_register_scope.NewRegister(); |
+ builder().LoadContextSlot(current_context(), |
+ Context::GLOBAL_OBJECT_INDEX); |
+ builder().StoreAccumulatorInRegister(obj); |
+ builder().LoadLiteral(variable->name()); |
+ builder().LoadNamedProperty(obj, feedback_index(slot), language_mode()); |
+ break; |
+ } |
+ case VariableLocation::CONTEXT: |
+ case VariableLocation::LOOKUP: |
+ UNIMPLEMENTED(); |
+ } |
+} |
+ |
+ |
+void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
+ FeedbackVectorICSlot slot) { |
+ switch (variable->location()) { |
+ case VariableLocation::LOCAL: { |
+ // TODO(rmcilroy): support const mode initialization. |
+ Register destination(variable->index()); |
+ builder().StoreAccumulatorInRegister(destination); |
+ break; |
+ } |
+ case VariableLocation::PARAMETER: { |
+ // The parameter indices are shifted by 1 (receiver is variable |
+ // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
+ Register destination(builder().Parameter(variable->index() + 1)); |
+ builder().StoreAccumulatorInRegister(destination); |
+ 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().StoreGlobal(variable->index(), language_mode()); |
+ break; |
+ } |
+ case VariableLocation::UNALLOCATED: { |
+ TemporaryRegisterScope temporary_register_scope(&builder_); |
+ Register value = temporary_register_scope.NewRegister(); |
+ Register obj = temporary_register_scope.NewRegister(); |
+ Register name = temporary_register_scope.NewRegister(); |
+ // TODO(rmcilroy): Investigate whether we can avoid having to stash the |
+ // value in a register. |
+ builder().StoreAccumulatorInRegister(value); |
+ builder().LoadContextSlot(current_context(), |
+ Context::GLOBAL_OBJECT_INDEX); |
+ builder().StoreAccumulatorInRegister(obj); |
+ builder().LoadLiteral(variable->name()); |
+ builder().StoreAccumulatorInRegister(name); |
+ builder().LoadAccumulatorWithRegister(value); |
+ builder().StoreNamedProperty(obj, name, feedback_index(slot), |
+ language_mode()); |
+ break; |
+ } |
case VariableLocation::CONTEXT: |
case VariableLocation::LOOKUP: |
UNIMPLEMENTED(); |
@@ -341,9 +456,7 @@ void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
switch (assign_type) { |
case VARIABLE: { |
Variable* variable = expr->target()->AsVariableProxy()->var(); |
- DCHECK(variable->location() == VariableLocation::LOCAL); |
- Register destination(variable->index()); |
- builder().StoreAccumulatorInRegister(destination); |
+ VisitVariableAssignment(variable, slot); |
break; |
} |
case NAMED_PROPERTY: |
@@ -427,7 +540,7 @@ void BytecodeGenerator::VisitCall(Call* expr) { |
builder().LoadUndefined().StoreAccumulatorInRegister(receiver); |
// Load callee as a global variable. |
VariableProxy* proxy = callee_expr->AsVariableProxy(); |
- VisitVariableLoad(proxy->var()); |
+ VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
builder().StoreAccumulatorInRegister(callee); |
break; |
} |
@@ -570,6 +683,9 @@ int BytecodeGenerator::feedback_index(FeedbackVectorICSlot slot) const { |
return info()->feedback_vector()->GetIndex(slot); |
} |
+ |
+Register BytecodeGenerator::current_context() const { return current_context_; } |
+ |
} // namespace interpreter |
} // namespace internal |
} // namespace v8 |