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

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

Issue 1378523005: [Interpreter] Add support for global declarations and load/store of global variables (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@int_toplevel
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
« 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/objects.h" 10 #include "src/objects.h"
11 #include "src/scopes.h" 11 #include "src/scopes.h"
12 #include "src/token.h" 12 #include "src/token.h"
13 13
14 namespace v8 { 14 namespace v8 {
15 namespace internal { 15 namespace internal {
16 namespace interpreter { 16 namespace interpreter {
17 17
18 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) 18 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
19 : builder_(isolate, zone) { 19 : builder_(isolate, zone),
20 globals_(0, zone),
21 current_context_(Register::function_context()) {
20 InitializeAstVisitor(isolate, zone); 22 InitializeAstVisitor(isolate, zone);
21 } 23 }
22 24
23 25
24 BytecodeGenerator::~BytecodeGenerator() {} 26 BytecodeGenerator::~BytecodeGenerator() {}
25 27
26 28
27 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 29 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
28 set_info(info); 30 set_info(info);
29 set_scope(info->scope()); 31 set_scope(info->scope());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
61 VisitDeclarations(node->scope()->declarations()); 63 VisitDeclarations(node->scope()->declarations());
62 VisitStatements(node->statements()); 64 VisitStatements(node->statements());
63 } 65 }
64 } 66 }
65 builder().LeaveBlock(); 67 builder().LeaveBlock();
66 } 68 }
67 69
68 70
69 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { 71 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
70 Variable* variable = decl->proxy()->var(); 72 Variable* variable = decl->proxy()->var();
73 VariableMode mode = decl->mode();
74 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
75 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.
71 switch (variable->location()) { 76 switch (variable->location()) {
72 case VariableLocation::GLOBAL: 77 case VariableLocation::GLOBAL:
73 case VariableLocation::UNALLOCATED: 78 case VariableLocation::UNALLOCATED: {
74 UNIMPLEMENTED(); 79 Handle<Oddball> value = variable->binding_needs_init()
80 ? isolate()->factory()->the_hole_value()
81 : isolate()->factory()->undefined_value();
82 globals()->push_back(variable->name());
83 globals()->push_back(value);
75 break; 84 break;
85 }
76 case VariableLocation::PARAMETER: 86 case VariableLocation::PARAMETER:
77 case VariableLocation::LOCAL: 87 case VariableLocation::LOCAL:
78 // Details stored in scope, i.e. variable index. 88 // Details stored in scope, i.e. variable index.
79 break; 89 break;
80 case VariableLocation::CONTEXT: 90 case VariableLocation::CONTEXT:
81 case VariableLocation::LOOKUP: 91 case VariableLocation::LOOKUP:
82 UNIMPLEMENTED(); 92 UNIMPLEMENTED();
83 break; 93 break;
84 } 94 }
85 } 95 }
86 96
87 97
88 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { 98 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
89 UNIMPLEMENTED(); 99 Variable* variable = decl->proxy()->var();
100 switch (variable->location()) {
101 case VariableLocation::GLOBAL:
102 case VariableLocation::UNALLOCATED: {
103 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
104 decl->fun(), info()->script(), info());
105 // Check for stack-overflow exception.
106 if (function.is_null()) return SetStackOverflow();
107 globals()->push_back(variable->name());
108 globals()->push_back(function);
109 break;
110 }
111 case VariableLocation::PARAMETER:
112 case VariableLocation::LOCAL:
113 case VariableLocation::CONTEXT:
114 case VariableLocation::LOOKUP:
115 UNIMPLEMENTED();
116 }
90 } 117 }
91 118
92 119
93 void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) { 120 void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
94 UNIMPLEMENTED(); 121 UNIMPLEMENTED();
95 } 122 }
96 123
97 124
98 void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) { 125 void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
99 UNIMPLEMENTED(); 126 UNIMPLEMENTED();
100 } 127 }
101 128
102 129
130 void BytecodeGenerator::VisitDeclarations(
131 ZoneList<Declaration*>* declarations) {
132 DCHECK(globals()->empty());
133 AstVisitor::VisitDeclarations(declarations);
134 if (globals()->empty()) return;
135 int array_index = 0;
136 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
137 static_cast<int>(globals()->size()), TENURED);
138 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
139 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
140 DeclareGlobalsNativeFlag::encode(info()->is_native()) |
141 DeclareGlobalsLanguageMode::encode(language_mode());
142
143 TemporaryRegisterScope temporary_register_scope(&builder_);
144 Register pairs = temporary_register_scope.NewRegister();
145 builder().LoadLiteral(data);
146 builder().StoreAccumulatorInRegister(pairs);
147
148 Register flags = temporary_register_scope.NewRegister();
149 builder().LoadLiteral(Smi::FromInt(encoded_flags));
150 builder().StoreAccumulatorInRegister(flags);
151 DCHECK(flags.index() == pairs.index() + 1);
152
153 builder().CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
154 globals()->clear();
155 }
156
157
103 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 158 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
104 Visit(stmt->expression()); 159 Visit(stmt->expression());
105 } 160 }
106 161
107 162
108 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 163 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
109 // TODO(oth): For control-flow it could be useful to signal empty paths here. 164 // TODO(oth): For control-flow it could be useful to signal empty paths here.
110 } 165 }
111 166
112 167
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 UNIMPLEMENTED(); 306 UNIMPLEMENTED();
252 } 307 }
253 308
254 309
255 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { 310 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
256 UNIMPLEMENTED(); 311 UNIMPLEMENTED();
257 } 312 }
258 313
259 314
260 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { 315 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
261 VisitVariableLoad(proxy->var()); 316 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
262 } 317 }
263 318
264 319
265 void BytecodeGenerator::VisitVariableLoad(Variable* variable) { 320 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
321 FeedbackVectorICSlot slot) {
266 switch (variable->location()) { 322 switch (variable->location()) {
267 case VariableLocation::LOCAL: { 323 case VariableLocation::LOCAL: {
268 Register source(variable->index()); 324 Register source(variable->index());
269 builder().LoadAccumulatorWithRegister(source); 325 builder().LoadAccumulatorWithRegister(source);
270 break; 326 break;
271 } 327 }
272 case VariableLocation::PARAMETER: { 328 case VariableLocation::PARAMETER: {
273 // The parameter indices are shifted by 1 (receiver is variable 329 // The parameter indices are shifted by 1 (receiver is variable
274 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 330 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
275 Register source(builder().Parameter(variable->index() + 1)); 331 Register source(builder().Parameter(variable->index() + 1));
276 builder().LoadAccumulatorWithRegister(source); 332 builder().LoadAccumulatorWithRegister(source);
277 break; 333 break;
278 } 334 }
279 case VariableLocation::GLOBAL: { 335 case VariableLocation::GLOBAL: {
280 // Global var, const, or let variable. 336 // Global var, const, or let variable.
281 // TODO(rmcilroy): If context chain depth is short enough, do this using 337 // TODO(rmcilroy): If context chain depth is short enough, do this using
282 // a generic version of LoadGlobalViaContextStub rather than calling the 338 // a generic version of LoadGlobalViaContextStub rather than calling the
283 // runtime. 339 // runtime.
284 DCHECK(variable->IsStaticGlobalObjectProperty()); 340 DCHECK(variable->IsStaticGlobalObjectProperty());
285 builder().LoadGlobal(variable->index()); 341 builder().LoadGlobal(variable->index());
286 break; 342 break;
287 } 343 }
288 case VariableLocation::UNALLOCATED: 344 case VariableLocation::UNALLOCATED: {
345 TemporaryRegisterScope temporary_register_scope(&builder_);
346 Register obj = temporary_register_scope.NewRegister();
347 builder().LoadContextSlot(current_context(),
348 Context::GLOBAL_OBJECT_INDEX);
349 builder().StoreAccumulatorInRegister(obj);
350 builder().LoadLiteral(variable->name());
351 builder().LoadNamedProperty(obj, feedback_index(slot), language_mode());
352 break;
353 }
289 case VariableLocation::CONTEXT: 354 case VariableLocation::CONTEXT:
290 case VariableLocation::LOOKUP: 355 case VariableLocation::LOOKUP:
291 UNIMPLEMENTED(); 356 UNIMPLEMENTED();
357 }
358 }
359
360
361 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
362 FeedbackVectorICSlot slot) {
363 switch (variable->location()) {
364 case VariableLocation::LOCAL: {
365 // TODO(rmcilroy): support const mode initialization.
366 Register destination(variable->index());
367 builder().StoreAccumulatorInRegister(destination);
368 break;
369 }
370 case VariableLocation::PARAMETER: {
371 // The parameter indices are shifted by 1 (receiver is variable
372 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
373 Register destination(builder().Parameter(variable->index() + 1));
374 builder().StoreAccumulatorInRegister(destination);
375 break;
376 }
377 case VariableLocation::GLOBAL: {
378 // Global var, const, or let variable.
379 // TODO(rmcilroy): If context chain depth is short enough, do this using
380 // a generic version of LoadGlobalViaContextStub rather than calling the
381 // runtime.
382 DCHECK(variable->IsStaticGlobalObjectProperty());
383 builder().StoreGlobal(variable->index(), language_mode());
384 break;
385 }
386 case VariableLocation::UNALLOCATED: {
387 TemporaryRegisterScope temporary_register_scope(&builder_);
388 Register value = temporary_register_scope.NewRegister();
389 Register obj = temporary_register_scope.NewRegister();
390 Register name = temporary_register_scope.NewRegister();
391 // TODO(rmcilroy): Investigate whether we can avoid having to stash the
392 // value in a register.
393 builder().StoreAccumulatorInRegister(value);
394 builder().LoadContextSlot(current_context(),
395 Context::GLOBAL_OBJECT_INDEX);
396 builder().StoreAccumulatorInRegister(obj);
397 builder().LoadLiteral(variable->name());
398 builder().StoreAccumulatorInRegister(name);
399 builder().LoadAccumulatorWithRegister(value);
400 builder().StoreNamedProperty(obj, name, feedback_index(slot),
401 language_mode());
402 break;
403 }
404 case VariableLocation::CONTEXT:
405 case VariableLocation::LOOKUP:
406 UNIMPLEMENTED();
292 } 407 }
293 } 408 }
294 409
295 410
296 void BytecodeGenerator::VisitAssignment(Assignment* expr) { 411 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
297 DCHECK(expr->target()->IsValidReferenceExpression()); 412 DCHECK(expr->target()->IsValidReferenceExpression());
298 TemporaryRegisterScope temporary_register_scope(&builder_); 413 TemporaryRegisterScope temporary_register_scope(&builder_);
299 Register object, key; 414 Register object, key;
300 415
301 // Left-hand side can only be a property, a global or a variable slot. 416 // Left-hand side can only be a property, a global or a variable slot.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 UNIMPLEMENTED(); 449 UNIMPLEMENTED();
335 } else { 450 } else {
336 Visit(expr->value()); 451 Visit(expr->value());
337 } 452 }
338 453
339 // Store the value. 454 // Store the value.
340 FeedbackVectorICSlot slot = expr->AssignmentSlot(); 455 FeedbackVectorICSlot slot = expr->AssignmentSlot();
341 switch (assign_type) { 456 switch (assign_type) {
342 case VARIABLE: { 457 case VARIABLE: {
343 Variable* variable = expr->target()->AsVariableProxy()->var(); 458 Variable* variable = expr->target()->AsVariableProxy()->var();
344 DCHECK(variable->location() == VariableLocation::LOCAL); 459 VisitVariableAssignment(variable, slot);
345 Register destination(variable->index());
346 builder().StoreAccumulatorInRegister(destination);
347 break; 460 break;
348 } 461 }
349 case NAMED_PROPERTY: 462 case NAMED_PROPERTY:
350 builder().StoreNamedProperty(object, key, feedback_index(slot), 463 builder().StoreNamedProperty(object, key, feedback_index(slot),
351 language_mode()); 464 language_mode());
352 break; 465 break;
353 case KEYED_PROPERTY: 466 case KEYED_PROPERTY:
354 builder().StoreKeyedProperty(object, key, feedback_index(slot), 467 builder().StoreKeyedProperty(object, key, feedback_index(slot),
355 language_mode()); 468 language_mode());
356 break; 469 break;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 // Perform a property load of the callee. 533 // Perform a property load of the callee.
421 VisitPropertyLoad(receiver, property); 534 VisitPropertyLoad(receiver, property);
422 builder().StoreAccumulatorInRegister(callee); 535 builder().StoreAccumulatorInRegister(callee);
423 break; 536 break;
424 } 537 }
425 case Call::GLOBAL_CALL: { 538 case Call::GLOBAL_CALL: {
426 // Receiver is undefined for global calls. 539 // Receiver is undefined for global calls.
427 builder().LoadUndefined().StoreAccumulatorInRegister(receiver); 540 builder().LoadUndefined().StoreAccumulatorInRegister(receiver);
428 // Load callee as a global variable. 541 // Load callee as a global variable.
429 VariableProxy* proxy = callee_expr->AsVariableProxy(); 542 VariableProxy* proxy = callee_expr->AsVariableProxy();
430 VisitVariableLoad(proxy->var()); 543 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
431 builder().StoreAccumulatorInRegister(callee); 544 builder().StoreAccumulatorInRegister(callee);
432 break; 545 break;
433 } 546 }
434 case Call::LOOKUP_SLOT_CALL: 547 case Call::LOOKUP_SLOT_CALL:
435 case Call::SUPER_CALL: 548 case Call::SUPER_CALL:
436 case Call::POSSIBLY_EVAL_CALL: 549 case Call::POSSIBLY_EVAL_CALL:
437 case Call::OTHER_CALL: 550 case Call::OTHER_CALL:
438 UNIMPLEMENTED(); 551 UNIMPLEMENTED();
439 } 552 }
440 553
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
563 676
564 LanguageMode BytecodeGenerator::language_mode() const { 677 LanguageMode BytecodeGenerator::language_mode() const {
565 return info()->language_mode(); 678 return info()->language_mode();
566 } 679 }
567 680
568 681
569 int BytecodeGenerator::feedback_index(FeedbackVectorICSlot slot) const { 682 int BytecodeGenerator::feedback_index(FeedbackVectorICSlot slot) const {
570 return info()->feedback_vector()->GetIndex(slot); 683 return info()->feedback_vector()->GetIndex(slot);
571 } 684 }
572 685
686
687 Register BytecodeGenerator::current_context() const { return current_context_; }
688
573 } // namespace interpreter 689 } // namespace interpreter
574 } // namespace internal 690 } // namespace internal
575 } // namespace v8 691 } // 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