Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1403943004: [Interpreter] Add support for local context loads and stores. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@int_contextchain
Patch Set: Add back outer_ &&] Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/interpreter/bytecode-generator.h" 5 #include "src/interpreter/bytecode-generator.h"
6 6
7 #include <stack> 7 #include <stack>
8 8
9 #include "src/compiler.h" 9 #include "src/compiler.h"
10 #include "src/interpreter/control-flow-builders.h" 10 #include "src/interpreter/control-flow-builders.h"
11 #include "src/objects.h" 11 #include "src/objects.h"
12 #include "src/parser.h" 12 #include "src/parser.h"
13 #include "src/scopes.h" 13 #include "src/scopes.h"
14 #include "src/token.h" 14 #include "src/token.h"
15 15
16 namespace v8 { 16 namespace v8 {
17 namespace internal { 17 namespace internal {
18 namespace interpreter { 18 namespace interpreter {
19 19
20 20
21 // Scoped class tracking context objects created by the visitor. Represents 21 // Scoped class tracking context objects created by the visitor. Represents
22 // mutations of the context chain within the function body, allowing pushing and 22 // mutations of the context chain within the function body, allowing pushing and
23 // popping of the current {context_register} during visitation. 23 // popping of the current {context_register} during visitation.
24 class BytecodeGenerator::ContextScope BASE_EMBEDDED { 24 class BytecodeGenerator::ContextScope BASE_EMBEDDED {
25 public: 25 public:
26 explicit ContextScope(BytecodeGenerator* generator, 26 ContextScope(BytecodeGenerator* generator, Scope* scope,
27 bool is_function_context = false) 27 bool should_pop_context = true)
28 : generator_(generator), 28 : generator_(generator),
29 outer_(generator_->current_context()), 29 scope_(scope),
30 is_function_context_(is_function_context) { 30 outer_(generator_->execution_context()),
31 DCHECK(!is_function_context || 31 register_(generator_->NextContextRegister()),
32 outer_.index() == Register::function_context().index()); 32 depth_(0),
33 Register new_context_reg = NewContextRegister(); 33 should_pop_context_(should_pop_context) {
34 generator_->builder()->PushContext(new_context_reg); 34 if (outer_) {
35 generator_->set_current_context(new_context_reg); 35 depth_ = outer_->depth_ + 1;
36 generator_->builder()->PushContext(register_);
37 }
38 generator_->set_execution_context(this);
36 } 39 }
37 40
38 ~ContextScope() { 41 ~ContextScope() {
39 if (!is_function_context_) { 42 if (outer_ && should_pop_context_) {
40 generator_->builder()->PopContext(outer_); 43 generator_->builder()->PopContext(outer_->reg());
41 } 44 }
42 generator_->set_current_context(outer_); 45 generator_->set_execution_context(outer_);
43 } 46 }
44 47
45 private: 48 // Returns the execution context for the given |scope| if it is a function
46 Register NewContextRegister() const { 49 // local execution context, otherwise returns nullptr.
47 if (outer_.index() == Register::function_context().index()) { 50 ContextScope* Previous(Scope* scope) {
48 return generator_->builder()->first_context_register(); 51 int depth = scope_->ContextChainLength(scope);
49 } else { 52 if (depth > depth_) {
50 DCHECK_LT(outer_.index(), 53 return nullptr;
51 generator_->builder()->last_context_register().index());
52 return Register(outer_.index() + 1);
53 } 54 }
55
56 ContextScope* previous = this;
57 for (int i = depth; i > 0; --i) {
58 previous = previous->outer_;
59 }
60 DCHECK_EQ(previous->scope_, scope);
61 return previous;
54 } 62 }
55 63
64 Scope* scope() const { return scope_; }
65 Register reg() const { return register_; }
66
67 private:
56 BytecodeGenerator* generator_; 68 BytecodeGenerator* generator_;
57 Register outer_; 69 Scope* scope_;
58 bool is_function_context_; 70 ContextScope* outer_;
71 Register register_;
72 int depth_;
73 bool should_pop_context_;
59 }; 74 };
60 75
61 76
62 // Scoped class for tracking control statements entered by the 77 // Scoped class for tracking control statements entered by the
63 // visitor. The pattern derives AstGraphBuilder::ControlScope. 78 // visitor. The pattern derives AstGraphBuilder::ControlScope.
64 class BytecodeGenerator::ControlScope BASE_EMBEDDED { 79 class BytecodeGenerator::ControlScope BASE_EMBEDDED {
65 public: 80 public:
66 explicit ControlScope(BytecodeGenerator* generator) 81 explicit ControlScope(BytecodeGenerator* generator)
67 : generator_(generator), outer_(generator->control_scope()) { 82 : generator_(generator), outer_(generator->execution_control()) {
68 generator_->set_control_scope(this); 83 generator_->set_execution_control(this);
69 } 84 }
70 virtual ~ControlScope() { generator_->set_control_scope(outer()); } 85 virtual ~ControlScope() { generator_->set_execution_control(outer()); }
71 86
72 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } 87 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); }
73 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } 88 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); }
74 89
75 protected: 90 protected:
76 enum Command { CMD_BREAK, CMD_CONTINUE }; 91 enum Command { CMD_BREAK, CMD_CONTINUE };
77 void PerformCommand(Command command, Statement* statement); 92 void PerformCommand(Command command, Statement* statement);
78 virtual bool Execute(Command command, Statement* statement) = 0; 93 virtual bool Execute(Command command, Statement* statement) = 0;
79 94
80 BytecodeGenerator* generator() const { return generator_; } 95 BytecodeGenerator* generator() const { return generator_; }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 } 146 }
132 147
133 148
134 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) 149 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
135 : isolate_(isolate), 150 : isolate_(isolate),
136 zone_(zone), 151 zone_(zone),
137 builder_(isolate, zone), 152 builder_(isolate, zone),
138 info_(nullptr), 153 info_(nullptr),
139 scope_(nullptr), 154 scope_(nullptr),
140 globals_(0, zone), 155 globals_(0, zone),
141 control_scope_(nullptr), 156 execution_control_(nullptr),
142 current_context_(Register::function_context()) { 157 execution_context_(nullptr) {
143 InitializeAstVisitor(isolate); 158 InitializeAstVisitor(isolate);
144 } 159 }
145 160
146 161
147 BytecodeGenerator::~BytecodeGenerator() {} 162 BytecodeGenerator::~BytecodeGenerator() {}
148 163
149 164
150 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 165 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
151 set_info(info); 166 set_info(info);
152 set_scope(info->scope()); 167 set_scope(info->scope());
153 168
169 // Initialize the incoming context.
170 ContextScope incoming_context(this, scope(), false);
171
154 builder()->set_parameter_count(info->num_parameters_including_this()); 172 builder()->set_parameter_count(info->num_parameters_including_this());
155 builder()->set_locals_count(scope()->num_stack_slots()); 173 builder()->set_locals_count(scope()->num_stack_slots());
156 builder()->set_context_count(scope()->MaxNestedContextChainLength()); 174 builder()->set_context_count(scope()->MaxNestedContextChainLength());
157 175
158 // Build function context only if there are context allocated variables. 176 // Build function context only if there are context allocated variables.
159 if (scope()->NeedsContext()) { 177 if (scope()->NeedsContext()) {
160 // Push a new inner context scope for the function. 178 // Push a new inner context scope for the function.
161 VisitNewLocalFunctionContext(); 179 VisitNewLocalFunctionContext();
162 ContextScope top_context(this, true); 180 ContextScope local_function_context(this, scope(), false);
181 VisitBuildLocalActivationContext();
163 MakeBytecodeBody(); 182 MakeBytecodeBody();
164 } else { 183 } else {
165 MakeBytecodeBody(); 184 MakeBytecodeBody();
166 } 185 }
167 186
168 set_scope(nullptr); 187 set_scope(nullptr);
169 set_info(nullptr); 188 set_info(nullptr);
170 return builder_.ToBytecodeArray(); 189 return builder_.ToBytecodeArray();
171 } 190 }
172 191
173 192
174 void BytecodeGenerator::MakeBytecodeBody() { 193 void BytecodeGenerator::MakeBytecodeBody() {
175 // Visit declarations within the function scope. 194 // Visit declarations within the function scope.
176 VisitDeclarations(scope()->declarations()); 195 VisitDeclarations(scope()->declarations());
177 196
178 // Visit statements in the function body. 197 // Visit statements in the function body.
179 VisitStatements(info()->literal()->body()); 198 VisitStatements(info()->literal()->body());
180 } 199 }
181 200
182 201
183 void BytecodeGenerator::VisitBlock(Block* node) { 202 void BytecodeGenerator::VisitBlock(Block* stmt) {
184 builder()->EnterBlock(); 203 builder()->EnterBlock();
185 if (node->scope() == NULL) { 204 if (stmt->scope() == NULL) {
186 // Visit statements in the same scope, no declarations. 205 // Visit statements in the same scope, no declarations.
187 VisitStatements(node->statements()); 206 VisitStatements(stmt->statements());
188 } else { 207 } else {
189 // Visit declarations and statements in a block scope. 208 // Visit declarations and statements in a block scope.
190 if (node->scope()->ContextLocalCount() > 0) { 209 if (stmt->scope()->NeedsContext()) {
191 UNIMPLEMENTED(); 210 VisitNewLocalBlockContext(stmt->scope());
211 ContextScope scope(this, stmt->scope());
212 VisitDeclarations(stmt->scope()->declarations());
213 VisitStatements(stmt->statements());
192 } else { 214 } else {
193 VisitDeclarations(node->scope()->declarations()); 215 VisitDeclarations(stmt->scope()->declarations());
194 VisitStatements(node->statements()); 216 VisitStatements(stmt->statements());
195 } 217 }
196 } 218 }
197 builder()->LeaveBlock(); 219 builder()->LeaveBlock();
198 } 220 }
199 221
200 222
201 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { 223 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
202 Variable* variable = decl->proxy()->var(); 224 Variable* variable = decl->proxy()->var();
203 VariableMode mode = decl->mode(); 225 VariableMode mode = decl->mode();
226 // Const and let variables are initialized with the hole so that we can
227 // check that they are only assigned once.
204 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; 228 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
205 if (hole_init) {
206 UNIMPLEMENTED();
207 }
208 switch (variable->location()) { 229 switch (variable->location()) {
209 case VariableLocation::GLOBAL: 230 case VariableLocation::GLOBAL:
210 case VariableLocation::UNALLOCATED: { 231 case VariableLocation::UNALLOCATED: {
211 Handle<Oddball> value = variable->binding_needs_init() 232 Handle<Oddball> value = variable->binding_needs_init()
212 ? isolate()->factory()->the_hole_value() 233 ? isolate()->factory()->the_hole_value()
213 : isolate()->factory()->undefined_value(); 234 : isolate()->factory()->undefined_value();
214 globals()->push_back(variable->name()); 235 globals()->push_back(variable->name());
215 globals()->push_back(value); 236 globals()->push_back(value);
216 break; 237 break;
217 } 238 }
239 case VariableLocation::LOCAL:
240 if (hole_init) {
241 Register destination(variable->index());
242 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
243 }
244 break;
218 case VariableLocation::PARAMETER: 245 case VariableLocation::PARAMETER:
219 case VariableLocation::LOCAL: 246 if (hole_init) {
220 // Details stored in scope, i.e. variable index. 247 // The parameter indices are shifted by 1 (receiver is variable
248 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
249 Register destination(builder()->Parameter(variable->index() + 1));
250 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
251 }
221 break; 252 break;
222 case VariableLocation::CONTEXT: 253 case VariableLocation::CONTEXT:
254 if (hole_init) {
255 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
256 variable->index());
257 }
258 break;
223 case VariableLocation::LOOKUP: 259 case VariableLocation::LOOKUP:
224 UNIMPLEMENTED(); 260 UNIMPLEMENTED();
225 break; 261 break;
226 } 262 }
227 } 263 }
228 264
229 265
230 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { 266 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
231 Variable* variable = decl->proxy()->var(); 267 Variable* variable = decl->proxy()->var();
232 switch (variable->location()) { 268 switch (variable->location()) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 } 355 }
320 356
321 357
322 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( 358 void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
323 SloppyBlockFunctionStatement* stmt) { 359 SloppyBlockFunctionStatement* stmt) {
324 Visit(stmt->statement()); 360 Visit(stmt->statement());
325 } 361 }
326 362
327 363
328 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { 364 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
329 control_scope()->Continue(stmt->target()); 365 execution_control()->Continue(stmt->target());
330 } 366 }
331 367
332 368
333 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 369 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
334 control_scope()->Break(stmt->target()); 370 execution_control()->Break(stmt->target());
335 } 371 }
336 372
337 373
338 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 374 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
339 Visit(stmt->expression()); 375 Visit(stmt->expression());
340 builder()->Return(); 376 builder()->Return();
341 } 377 }
342 378
343 379
344 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 380 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
345 UNIMPLEMENTED(); 381 UNIMPLEMENTED();
346 } 382 }
347 383
348 384
349 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 385 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
350 UNIMPLEMENTED(); 386 UNIMPLEMENTED();
351 } 387 }
352 388
353 389
354 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } 390 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); }
355 391
356 392
357 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 393 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
358 LoopBuilder loop_builder(builder()); 394 LoopBuilder loop_builder(builder());
359 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 395 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
360 396
361 BytecodeLabel body_label, condition_label, done_label; 397 BytecodeLabel body_label, condition_label, done_label;
362 builder()->Bind(&body_label); 398 builder()->Bind(&body_label);
363 Visit(stmt->body()); 399 Visit(stmt->body());
364 builder()->Bind(&condition_label); 400 builder()->Bind(&condition_label);
365 Visit(stmt->cond()); 401 Visit(stmt->cond());
366 builder()->JumpIfTrue(&body_label); 402 builder()->JumpIfTrue(&body_label);
367 builder()->Bind(&done_label); 403 builder()->Bind(&done_label);
368 404
369 loop_builder.SetBreakTarget(done_label); 405 loop_builder.SetBreakTarget(done_label);
370 loop_builder.SetContinueTarget(condition_label); 406 loop_builder.SetContinueTarget(condition_label);
371 } 407 }
372 408
373 409
374 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 410 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
375 LoopBuilder loop_builder(builder()); 411 LoopBuilder loop_builder(builder());
376 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 412 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
377 413
378 BytecodeLabel body_label, condition_label, done_label; 414 BytecodeLabel body_label, condition_label, done_label;
379 builder()->Jump(&condition_label); 415 builder()->Jump(&condition_label);
380 builder()->Bind(&body_label); 416 builder()->Bind(&body_label);
381 Visit(stmt->body()); 417 Visit(stmt->body());
382 builder()->Bind(&condition_label); 418 builder()->Bind(&condition_label);
383 Visit(stmt->cond()); 419 Visit(stmt->cond());
384 builder()->JumpIfTrue(&body_label); 420 builder()->JumpIfTrue(&body_label);
385 builder()->Bind(&done_label); 421 builder()->Bind(&done_label);
386 422
387 loop_builder.SetBreakTarget(done_label); 423 loop_builder.SetBreakTarget(done_label);
388 loop_builder.SetContinueTarget(condition_label); 424 loop_builder.SetContinueTarget(condition_label);
389 } 425 }
390 426
391 427
392 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 428 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
393 LoopBuilder loop_builder(builder()); 429 LoopBuilder loop_builder(builder());
394 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 430 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
395 431
396 if (stmt->init() != nullptr) { 432 if (stmt->init() != nullptr) {
397 Visit(stmt->init()); 433 Visit(stmt->init());
398 } 434 }
399 435
400 BytecodeLabel body_label, condition_label, next_label, done_label; 436 BytecodeLabel body_label, condition_label, next_label, done_label;
401 if (stmt->cond() != nullptr) { 437 if (stmt->cond() != nullptr) {
402 builder()->Jump(&condition_label); 438 builder()->Jump(&condition_label);
403 } 439 }
404 builder()->Bind(&body_label); 440 builder()->Bind(&body_label);
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 } 624 }
589 break; 625 break;
590 case ObjectLiteral::Property::SETTER: 626 case ObjectLiteral::Property::SETTER:
591 if (property->emit_store()) { 627 if (property->emit_store()) {
592 accessor_table.lookup(literal_key)->second->setter = property; 628 accessor_table.lookup(literal_key)->second->setter = property;
593 } 629 }
594 break; 630 break;
595 } 631 }
596 } 632 }
597 633
598 // Create nodes to define accessors, using only a single call to the runtime 634 // Define accessors, using only a single call to the runtime for each pair of
599 // for each pair of corresponding getters and setters. 635 // corresponding getters and setters.
600 for (AccessorTable::Iterator it = accessor_table.begin(); 636 for (AccessorTable::Iterator it = accessor_table.begin();
601 it != accessor_table.end(); ++it) { 637 it != accessor_table.end(); ++it) {
602 TemporaryRegisterScope inner_temporary_register_scope(builder()); 638 TemporaryRegisterScope inner_temporary_register_scope(builder());
603 Register name = inner_temporary_register_scope.NewRegister(); 639 Register name = inner_temporary_register_scope.NewRegister();
604 Register getter = inner_temporary_register_scope.NewRegister(); 640 Register getter = inner_temporary_register_scope.NewRegister();
605 Register setter = inner_temporary_register_scope.NewRegister(); 641 Register setter = inner_temporary_register_scope.NewRegister();
606 Register attr = inner_temporary_register_scope.NewRegister(); 642 Register attr = inner_temporary_register_scope.NewRegister();
607 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); 643 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr));
608 Visit(it->first); 644 Visit(it->first);
609 builder()->StoreAccumulatorInRegister(name); 645 builder()->StoreAccumulatorInRegister(name);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 727
692 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 728 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
693 // Deep-copy the literal boilerplate. 729 // Deep-copy the literal boilerplate.
694 builder() 730 builder()
695 ->LoadLiteral(expr->constant_elements()) 731 ->LoadLiteral(expr->constant_elements())
696 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true)); 732 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true));
697 733
698 TemporaryRegisterScope temporary_register_scope(builder()); 734 TemporaryRegisterScope temporary_register_scope(builder());
699 Register index, literal; 735 Register index, literal;
700 736
701 // Create nodes to evaluate all the non-constant subexpressions and to store 737 // Evaluate all the non-constant subexpressions and store them into the
702 // them into the newly cloned array. 738 // newly cloned array.
703 bool literal_in_accumulator = true; 739 bool literal_in_accumulator = true;
704 for (int array_index = 0; array_index < expr->values()->length(); 740 for (int array_index = 0; array_index < expr->values()->length();
705 array_index++) { 741 array_index++) {
706 Expression* subexpr = expr->values()->at(array_index); 742 Expression* subexpr = expr->values()->at(array_index);
707 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 743 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
708 if (subexpr->IsSpread()) { 744 if (subexpr->IsSpread()) {
709 // TODO(rmcilroy): Deal with spread expressions. 745 // TODO(rmcilroy): Deal with spread expressions.
710 UNIMPLEMENTED(); 746 UNIMPLEMENTED();
711 } 747 }
712 748
(...skipping 24 matching lines...) Expand all
737 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 773 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
738 } 774 }
739 775
740 776
741 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 777 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
742 FeedbackVectorSlot slot) { 778 FeedbackVectorSlot slot) {
743 switch (variable->location()) { 779 switch (variable->location()) {
744 case VariableLocation::LOCAL: { 780 case VariableLocation::LOCAL: {
745 Register source(variable->index()); 781 Register source(variable->index());
746 builder()->LoadAccumulatorWithRegister(source); 782 builder()->LoadAccumulatorWithRegister(source);
783 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
784 // let variables.
747 break; 785 break;
748 } 786 }
749 case VariableLocation::PARAMETER: { 787 case VariableLocation::PARAMETER: {
750 // The parameter indices are shifted by 1 (receiver is variable 788 // The parameter indices are shifted by 1 (receiver is variable
751 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 789 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
752 Register source(builder()->Parameter(variable->index() + 1)); 790 Register source(builder()->Parameter(variable->index() + 1));
753 builder()->LoadAccumulatorWithRegister(source); 791 builder()->LoadAccumulatorWithRegister(source);
754 break; 792 break;
755 } 793 }
756 case VariableLocation::GLOBAL: { 794 case VariableLocation::GLOBAL: {
757 // Global var, const, or let variable. 795 // Global var, const, or let variable.
758 // TODO(rmcilroy): If context chain depth is short enough, do this using 796 // TODO(rmcilroy): If context chain depth is short enough, do this using
759 // a generic version of LoadGlobalViaContextStub rather than calling the 797 // a generic version of LoadGlobalViaContextStub rather than calling the
760 // runtime. 798 // runtime.
761 DCHECK(variable->IsStaticGlobalObjectProperty()); 799 DCHECK(variable->IsStaticGlobalObjectProperty());
762 builder()->LoadGlobal(variable->index()); 800 builder()->LoadGlobal(variable->index());
763 break; 801 break;
764 } 802 }
765 case VariableLocation::UNALLOCATED: { 803 case VariableLocation::UNALLOCATED: {
766 TemporaryRegisterScope temporary_register_scope(builder()); 804 TemporaryRegisterScope temporary_register_scope(builder());
767 Register obj = temporary_register_scope.NewRegister(); 805 Register obj = temporary_register_scope.NewRegister();
768 builder()->LoadContextSlot(current_context(), 806 builder()->LoadContextSlot(execution_context()->reg(),
769 Context::GLOBAL_OBJECT_INDEX); 807 Context::GLOBAL_OBJECT_INDEX);
770 builder()->StoreAccumulatorInRegister(obj); 808 builder()->StoreAccumulatorInRegister(obj);
771 builder()->LoadLiteral(variable->name()); 809 builder()->LoadLiteral(variable->name());
772 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); 810 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
773 break; 811 break;
774 } 812 }
775 case VariableLocation::CONTEXT: 813 case VariableLocation::CONTEXT: {
814 ContextScope* context = execution_context()->Previous(variable->scope());
815 if (context) {
816 builder()->LoadContextSlot(context->reg(), variable->index());
817 } else {
818 UNIMPLEMENTED();
819 }
820 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
821 // let variables.
822 break;
823 }
776 case VariableLocation::LOOKUP: 824 case VariableLocation::LOOKUP:
777 UNIMPLEMENTED(); 825 UNIMPLEMENTED();
778 } 826 }
779 } 827 }
780 828
781 829
782 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 830 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
783 FeedbackVectorSlot slot) { 831 FeedbackVectorSlot slot) {
784 switch (variable->location()) { 832 switch (variable->location()) {
785 case VariableLocation::LOCAL: { 833 case VariableLocation::LOCAL: {
(...skipping 19 matching lines...) Expand all
805 break; 853 break;
806 } 854 }
807 case VariableLocation::UNALLOCATED: { 855 case VariableLocation::UNALLOCATED: {
808 TemporaryRegisterScope temporary_register_scope(builder()); 856 TemporaryRegisterScope temporary_register_scope(builder());
809 Register value = temporary_register_scope.NewRegister(); 857 Register value = temporary_register_scope.NewRegister();
810 Register obj = temporary_register_scope.NewRegister(); 858 Register obj = temporary_register_scope.NewRegister();
811 Register name = temporary_register_scope.NewRegister(); 859 Register name = temporary_register_scope.NewRegister();
812 // TODO(rmcilroy): Investigate whether we can avoid having to stash the 860 // TODO(rmcilroy): Investigate whether we can avoid having to stash the
813 // value in a register. 861 // value in a register.
814 builder()->StoreAccumulatorInRegister(value); 862 builder()->StoreAccumulatorInRegister(value);
815 builder()->LoadContextSlot(current_context(), 863 builder()->LoadContextSlot(execution_context()->reg(),
816 Context::GLOBAL_OBJECT_INDEX); 864 Context::GLOBAL_OBJECT_INDEX);
817 builder()->StoreAccumulatorInRegister(obj); 865 builder()->StoreAccumulatorInRegister(obj);
818 builder()->LoadLiteral(variable->name()); 866 builder()->LoadLiteral(variable->name());
819 builder()->StoreAccumulatorInRegister(name); 867 builder()->StoreAccumulatorInRegister(name);
820 builder()->LoadAccumulatorWithRegister(value); 868 builder()->LoadAccumulatorWithRegister(value);
821 builder()->StoreNamedProperty(obj, name, feedback_index(slot), 869 builder()->StoreNamedProperty(obj, name, feedback_index(slot),
822 language_mode()); 870 language_mode());
823 break; 871 break;
824 } 872 }
825 case VariableLocation::CONTEXT: 873 case VariableLocation::CONTEXT: {
874 // TODO(rmcilroy): support const mode initialization.
875 ContextScope* context = execution_context()->Previous(variable->scope());
876 if (context) {
877 builder()->StoreContextSlot(context->reg(), variable->index());
878 } else {
879 UNIMPLEMENTED();
880 }
881 break;
882 }
826 case VariableLocation::LOOKUP: 883 case VariableLocation::LOOKUP:
827 UNIMPLEMENTED(); 884 UNIMPLEMENTED();
828 } 885 }
829 } 886 }
830 887
831 888
832 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 889 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
833 DCHECK(expr->target()->IsValidReferenceExpression()); 890 DCHECK(expr->target()->IsValidReferenceExpression());
834 TemporaryRegisterScope temporary_register_scope(builder()); 891 TemporaryRegisterScope temporary_register_scope(builder());
835 Register object, key; 892 Register object, key;
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 builder() 1191 builder()
1135 ->LoadAccumulatorWithRegister(Register::function_closure()) 1192 ->LoadAccumulatorWithRegister(Register::function_closure())
1136 .StoreAccumulatorInRegister(closure) 1193 .StoreAccumulatorInRegister(closure)
1137 .LoadLiteral(scope->GetScopeInfo(isolate())) 1194 .LoadLiteral(scope->GetScopeInfo(isolate()))
1138 .StoreAccumulatorInRegister(scope_info) 1195 .StoreAccumulatorInRegister(scope_info)
1139 .CallRuntime(Runtime::kNewScriptContext, closure, 2); 1196 .CallRuntime(Runtime::kNewScriptContext, closure, 2);
1140 } else { 1197 } else {
1141 builder()->CallRuntime(Runtime::kNewFunctionContext, 1198 builder()->CallRuntime(Runtime::kNewFunctionContext,
1142 Register::function_closure(), 1); 1199 Register::function_closure(), 1);
1143 } 1200 }
1201 }
1202
1203
1204 void BytecodeGenerator::VisitBuildLocalActivationContext() {
1205 Scope* scope = this->scope();
1144 1206
1145 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { 1207 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
1146 UNIMPLEMENTED(); 1208 UNIMPLEMENTED();
1147 } 1209 }
1148 1210
1149 // Copy parameters into context if necessary. 1211 // Copy parameters into context if necessary.
1150 int num_parameters = scope->num_parameters(); 1212 int num_parameters = scope->num_parameters();
1151 for (int i = 0; i < num_parameters; i++) { 1213 for (int i = 0; i < num_parameters; i++) {
1152 Variable* variable = scope->parameter(i); 1214 Variable* variable = scope->parameter(i);
1153 if (variable->IsContextSlot()) { 1215 if (!variable->IsContextSlot()) continue;
1154 UNIMPLEMENTED(); 1216
1155 } 1217 // The parameter indices are shifted by 1 (receiver is variable
1218 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1219 Register parameter(builder()->Parameter(i + 1));
1220 // Context variable (at bottom of the context chain).
1221 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
1222 builder()->LoadAccumulatorWithRegister(parameter)
1223 .StoreContextSlot(execution_context()->reg(), variable->index());
1156 } 1224 }
1157 } 1225 }
1158 1226
1159 1227
1228 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
1229 DCHECK(scope->is_block_scope());
1230
1231 // Allocate a new local block context.
1232 TemporaryRegisterScope temporary_register_scope(builder());
1233 Register scope_info = temporary_register_scope.NewRegister();
1234 Register closure = temporary_register_scope.NewRegister();
1235 DCHECK(Register::AreContiguous(scope_info, closure));
1236 builder()
1237 ->LoadLiteral(scope->GetScopeInfo(isolate()))
1238 .StoreAccumulatorInRegister(scope_info);
1239 VisitFunctionClosureForContext();
1240 builder()
1241 ->StoreAccumulatorInRegister(closure)
1242 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2);
1243 }
1244
1245
1160 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { 1246 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) {
1161 Token::Value op = binop->op(); 1247 Token::Value op = binop->op();
1162 Expression* left = binop->left(); 1248 Expression* left = binop->left();
1163 Expression* right = binop->right(); 1249 Expression* right = binop->right();
1164 1250
1165 TemporaryRegisterScope temporary_register_scope(builder()); 1251 TemporaryRegisterScope temporary_register_scope(builder());
1166 Register temporary = temporary_register_scope.NewRegister(); 1252 Register temporary = temporary_register_scope.NewRegister();
1167 1253
1168 Visit(left); 1254 Visit(left);
1169 builder()->StoreAccumulatorInRegister(temporary); 1255 builder()->StoreAccumulatorInRegister(temporary);
1170 Visit(right); 1256 Visit(right);
1171 builder()->BinaryOperation(op, temporary, language_mode_strength()); 1257 builder()->BinaryOperation(op, temporary, language_mode_strength());
1172 } 1258 }
1173 1259
1174 1260
1175 void BytecodeGenerator::VisitObjectLiteralAccessor(
1176 Register home_object, ObjectLiteralProperty* property, Register value_out) {
1177 // TODO(rmcilroy): Replace value_out with VisitForRegister();
1178 if (property == nullptr) {
1179 builder()->LoadNull().StoreAccumulatorInRegister(value_out);
1180 } else {
1181 Visit(property->value());
1182 builder()->StoreAccumulatorInRegister(value_out);
1183 VisitSetHomeObject(value_out, home_object, property);
1184 }
1185 }
1186
1187
1188 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
1189 ObjectLiteralProperty* property,
1190 int slot_number) {
1191 Expression* expr = property->value();
1192 if (!FunctionLiteral::NeedsHomeObject(expr)) return;
1193
1194 // TODO(rmcilroy): Remove UNIMPLEMENTED once we have tests for setting the
1195 // home object.
1196 UNIMPLEMENTED();
1197
1198 TemporaryRegisterScope temporary_register_scope(builder());
1199 Register name = temporary_register_scope.NewRegister();
1200 isolate()->factory()->home_object_symbol();
1201 builder()
1202 ->LoadLiteral(isolate()->factory()->home_object_symbol())
1203 .StoreAccumulatorInRegister(name)
1204 .StoreNamedProperty(home_object, name,
1205 feedback_index(property->GetSlot(slot_number)),
1206 language_mode());
1207 }
1208
1209
1210 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { 1261 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
1211 Expression* left = binop->left(); 1262 Expression* left = binop->left();
1212 Expression* right = binop->right(); 1263 Expression* right = binop->right();
1213 1264
1214 Visit(left); 1265 Visit(left);
1215 Visit(right); 1266 Visit(right);
1216 } 1267 }
1217 1268
1218 1269
1219 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { 1270 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
(...skipping 27 matching lines...) Expand all
1247 BytecodeLabel end_label; 1298 BytecodeLabel end_label;
1248 1299
1249 Visit(left); 1300 Visit(left);
1250 builder()->JumpIfToBooleanFalse(&end_label); 1301 builder()->JumpIfToBooleanFalse(&end_label);
1251 Visit(right); 1302 Visit(right);
1252 builder()->Bind(&end_label); 1303 builder()->Bind(&end_label);
1253 } 1304 }
1254 } 1305 }
1255 1306
1256 1307
1308 void BytecodeGenerator::VisitObjectLiteralAccessor(
1309 Register home_object, ObjectLiteralProperty* property, Register value_out) {
1310 // TODO(rmcilroy): Replace value_out with VisitForRegister();
1311 if (property == nullptr) {
1312 builder()->LoadNull().StoreAccumulatorInRegister(value_out);
1313 } else {
1314 Visit(property->value());
1315 builder()->StoreAccumulatorInRegister(value_out);
1316 VisitSetHomeObject(value_out, home_object, property);
1317 }
1318 }
1319
1320
1321 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
1322 ObjectLiteralProperty* property,
1323 int slot_number) {
1324 Expression* expr = property->value();
1325 if (!FunctionLiteral::NeedsHomeObject(expr)) return;
1326
1327 // TODO(rmcilroy): Remove UNIMPLEMENTED once we have tests for setting the
1328 // home object.
1329 UNIMPLEMENTED();
1330
1331 TemporaryRegisterScope temporary_register_scope(builder());
1332 Register name = temporary_register_scope.NewRegister();
1333 isolate()->factory()->home_object_symbol();
1334 builder()
1335 ->LoadLiteral(isolate()->factory()->home_object_symbol())
1336 .StoreAccumulatorInRegister(name)
1337 .StoreNamedProperty(home_object, name,
1338 feedback_index(property->GetSlot(slot_number)),
1339 language_mode());
1340 }
1341
1342
1343 void BytecodeGenerator::VisitFunctionClosureForContext() {
1344 Scope* closure_scope = execution_context()->scope()->ClosureScope();
1345 if (closure_scope->is_script_scope() ||
1346 closure_scope->is_module_scope()) {
1347 // Contexts nested in the native context have a canonical empty function as
1348 // their closure, not the anonymous closure containing the global code.
1349 // Pass a SMI sentinel and let the runtime look up the empty function.
1350 builder()->LoadLiteral(Smi::FromInt(0));
1351 } else {
1352 DCHECK(closure_scope->is_function_scope());
1353 builder()->LoadAccumulatorWithRegister(Register::function_closure());
1354 }
1355 }
1356
1357
1358 Register BytecodeGenerator::NextContextRegister() const {
1359 if (execution_context() == nullptr) {
1360 // Return the incoming function context for the outermost execution context.
1361 return Register::function_context();
1362 }
1363 Register previous = execution_context()->reg();
1364 if (previous == Register::function_context()) {
1365 // If the previous context was the incoming function context, then the next
1366 // context register is the first local context register.
1367 return builder_.first_context_register();
1368 } else {
1369 // Otherwise use the next local context register.
1370 DCHECK_LT(previous.index(), builder_.last_context_register().index());
1371 return Register(previous.index() + 1);
1372 }
1373 }
1374
1375
1257 LanguageMode BytecodeGenerator::language_mode() const { 1376 LanguageMode BytecodeGenerator::language_mode() const {
1258 return info()->language_mode(); 1377 return info()->language_mode();
1259 } 1378 }
1260 1379
1261 1380
1262 Strength BytecodeGenerator::language_mode_strength() const { 1381 Strength BytecodeGenerator::language_mode_strength() const {
1263 return strength(language_mode()); 1382 return strength(language_mode());
1264 } 1383 }
1265 1384
1266 1385
1267 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 1386 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
1268 return info()->feedback_vector()->GetIndex(slot); 1387 return info()->feedback_vector()->GetIndex(slot);
1269 } 1388 }
1270 1389
1271 } // namespace interpreter 1390 } // namespace interpreter
1272 } // namespace internal 1391 } // namespace internal
1273 } // namespace v8 1392 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698