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

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: 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
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 is_function_context = false)
28 : generator_(generator), 28 : generator_(generator),
29 outer_(generator_->current_context()), 29 scope_(scope),
30 outer_(generator_->execution_context()),
31 register_(generator_->NextContextRegister()),
32 depth_(0),
30 is_function_context_(is_function_context) { 33 is_function_context_(is_function_context) {
31 DCHECK(!is_function_context || 34 if (outer_) {
32 outer_.index() == Register::function_context().index()); 35 depth_ = outer_->depth_ + 1;
33 Register new_context_reg = NewContextRegister(); 36 generator_->builder()->PushContext(register_);
34 generator_->builder()->PushContext(new_context_reg); 37 }
35 generator_->set_current_context(new_context_reg); 38 generator_->set_execution_context(this);
36 } 39 }
37 40
38 ~ContextScope() { 41 ~ContextScope() {
39 if (!is_function_context_) { 42 if (outer_ && !is_function_context_) {
Michael Starzinger 2015/10/16 09:10:04 The semantics of the "is_function_context" flags a
rmcilroy 2015/10/16 11:19:04 Done, but named it should_pop_context.
Michael Starzinger 2015/10/16 13:29:05 Acknowledged. Works for me.
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_;
70 ContextScope* outer_;
71 Register register_;
72 int depth_;
58 bool is_function_context_; 73 bool is_function_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(), true);
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(), true);
163 MakeBytecodeBody(); 181 MakeBytecodeBody();
164 } else { 182 } else {
165 MakeBytecodeBody(); 183 MakeBytecodeBody();
166 } 184 }
167 185
168 set_scope(nullptr); 186 set_scope(nullptr);
169 set_info(nullptr); 187 set_info(nullptr);
170 return builder_.ToBytecodeArray(); 188 return builder_.ToBytecodeArray();
171 } 189 }
172 190
173 191
174 void BytecodeGenerator::MakeBytecodeBody() { 192 void BytecodeGenerator::MakeBytecodeBody() {
175 // Visit declarations within the function scope. 193 // Visit declarations within the function scope.
176 VisitDeclarations(scope()->declarations()); 194 VisitDeclarations(scope()->declarations());
177 195
178 // Visit statements in the function body. 196 // Visit statements in the function body.
179 VisitStatements(info()->literal()->body()); 197 VisitStatements(info()->literal()->body());
180 } 198 }
181 199
182 200
183 void BytecodeGenerator::VisitBlock(Block* node) { 201 void BytecodeGenerator::VisitBlock(Block* stmt) {
184 builder()->EnterBlock(); 202 builder()->EnterBlock();
185 if (node->scope() == NULL) { 203 if (stmt->scope() == NULL) {
186 // Visit statements in the same scope, no declarations. 204 // Visit statements in the same scope, no declarations.
187 VisitStatements(node->statements()); 205 VisitStatements(stmt->statements());
188 } else { 206 } else {
189 // Visit declarations and statements in a block scope. 207 // Visit declarations and statements in a block scope.
190 if (node->scope()->ContextLocalCount() > 0) { 208 if (stmt->scope()->NeedsContext()) {
191 UNIMPLEMENTED(); 209 VisitNewLocalBlockContext(stmt->scope());
210 ContextScope scope(this, stmt->scope());
211 VisitDeclarations(stmt->scope()->declarations());
212 VisitStatements(stmt->statements());
192 } else { 213 } else {
193 VisitDeclarations(node->scope()->declarations()); 214 VisitDeclarations(stmt->scope()->declarations());
194 VisitStatements(node->statements()); 215 VisitStatements(stmt->statements());
195 } 216 }
196 } 217 }
197 builder()->LeaveBlock(); 218 builder()->LeaveBlock();
198 } 219 }
199 220
200 221
201 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { 222 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
202 Variable* variable = decl->proxy()->var(); 223 Variable* variable = decl->proxy()->var();
203 VariableMode mode = decl->mode(); 224 VariableMode mode = decl->mode();
204 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; 225 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
oth 2015/10/16 09:30:43 A comment would be helpful explaining the purpose
rmcilroy 2015/10/16 11:19:04 Done.
205 if (hole_init) {
206 UNIMPLEMENTED();
207 }
208 switch (variable->location()) { 226 switch (variable->location()) {
209 case VariableLocation::GLOBAL: 227 case VariableLocation::GLOBAL:
210 case VariableLocation::UNALLOCATED: { 228 case VariableLocation::UNALLOCATED: {
211 Handle<Oddball> value = variable->binding_needs_init() 229 Handle<Oddball> value = variable->binding_needs_init()
212 ? isolate()->factory()->the_hole_value() 230 ? isolate()->factory()->the_hole_value()
213 : isolate()->factory()->undefined_value(); 231 : isolate()->factory()->undefined_value();
214 globals()->push_back(variable->name()); 232 globals()->push_back(variable->name());
215 globals()->push_back(value); 233 globals()->push_back(value);
216 break; 234 break;
217 } 235 }
236 case VariableLocation::LOCAL:
237 if (hole_init) {
238 Register destination(variable->index());
239 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
240 }
241 break;
218 case VariableLocation::PARAMETER: 242 case VariableLocation::PARAMETER:
219 case VariableLocation::LOCAL: 243 if (hole_init) {
220 // Details stored in scope, i.e. variable index. 244 // The parameter indices are shifted by 1 (receiver is variable
245 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
246 Register destination(builder()->Parameter(variable->index() + 1));
247 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
248 }
221 break; 249 break;
222 case VariableLocation::CONTEXT: 250 case VariableLocation::CONTEXT:
251 if (hole_init) {
252 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
253 variable->index());
254 }
255 break;
223 case VariableLocation::LOOKUP: 256 case VariableLocation::LOOKUP:
224 UNIMPLEMENTED(); 257 UNIMPLEMENTED();
225 break; 258 break;
226 } 259 }
227 } 260 }
228 261
229 262
230 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { 263 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
231 Variable* variable = decl->proxy()->var(); 264 Variable* variable = decl->proxy()->var();
232 switch (variable->location()) { 265 switch (variable->location()) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 } 352 }
320 353
321 354
322 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( 355 void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
323 SloppyBlockFunctionStatement* stmt) { 356 SloppyBlockFunctionStatement* stmt) {
324 Visit(stmt->statement()); 357 Visit(stmt->statement());
325 } 358 }
326 359
327 360
328 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { 361 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
329 control_scope()->Continue(stmt->target()); 362 execution_control()->Continue(stmt->target());
330 } 363 }
331 364
332 365
333 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 366 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
334 control_scope()->Break(stmt->target()); 367 execution_control()->Break(stmt->target());
335 } 368 }
336 369
337 370
338 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 371 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
339 Visit(stmt->expression()); 372 Visit(stmt->expression());
340 builder()->Return(); 373 builder()->Return();
341 } 374 }
342 375
343 376
344 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 377 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
345 UNIMPLEMENTED(); 378 UNIMPLEMENTED();
346 } 379 }
347 380
348 381
349 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 382 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
350 UNIMPLEMENTED(); 383 UNIMPLEMENTED();
351 } 384 }
352 385
353 386
354 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } 387 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); }
355 388
356 389
357 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 390 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
358 LoopBuilder loop_builder(builder()); 391 LoopBuilder loop_builder(builder());
359 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 392 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
360 393
361 BytecodeLabel body_label, condition_label, done_label; 394 BytecodeLabel body_label, condition_label, done_label;
362 builder()->Bind(&body_label); 395 builder()->Bind(&body_label);
363 Visit(stmt->body()); 396 Visit(stmt->body());
364 builder()->Bind(&condition_label); 397 builder()->Bind(&condition_label);
365 Visit(stmt->cond()); 398 Visit(stmt->cond());
366 builder()->JumpIfTrue(&body_label); 399 builder()->JumpIfTrue(&body_label);
367 builder()->Bind(&done_label); 400 builder()->Bind(&done_label);
368 401
369 loop_builder.SetBreakTarget(done_label); 402 loop_builder.SetBreakTarget(done_label);
370 loop_builder.SetContinueTarget(condition_label); 403 loop_builder.SetContinueTarget(condition_label);
371 } 404 }
372 405
373 406
374 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { 407 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
375 LoopBuilder loop_builder(builder()); 408 LoopBuilder loop_builder(builder());
376 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 409 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
377 410
378 BytecodeLabel body_label, condition_label, done_label; 411 BytecodeLabel body_label, condition_label, done_label;
379 builder()->Jump(&condition_label); 412 builder()->Jump(&condition_label);
380 builder()->Bind(&body_label); 413 builder()->Bind(&body_label);
381 Visit(stmt->body()); 414 Visit(stmt->body());
382 builder()->Bind(&condition_label); 415 builder()->Bind(&condition_label);
383 Visit(stmt->cond()); 416 Visit(stmt->cond());
384 builder()->JumpIfTrue(&body_label); 417 builder()->JumpIfTrue(&body_label);
385 builder()->Bind(&done_label); 418 builder()->Bind(&done_label);
386 419
387 loop_builder.SetBreakTarget(done_label); 420 loop_builder.SetBreakTarget(done_label);
388 loop_builder.SetContinueTarget(condition_label); 421 loop_builder.SetContinueTarget(condition_label);
389 } 422 }
390 423
391 424
392 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { 425 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
393 LoopBuilder loop_builder(builder()); 426 LoopBuilder loop_builder(builder());
394 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 427 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
395 428
396 if (stmt->init() != nullptr) { 429 if (stmt->init() != nullptr) {
397 Visit(stmt->init()); 430 Visit(stmt->init());
398 } 431 }
399 432
400 BytecodeLabel body_label, condition_label, next_label, done_label; 433 BytecodeLabel body_label, condition_label, next_label, done_label;
401 if (stmt->cond() != nullptr) { 434 if (stmt->cond() != nullptr) {
402 builder()->Jump(&condition_label); 435 builder()->Jump(&condition_label);
403 } 436 }
404 builder()->Bind(&body_label); 437 builder()->Bind(&body_label);
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 } 621 }
589 break; 622 break;
590 case ObjectLiteral::Property::SETTER: 623 case ObjectLiteral::Property::SETTER:
591 if (property->emit_store()) { 624 if (property->emit_store()) {
592 accessor_table.lookup(literal_key)->second->setter = property; 625 accessor_table.lookup(literal_key)->second->setter = property;
593 } 626 }
594 break; 627 break;
595 } 628 }
596 } 629 }
597 630
598 // Create nodes to define accessors, using only a single call to the runtime 631 // Define accessors, using only a single call to the runtime for each pair of
599 // for each pair of corresponding getters and setters. 632 // corresponding getters and setters.
600 for (AccessorTable::Iterator it = accessor_table.begin(); 633 for (AccessorTable::Iterator it = accessor_table.begin();
601 it != accessor_table.end(); ++it) { 634 it != accessor_table.end(); ++it) {
602 TemporaryRegisterScope inner_temporary_register_scope(builder()); 635 TemporaryRegisterScope inner_temporary_register_scope(builder());
603 Register name = inner_temporary_register_scope.NewRegister(); 636 Register name = inner_temporary_register_scope.NewRegister();
604 Register getter = inner_temporary_register_scope.NewRegister(); 637 Register getter = inner_temporary_register_scope.NewRegister();
605 Register setter = inner_temporary_register_scope.NewRegister(); 638 Register setter = inner_temporary_register_scope.NewRegister();
606 Register attr = inner_temporary_register_scope.NewRegister(); 639 Register attr = inner_temporary_register_scope.NewRegister();
607 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); 640 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr));
608 Visit(it->first); 641 Visit(it->first);
609 builder()->StoreAccumulatorInRegister(name); 642 builder()->StoreAccumulatorInRegister(name);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 724
692 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 725 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
693 // Deep-copy the literal boilerplate. 726 // Deep-copy the literal boilerplate.
694 builder() 727 builder()
695 ->LoadLiteral(expr->constant_elements()) 728 ->LoadLiteral(expr->constant_elements())
696 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true)); 729 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true));
697 730
698 TemporaryRegisterScope temporary_register_scope(builder()); 731 TemporaryRegisterScope temporary_register_scope(builder());
699 Register index, literal; 732 Register index, literal;
700 733
701 // Create nodes to evaluate all the non-constant subexpressions and to store 734 // Evaluate all the non-constant subexpressions and to store them into the
Michael Starzinger 2015/10/16 09:10:04 nit: Drop the "to" in this sentence.
rmcilroy 2015/10/16 11:19:04 Done.
702 // them into the newly cloned array. 735 // newly cloned array.
703 bool literal_in_accumulator = true; 736 bool literal_in_accumulator = true;
704 for (int array_index = 0; array_index < expr->values()->length(); 737 for (int array_index = 0; array_index < expr->values()->length();
705 array_index++) { 738 array_index++) {
706 Expression* subexpr = expr->values()->at(array_index); 739 Expression* subexpr = expr->values()->at(array_index);
707 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 740 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
708 if (subexpr->IsSpread()) { 741 if (subexpr->IsSpread()) {
709 // TODO(rmcilroy): Deal with spread expressions. 742 // TODO(rmcilroy): Deal with spread expressions.
710 UNIMPLEMENTED(); 743 UNIMPLEMENTED();
711 } 744 }
712 745
(...skipping 24 matching lines...) Expand all
737 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 770 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
738 } 771 }
739 772
740 773
741 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 774 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
742 FeedbackVectorSlot slot) { 775 FeedbackVectorSlot slot) {
743 switch (variable->location()) { 776 switch (variable->location()) {
744 case VariableLocation::LOCAL: { 777 case VariableLocation::LOCAL: {
745 Register source(variable->index()); 778 Register source(variable->index());
746 builder()->LoadAccumulatorWithRegister(source); 779 builder()->LoadAccumulatorWithRegister(source);
780 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
781 // let variables.
747 break; 782 break;
748 } 783 }
749 case VariableLocation::PARAMETER: { 784 case VariableLocation::PARAMETER: {
750 // The parameter indices are shifted by 1 (receiver is variable 785 // The parameter indices are shifted by 1 (receiver is variable
751 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 786 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
752 Register source(builder()->Parameter(variable->index() + 1)); 787 Register source(builder()->Parameter(variable->index() + 1));
753 builder()->LoadAccumulatorWithRegister(source); 788 builder()->LoadAccumulatorWithRegister(source);
754 break; 789 break;
755 } 790 }
756 case VariableLocation::GLOBAL: { 791 case VariableLocation::GLOBAL: {
757 // Global var, const, or let variable. 792 // Global var, const, or let variable.
758 // TODO(rmcilroy): If context chain depth is short enough, do this using 793 // TODO(rmcilroy): If context chain depth is short enough, do this using
759 // a generic version of LoadGlobalViaContextStub rather than calling the 794 // a generic version of LoadGlobalViaContextStub rather than calling the
760 // runtime. 795 // runtime.
761 DCHECK(variable->IsStaticGlobalObjectProperty()); 796 DCHECK(variable->IsStaticGlobalObjectProperty());
762 builder()->LoadGlobal(variable->index()); 797 builder()->LoadGlobal(variable->index());
763 break; 798 break;
764 } 799 }
765 case VariableLocation::UNALLOCATED: { 800 case VariableLocation::UNALLOCATED: {
766 TemporaryRegisterScope temporary_register_scope(builder()); 801 TemporaryRegisterScope temporary_register_scope(builder());
767 Register obj = temporary_register_scope.NewRegister(); 802 Register obj = temporary_register_scope.NewRegister();
768 builder()->LoadContextSlot(current_context(), 803 builder()->LoadContextSlot(execution_context()->reg(),
769 Context::GLOBAL_OBJECT_INDEX); 804 Context::GLOBAL_OBJECT_INDEX);
770 builder()->StoreAccumulatorInRegister(obj); 805 builder()->StoreAccumulatorInRegister(obj);
771 builder()->LoadLiteral(variable->name()); 806 builder()->LoadLiteral(variable->name());
772 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); 807 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode());
773 break; 808 break;
774 } 809 }
775 case VariableLocation::CONTEXT: 810 case VariableLocation::CONTEXT: {
811 ContextScope* context = execution_context()->Previous(variable->scope());
812 if (context) {
813 builder()->LoadContextSlot(context->reg(), variable->index());
814 } else {
815 UNIMPLEMENTED();
816 }
817 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
818 // let variables.
819 break;
820 }
776 case VariableLocation::LOOKUP: 821 case VariableLocation::LOOKUP:
777 UNIMPLEMENTED(); 822 UNIMPLEMENTED();
778 } 823 }
779 } 824 }
780 825
781 826
782 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 827 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
783 FeedbackVectorSlot slot) { 828 FeedbackVectorSlot slot) {
784 switch (variable->location()) { 829 switch (variable->location()) {
785 case VariableLocation::LOCAL: { 830 case VariableLocation::LOCAL: {
(...skipping 19 matching lines...) Expand all
805 break; 850 break;
806 } 851 }
807 case VariableLocation::UNALLOCATED: { 852 case VariableLocation::UNALLOCATED: {
808 TemporaryRegisterScope temporary_register_scope(builder()); 853 TemporaryRegisterScope temporary_register_scope(builder());
809 Register value = temporary_register_scope.NewRegister(); 854 Register value = temporary_register_scope.NewRegister();
810 Register obj = temporary_register_scope.NewRegister(); 855 Register obj = temporary_register_scope.NewRegister();
811 Register name = temporary_register_scope.NewRegister(); 856 Register name = temporary_register_scope.NewRegister();
812 // TODO(rmcilroy): Investigate whether we can avoid having to stash the 857 // TODO(rmcilroy): Investigate whether we can avoid having to stash the
813 // value in a register. 858 // value in a register.
814 builder()->StoreAccumulatorInRegister(value); 859 builder()->StoreAccumulatorInRegister(value);
815 builder()->LoadContextSlot(current_context(), 860 builder()->LoadContextSlot(execution_context()->reg(),
816 Context::GLOBAL_OBJECT_INDEX); 861 Context::GLOBAL_OBJECT_INDEX);
817 builder()->StoreAccumulatorInRegister(obj); 862 builder()->StoreAccumulatorInRegister(obj);
818 builder()->LoadLiteral(variable->name()); 863 builder()->LoadLiteral(variable->name());
819 builder()->StoreAccumulatorInRegister(name); 864 builder()->StoreAccumulatorInRegister(name);
820 builder()->LoadAccumulatorWithRegister(value); 865 builder()->LoadAccumulatorWithRegister(value);
821 builder()->StoreNamedProperty(obj, name, feedback_index(slot), 866 builder()->StoreNamedProperty(obj, name, feedback_index(slot),
822 language_mode()); 867 language_mode());
823 break; 868 break;
824 } 869 }
825 case VariableLocation::CONTEXT: 870 case VariableLocation::CONTEXT: {
871 // TODO(rmcilroy): support const mode initialization.
872 ContextScope* context = execution_context()->Previous(variable->scope());
873 if (context) {
874 builder()->StoreContextSlot(context->reg(), variable->index());
875 } else {
876 UNIMPLEMENTED();
877 }
878 break;
879 }
826 case VariableLocation::LOOKUP: 880 case VariableLocation::LOOKUP:
827 UNIMPLEMENTED(); 881 UNIMPLEMENTED();
828 } 882 }
829 } 883 }
830 884
831 885
832 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 886 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
833 DCHECK(expr->target()->IsValidReferenceExpression()); 887 DCHECK(expr->target()->IsValidReferenceExpression());
834 TemporaryRegisterScope temporary_register_scope(builder()); 888 TemporaryRegisterScope temporary_register_scope(builder());
835 Register object, key; 889 Register object, key;
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 int num_parameters = scope->num_parameters(); 1204 int num_parameters = scope->num_parameters();
1151 for (int i = 0; i < num_parameters; i++) { 1205 for (int i = 0; i < num_parameters; i++) {
1152 Variable* variable = scope->parameter(i); 1206 Variable* variable = scope->parameter(i);
1153 if (variable->IsContextSlot()) { 1207 if (variable->IsContextSlot()) {
1154 UNIMPLEMENTED(); 1208 UNIMPLEMENTED();
1155 } 1209 }
1156 } 1210 }
1157 } 1211 }
1158 1212
1159 1213
1214 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
1215 DCHECK(scope->is_block_scope());
1216
1217 // Allocate a new local block context.
1218 TemporaryRegisterScope temporary_register_scope(builder());
1219 Register scope_info = temporary_register_scope.NewRegister();
1220 Register closure = temporary_register_scope.NewRegister();
1221 DCHECK(Register::AreContiguous(scope_info, closure));
1222 builder()
1223 ->LoadLiteral(scope->GetScopeInfo(isolate()))
1224 .StoreAccumulatorInRegister(scope_info)
1225 .LoadAccumulatorWithRegister(Register::function_closure())
Michael Starzinger 2015/10/16 09:10:04 For script (or any other top level code) the passe
rmcilroy 2015/10/16 11:19:04 Ahh I never spotted this, thanks for the hint. I'v
Michael Starzinger 2015/10/16 13:29:06 Acknowledged.
1226 .StoreAccumulatorInRegister(closure)
1227 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2);
1228 }
1229
1230
1160 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { 1231 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) {
1161 Token::Value op = binop->op(); 1232 Token::Value op = binop->op();
1162 Expression* left = binop->left(); 1233 Expression* left = binop->left();
1163 Expression* right = binop->right(); 1234 Expression* right = binop->right();
1164 1235
1165 TemporaryRegisterScope temporary_register_scope(builder()); 1236 TemporaryRegisterScope temporary_register_scope(builder());
1166 Register temporary = temporary_register_scope.NewRegister(); 1237 Register temporary = temporary_register_scope.NewRegister();
1167 1238
1168 Visit(left); 1239 Visit(left);
1169 builder()->StoreAccumulatorInRegister(temporary); 1240 builder()->StoreAccumulatorInRegister(temporary);
1170 Visit(right); 1241 Visit(right);
1171 builder()->BinaryOperation(op, temporary, language_mode_strength()); 1242 builder()->BinaryOperation(op, temporary, language_mode_strength());
1172 } 1243 }
1173 1244
1174 1245
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) { 1246 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
1211 Expression* left = binop->left(); 1247 Expression* left = binop->left();
1212 Expression* right = binop->right(); 1248 Expression* right = binop->right();
1213 1249
1214 Visit(left); 1250 Visit(left);
1215 Visit(right); 1251 Visit(right);
1216 } 1252 }
1217 1253
1218 1254
1219 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { 1255 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
(...skipping 27 matching lines...) Expand all
1247 BytecodeLabel end_label; 1283 BytecodeLabel end_label;
1248 1284
1249 Visit(left); 1285 Visit(left);
1250 builder()->JumpIfToBooleanFalse(&end_label); 1286 builder()->JumpIfToBooleanFalse(&end_label);
1251 Visit(right); 1287 Visit(right);
1252 builder()->Bind(&end_label); 1288 builder()->Bind(&end_label);
1253 } 1289 }
1254 } 1290 }
1255 1291
1256 1292
1293 void BytecodeGenerator::VisitObjectLiteralAccessor(
1294 Register home_object, ObjectLiteralProperty* property, Register value_out) {
1295 // TODO(rmcilroy): Replace value_out with VisitForRegister();
1296 if (property == nullptr) {
1297 builder()->LoadNull().StoreAccumulatorInRegister(value_out);
1298 } else {
1299 Visit(property->value());
1300 builder()->StoreAccumulatorInRegister(value_out);
1301 VisitSetHomeObject(value_out, home_object, property);
1302 }
1303 }
1304
1305
1306 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
1307 ObjectLiteralProperty* property,
1308 int slot_number) {
1309 Expression* expr = property->value();
1310 if (!FunctionLiteral::NeedsHomeObject(expr)) return;
1311
1312 // TODO(rmcilroy): Remove UNIMPLEMENTED once we have tests for setting the
1313 // home object.
1314 UNIMPLEMENTED();
1315
1316 TemporaryRegisterScope temporary_register_scope(builder());
1317 Register name = temporary_register_scope.NewRegister();
1318 isolate()->factory()->home_object_symbol();
1319 builder()
1320 ->LoadLiteral(isolate()->factory()->home_object_symbol())
1321 .StoreAccumulatorInRegister(name)
1322 .StoreNamedProperty(home_object, name,
1323 feedback_index(property->GetSlot(slot_number)),
1324 language_mode());
1325 }
1326
1327
1328 Register BytecodeGenerator::NextContextRegister() const {
1329 if (execution_context() == nullptr) {
1330 return Register::function_context();
1331 }
1332 Register previous = execution_context()->reg();
1333 if (previous == Register::function_context()) {
oth 2015/10/16 09:30:43 Comments here explaining the logic for the returne
rmcilroy 2015/10/16 11:19:04 Done.
1334 return builder_.first_context_register();
1335 } else {
1336 DCHECK_LT(previous.index(), builder_.last_context_register().index());
1337 return Register(previous.index() + 1);
1338 }
1339 }
1340
1341
1257 LanguageMode BytecodeGenerator::language_mode() const { 1342 LanguageMode BytecodeGenerator::language_mode() const {
1258 return info()->language_mode(); 1343 return info()->language_mode();
1259 } 1344 }
1260 1345
1261 1346
1262 Strength BytecodeGenerator::language_mode_strength() const { 1347 Strength BytecodeGenerator::language_mode_strength() const {
1263 return strength(language_mode()); 1348 return strength(language_mode());
1264 } 1349 }
1265 1350
1266 1351
1267 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 1352 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
1268 return info()->feedback_vector()->GetIndex(slot); 1353 return info()->feedback_vector()->GetIndex(slot);
1269 } 1354 }
1270 1355
1271 } // namespace interpreter 1356 } // namespace interpreter
1272 } // namespace internal 1357 } // namespace internal
1273 } // namespace v8 1358 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698