OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |