Chromium Code Reviews| 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 |