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> | |
8 | |
9 #include "src/compiler.h" | 7 #include "src/compiler.h" |
10 #include "src/interpreter/control-flow-builders.h" | 8 #include "src/interpreter/control-flow-builders.h" |
11 #include "src/objects.h" | 9 #include "src/objects.h" |
12 #include "src/parser.h" | 10 #include "src/parser.h" |
13 #include "src/scopes.h" | 11 #include "src/scopes.h" |
14 #include "src/token.h" | 12 #include "src/token.h" |
15 | 13 |
16 namespace v8 { | 14 namespace v8 { |
17 namespace internal { | 15 namespace internal { |
18 namespace interpreter { | 16 namespace interpreter { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
139 Statement* statement) { | 137 Statement* statement) { |
140 ControlScope* current = this; | 138 ControlScope* current = this; |
141 do { | 139 do { |
142 if (current->Execute(command, statement)) return; | 140 if (current->Execute(command, statement)) return; |
143 current = current->outer(); | 141 current = current->outer(); |
144 } while (current != nullptr); | 142 } while (current != nullptr); |
145 UNREACHABLE(); | 143 UNREACHABLE(); |
146 } | 144 } |
147 | 145 |
148 | 146 |
147 // Scoped base class for determining where the result of an expression | |
148 // is stored. | |
149 class BytecodeGenerator::ExpressionResultScope { | |
150 public: | |
151 explicit ExpressionResultScope(BytecodeGenerator* generator) | |
152 : generator_(generator), | |
153 parent_(generator->result_scope()), | |
154 allocator_(builder()), | |
155 result_identified_(false) { | |
156 generator_->set_result_scope(this); | |
157 } | |
158 | |
159 virtual ~ExpressionResultScope() { | |
160 generator_->set_result_scope(parent_); | |
161 DCHECK_EQ(result_identified(), true); | |
162 } | |
163 | |
164 virtual void SetResultInAccumulator() = 0; | |
165 virtual void SetResultInRegister(Register reg) = 0; | |
166 | |
167 BytecodeGenerator* generator() const { return generator_; } | |
168 BytecodeArrayBuilder* builder() const { return generator()->builder(); } | |
169 ExpressionResultScope* parent() const { return parent_; } | |
rmcilroy
2015/10/19 12:56:22
nit - outer() and outer_ to be consistent with oth
oth
2015/10/20 15:28:52
Done.
| |
170 | |
171 Register NewRegister() { return allocator_.NewRegister(); } | |
172 void PrepareForConsecutiveAllocations(size_t count) { | |
173 allocator_.PrepareForConsecutiveAllocations(count); | |
174 } | |
175 | |
176 protected: | |
177 void set_result_identified() { | |
178 DCHECK(!result_identified()); | |
179 result_identified_ = true; | |
180 } | |
181 | |
182 bool result_identified() const { return result_identified_; } | |
183 | |
184 private: | |
185 BytecodeGenerator* generator_; | |
186 ExpressionResultScope* parent_; | |
187 TemporaryRegisterScope allocator_; | |
188 bool result_identified_; | |
189 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); | |
190 }; | |
191 | |
192 | |
193 // Scoped class used for the top-level management of an expression scope. | |
194 // Specifically mapping registers across an expresion. | |
rmcilroy
2015/10/19 12:56:22
expression / expresion (although this class should
oth
2015/10/20 15:28:52
Done.
| |
195 class BytecodeGenerator::TopLevelResultScope final | |
196 : public ExpressionResultScope { | |
197 public: | |
198 explicit TopLevelResultScope(BytecodeGenerator* generator) | |
199 : ExpressionResultScope(generator) { | |
200 generator->set_top_level_result_scope(this); | |
201 set_result_identified(); | |
202 } | |
203 virtual ~TopLevelResultScope() { | |
rmcilroy
2015/10/19 12:56:22
nit newline above
oth
2015/10/20 15:28:52
Class removed.
| |
204 generator()->set_top_level_result_scope(nullptr); | |
205 } | |
206 | |
207 virtual void SetResultInAccumulator() { set_result_identified(); } | |
208 virtual void SetResultInRegister(Register reg) { set_result_identified(); } | |
209 }; | |
210 | |
211 | |
212 // Scoped class used when the result of the current expression to be | |
213 // evaluated should go into the interpreter's accumulator register. | |
214 class BytecodeGenerator::AccumulatorResultScope final | |
215 : public ExpressionResultScope { | |
216 public: | |
217 explicit AccumulatorResultScope(BytecodeGenerator* generator) | |
218 : ExpressionResultScope(generator) {} | |
219 virtual void SetResultInAccumulator() { | |
220 if (!result_identified()) { | |
221 // TODO(oth): REVIEW. | |
rmcilroy
2015/10/19 12:56:22
Can we remove the "if (!result_identified())" now?
oth
2015/10/20 15:28:52
Done.
| |
222 set_result_identified(); | |
223 } | |
224 } | |
225 virtual void SetResultInRegister(Register reg) { | |
rmcilroy
2015/10/19 12:56:23
nit - newline above
oth
2015/10/20 15:28:52
Done.
| |
226 builder()->LoadAccumulatorWithRegister(reg); | |
227 set_result_identified(); | |
228 } | |
229 }; | |
230 | |
231 | |
232 // Scoped class used when the result of the current expression is not | |
233 // expected to produce a result. | |
234 class BytecodeGenerator::EffectResultScope final | |
235 : public ExpressionResultScope { | |
236 public: | |
237 explicit EffectResultScope(BytecodeGenerator* generator) | |
238 : ExpressionResultScope(generator) { | |
239 set_result_identified(); | |
240 } | |
241 virtual void SetResultInAccumulator() {} | |
242 virtual void SetResultInRegister(Register reg) {} | |
243 }; | |
rmcilroy
2015/10/19 12:56:22
nit - could you move this above BytecodeGenerator:
oth
2015/10/20 15:28:52
Done.
| |
244 | |
245 | |
246 // Scoped class used when the result of the current expression to be | |
247 // evaluated should go into an interpreter register. | |
248 class BytecodeGenerator::RegisterResultScope final | |
249 : public ExpressionResultScope { | |
250 public: | |
251 explicit RegisterResultScope(BytecodeGenerator* generator) | |
252 : ExpressionResultScope(generator) {} | |
253 ~RegisterResultScope() {} | |
254 | |
255 virtual void SetResultInAccumulator() { | |
256 result_register_ = parent()->NewRegister(); | |
257 builder()->StoreAccumulatorInRegister(result_register_); | |
258 set_result_identified(); | |
259 } | |
260 | |
261 virtual void SetResultInRegister(Register reg) { | |
262 result_register_ = reg; | |
263 set_result_identified(); | |
264 } | |
265 | |
266 Register ResultRegister() const { return result_register_; } | |
267 | |
268 private: | |
269 Register result_register_; | |
270 }; | |
271 | |
272 | |
149 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) | 273 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) |
150 : isolate_(isolate), | 274 : isolate_(isolate), |
151 zone_(zone), | 275 zone_(zone), |
152 builder_(isolate, zone), | 276 builder_(isolate, zone), |
153 info_(nullptr), | 277 info_(nullptr), |
154 scope_(nullptr), | 278 scope_(nullptr), |
155 globals_(0, zone), | 279 globals_(0, zone), |
156 execution_control_(nullptr), | 280 execution_control_(nullptr), |
157 execution_context_(nullptr) { | 281 execution_context_(nullptr), |
282 result_scope_(nullptr), | |
283 top_level_result_scope_(nullptr), | |
284 binary_expression_depth_(0), | |
285 binary_expression_hazard_set_(zone) { | |
158 InitializeAstVisitor(isolate); | 286 InitializeAstVisitor(isolate); |
159 } | 287 } |
160 | 288 |
161 | 289 |
162 BytecodeGenerator::~BytecodeGenerator() {} | 290 BytecodeGenerator::~BytecodeGenerator() {} |
163 | 291 |
164 | 292 |
293 void BytecodeGenerator::set_result_scope(ExpressionResultScope* result_scope) { | |
294 result_scope_ = result_scope; | |
rmcilroy
2015/10/19 12:56:22
nit - just inline this in header
oth
2015/10/20 15:28:52
Done.
| |
295 } | |
296 | |
297 | |
298 BytecodeGenerator::ExpressionResultScope* BytecodeGenerator::result_scope() | |
rmcilroy
2015/10/19 12:56:23
ditto
oth
2015/10/20 15:28:52
Done.
| |
299 const { | |
300 return result_scope_; | |
301 } | |
302 | |
303 | |
304 BytecodeGenerator::ExpressionResultScope* | |
305 BytecodeGenerator::parent_result_scope() const { | |
rmcilroy
2015/10/19 12:56:22
Unused, please remove (callers could just do resul
oth
2015/10/20 15:28:52
Done.
| |
306 return result_scope_->parent(); | |
307 } | |
308 | |
309 void BytecodeGenerator::set_top_level_result_scope( | |
310 TopLevelResultScope* result_scope) { | |
311 DCHECK((result_scope == nullptr && top_level_result_scope_ != nullptr) || | |
312 (result_scope != nullptr && top_level_result_scope_ == nullptr)); | |
313 top_level_result_scope_ = result_scope; | |
314 } | |
315 | |
316 BytecodeGenerator::TopLevelResultScope* | |
317 BytecodeGenerator::top_level_result_scope() const { | |
318 return top_level_result_scope_; | |
319 } | |
320 | |
321 | |
165 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 322 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { |
166 set_info(info); | 323 set_info(info); |
167 set_scope(info->scope()); | 324 set_scope(info->scope()); |
168 | 325 |
169 // Initialize the incoming context. | 326 // Initialize the incoming context. |
170 ContextScope incoming_context(this, scope(), false); | 327 ContextScope incoming_context(this, scope(), false); |
171 | 328 |
172 builder()->set_parameter_count(info->num_parameters_including_this()); | 329 builder()->set_parameter_count(info->num_parameters_including_this()); |
173 builder()->set_locals_count(scope()->num_stack_slots()); | 330 builder()->set_locals_count(scope()->num_stack_slots()); |
174 builder()->set_context_count(scope()->MaxNestedContextChainLength()); | 331 builder()->set_context_count(scope()->MaxNestedContextChainLength()); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); | 474 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); |
318 builder()->StoreAccumulatorInRegister(flags); | 475 builder()->StoreAccumulatorInRegister(flags); |
319 DCHECK(flags.index() == pairs.index() + 1); | 476 DCHECK(flags.index() == pairs.index() + 1); |
320 | 477 |
321 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); | 478 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); |
322 globals()->clear(); | 479 globals()->clear(); |
323 } | 480 } |
324 | 481 |
325 | 482 |
326 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { | 483 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { |
327 Visit(stmt->expression()); | 484 TopLevelResultScope result_scope(this); |
485 VisitForAccumulatorValue(stmt->expression()); | |
rmcilroy
2015/10/19 12:56:23
VisitForEffect here I think? Following statements
oth
2015/10/20 15:28:53
Done.
| |
328 } | 486 } |
329 | 487 |
330 | 488 |
331 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { | 489 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { |
332 // TODO(oth): For control-flow it could be useful to signal empty paths here. | |
333 } | 490 } |
334 | 491 |
335 | 492 |
336 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { | 493 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { |
337 // TODO(oth): Spot easy cases where there code would not need to | 494 // TODO(oth): Spot easy cases where there code would not need to |
338 // emit the then block or the else block, e.g. condition is | 495 // emit the then block or the else block, e.g. condition is |
339 // obviously true/1/false/0. | 496 // obviously true/1/false/0. |
340 | 497 |
341 BytecodeLabel else_label, end_label; | 498 BytecodeLabel else_label, end_label; |
342 | 499 |
343 Visit(stmt->condition()); | 500 VisitForAccumulatorValue(stmt->condition()); |
344 builder()->CastAccumulatorToBoolean(); | 501 builder()->CastAccumulatorToBoolean(); |
345 builder()->JumpIfFalse(&else_label); | 502 builder()->JumpIfFalse(&else_label); |
346 Visit(stmt->then_statement()); | 503 Visit(stmt->then_statement()); |
347 if (stmt->HasElseStatement()) { | 504 if (stmt->HasElseStatement()) { |
348 builder()->Jump(&end_label); | 505 builder()->Jump(&end_label); |
349 builder()->Bind(&else_label); | 506 builder()->Bind(&else_label); |
350 Visit(stmt->else_statement()); | 507 Visit(stmt->else_statement()); |
351 } else { | 508 } else { |
352 builder()->Bind(&else_label); | 509 builder()->Bind(&else_label); |
353 } | 510 } |
(...skipping 11 matching lines...) Expand all Loading... | |
365 execution_control()->Continue(stmt->target()); | 522 execution_control()->Continue(stmt->target()); |
366 } | 523 } |
367 | 524 |
368 | 525 |
369 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 526 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { |
370 execution_control()->Break(stmt->target()); | 527 execution_control()->Break(stmt->target()); |
371 } | 528 } |
372 | 529 |
373 | 530 |
374 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 531 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { |
375 Visit(stmt->expression()); | 532 TopLevelResultScope scope(this); |
rmcilroy
2015/10/19 12:56:22
Given my comment above about removing TopLevelResu
oth
2015/10/20 15:28:53
Ack. Removed for now, the newer name is fine.
| |
533 VisitForAccumulatorValue(stmt->expression()); | |
376 builder()->Return(); | 534 builder()->Return(); |
377 } | 535 } |
378 | 536 |
379 | 537 |
380 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 538 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { |
381 UNIMPLEMENTED(); | 539 UNIMPLEMENTED(); |
382 } | 540 } |
383 | 541 |
384 | 542 |
385 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 543 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { |
386 UNIMPLEMENTED(); | 544 UNIMPLEMENTED(); |
387 } | 545 } |
388 | 546 |
389 | 547 |
390 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } | 548 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } |
391 | 549 |
392 | 550 |
393 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 551 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { |
394 LoopBuilder loop_builder(builder()); | 552 LoopBuilder loop_builder(builder()); |
395 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 553 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
396 | 554 |
397 BytecodeLabel body_label, condition_label, done_label; | 555 BytecodeLabel body_label, condition_label, done_label; |
398 builder()->Bind(&body_label); | 556 builder()->Bind(&body_label); |
399 Visit(stmt->body()); | 557 Visit(stmt->body()); |
400 builder()->Bind(&condition_label); | 558 builder()->Bind(&condition_label); |
401 Visit(stmt->cond()); | 559 VisitForAccumulatorValue(stmt->cond()); |
402 builder()->JumpIfTrue(&body_label); | 560 builder()->JumpIfTrue(&body_label); |
403 builder()->Bind(&done_label); | 561 builder()->Bind(&done_label); |
404 | 562 |
405 loop_builder.SetBreakTarget(done_label); | 563 loop_builder.SetBreakTarget(done_label); |
406 loop_builder.SetContinueTarget(condition_label); | 564 loop_builder.SetContinueTarget(condition_label); |
407 } | 565 } |
408 | 566 |
409 | 567 |
410 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 568 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { |
411 LoopBuilder loop_builder(builder()); | 569 LoopBuilder loop_builder(builder()); |
412 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 570 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
413 | 571 |
414 BytecodeLabel body_label, condition_label, done_label; | 572 BytecodeLabel body_label, condition_label, done_label; |
415 builder()->Jump(&condition_label); | 573 builder()->Jump(&condition_label); |
416 builder()->Bind(&body_label); | 574 builder()->Bind(&body_label); |
417 Visit(stmt->body()); | 575 Visit(stmt->body()); |
418 builder()->Bind(&condition_label); | 576 builder()->Bind(&condition_label); |
419 Visit(stmt->cond()); | 577 VisitForAccumulatorValue(stmt->cond()); |
420 builder()->JumpIfTrue(&body_label); | 578 builder()->JumpIfTrue(&body_label); |
421 builder()->Bind(&done_label); | 579 builder()->Bind(&done_label); |
422 | 580 |
423 loop_builder.SetBreakTarget(done_label); | 581 loop_builder.SetBreakTarget(done_label); |
424 loop_builder.SetContinueTarget(condition_label); | 582 loop_builder.SetContinueTarget(condition_label); |
425 } | 583 } |
426 | 584 |
427 | 585 |
428 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 586 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { |
429 LoopBuilder loop_builder(builder()); | 587 LoopBuilder loop_builder(builder()); |
430 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 588 ControlScopeForIteration execution_control(this, stmt, &loop_builder); |
431 | 589 |
432 if (stmt->init() != nullptr) { | 590 if (stmt->init() != nullptr) { |
433 Visit(stmt->init()); | 591 Visit(stmt->init()); |
434 } | 592 } |
435 | 593 |
436 BytecodeLabel body_label, condition_label, next_label, done_label; | 594 BytecodeLabel body_label, condition_label, next_label, done_label; |
437 if (stmt->cond() != nullptr) { | 595 if (stmt->cond() != nullptr) { |
438 builder()->Jump(&condition_label); | 596 builder()->Jump(&condition_label); |
439 } | 597 } |
440 builder()->Bind(&body_label); | 598 builder()->Bind(&body_label); |
441 Visit(stmt->body()); | 599 Visit(stmt->body()); |
442 builder()->Bind(&next_label); | 600 builder()->Bind(&next_label); |
443 if (stmt->next() != nullptr) { | 601 if (stmt->next() != nullptr) { |
444 Visit(stmt->next()); | 602 Visit(stmt->next()); |
445 } | 603 } |
446 if (stmt->cond()) { | 604 if (stmt->cond()) { |
447 builder()->Bind(&condition_label); | 605 builder()->Bind(&condition_label); |
448 Visit(stmt->cond()); | 606 VisitForAccumulatorValue(stmt->cond()); |
449 builder()->JumpIfTrue(&body_label); | 607 builder()->JumpIfTrue(&body_label); |
450 } else { | 608 } else { |
451 builder()->Jump(&body_label); | 609 builder()->Jump(&body_label); |
452 } | 610 } |
453 builder()->Bind(&done_label); | 611 builder()->Bind(&done_label); |
454 | 612 |
455 loop_builder.SetBreakTarget(done_label); | 613 loop_builder.SetBreakTarget(done_label); |
456 loop_builder.SetContinueTarget(next_label); | 614 loop_builder.SetContinueTarget(next_label); |
457 } | 615 } |
458 | 616 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
493 | 651 |
494 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { | 652 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) { |
495 // Find or build a shared function info. | 653 // Find or build a shared function info. |
496 Handle<SharedFunctionInfo> shared_info = | 654 Handle<SharedFunctionInfo> shared_info = |
497 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); | 655 Compiler::GetSharedFunctionInfo(expr, info()->script(), info()); |
498 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow? | 656 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow? |
499 | 657 |
500 builder() | 658 builder() |
501 ->LoadLiteral(shared_info) | 659 ->LoadLiteral(shared_info) |
502 .CreateClosure(expr->pretenure() ? TENURED : NOT_TENURED); | 660 .CreateClosure(expr->pretenure() ? TENURED : NOT_TENURED); |
661 result_scope()->SetResultInAccumulator(); | |
503 } | 662 } |
504 | 663 |
505 | 664 |
506 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { | 665 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) { |
507 UNIMPLEMENTED(); | 666 UNIMPLEMENTED(); |
508 } | 667 } |
509 | 668 |
510 | 669 |
511 void BytecodeGenerator::VisitNativeFunctionLiteral( | 670 void BytecodeGenerator::VisitNativeFunctionLiteral( |
512 NativeFunctionLiteral* expr) { | 671 NativeFunctionLiteral* expr) { |
(...skipping 14 matching lines...) Expand all Loading... | |
527 builder()->LoadTrue(); | 686 builder()->LoadTrue(); |
528 } else if (value->IsFalse()) { | 687 } else if (value->IsFalse()) { |
529 builder()->LoadFalse(); | 688 builder()->LoadFalse(); |
530 } else if (value->IsNull()) { | 689 } else if (value->IsNull()) { |
531 builder()->LoadNull(); | 690 builder()->LoadNull(); |
532 } else if (value->IsTheHole()) { | 691 } else if (value->IsTheHole()) { |
533 builder()->LoadTheHole(); | 692 builder()->LoadTheHole(); |
534 } else { | 693 } else { |
535 builder()->LoadLiteral(value); | 694 builder()->LoadLiteral(value); |
536 } | 695 } |
696 result_scope()->SetResultInAccumulator(); | |
537 } | 697 } |
538 | 698 |
539 | 699 |
540 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { | 700 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) { |
541 // Materialize a regular expression literal. | 701 // Materialize a regular expression literal. |
542 TemporaryRegisterScope temporary_register_scope(builder()); | 702 TemporaryRegisterScope temporary_register_scope(builder()); |
543 Register flags = temporary_register_scope.NewRegister(); | 703 Register flags = temporary_register_scope.NewRegister(); |
544 builder() | 704 builder() |
545 ->LoadLiteral(expr->flags()) | 705 ->LoadLiteral(expr->flags()) |
546 .StoreAccumulatorInRegister(flags) | 706 .StoreAccumulatorInRegister(flags) |
547 .LoadLiteral(expr->pattern()) | 707 .LoadLiteral(expr->pattern()) |
548 .CreateRegExpLiteral(expr->literal_index(), flags); | 708 .CreateRegExpLiteral(expr->literal_index(), flags); |
709 result_scope()->SetResultInAccumulator(); | |
549 } | 710 } |
550 | 711 |
551 | 712 |
552 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { | 713 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) { |
553 // Deep-copy the literal boilerplate. | 714 // Deep-copy the literal boilerplate. |
554 builder() | 715 builder() |
555 ->LoadLiteral(expr->constant_properties()) | 716 ->LoadLiteral(expr->constant_properties()) |
556 .CreateObjectLiteral(expr->literal_index(), expr->ComputeFlags(true)); | 717 .CreateObjectLiteral(expr->literal_index(), expr->ComputeFlags(true)); |
557 | 718 |
558 TemporaryRegisterScope temporary_register_scope(builder()); | 719 TemporaryRegisterScope temporary_register_scope(builder()); |
(...skipping 24 matching lines...) Expand all Loading... | |
583 // Fall through. | 744 // Fall through. |
584 case ObjectLiteral::Property::COMPUTED: { | 745 case ObjectLiteral::Property::COMPUTED: { |
585 // It is safe to use [[Put]] here because the boilerplate already | 746 // It is safe to use [[Put]] here because the boilerplate already |
586 // contains computed properties with an uninitialized value. | 747 // contains computed properties with an uninitialized value. |
587 if (literal_key->value()->IsInternalizedString()) { | 748 if (literal_key->value()->IsInternalizedString()) { |
588 if (property->emit_store()) { | 749 if (property->emit_store()) { |
589 Register name = inner_temporary_register_scope.NewRegister(); | 750 Register name = inner_temporary_register_scope.NewRegister(); |
590 builder() | 751 builder() |
591 ->LoadLiteral(literal_key->AsPropertyName()) | 752 ->LoadLiteral(literal_key->AsPropertyName()) |
592 .StoreAccumulatorInRegister(name); | 753 .StoreAccumulatorInRegister(name); |
593 Visit(property->value()); | 754 VisitForAccumulatorValue(property->value()); |
594 builder()->StoreNamedProperty(literal, name, | 755 builder()->StoreNamedProperty(literal, name, |
595 feedback_index(property->GetSlot(0)), | 756 feedback_index(property->GetSlot(0)), |
596 language_mode()); | 757 language_mode()); |
597 } else { | 758 } else { |
598 Visit(property->value()); | 759 VisitForAccumulatorValue(property->value()); |
rmcilroy
2015/10/19 12:56:22
VisitForEffect here
oth
2015/10/20 15:28:53
Done.
| |
599 } | 760 } |
600 } else { | 761 } else { |
601 Register key = inner_temporary_register_scope.NewRegister(); | 762 Register key = inner_temporary_register_scope.NewRegister(); |
602 Register value = inner_temporary_register_scope.NewRegister(); | 763 Register value = inner_temporary_register_scope.NewRegister(); |
603 Register language = inner_temporary_register_scope.NewRegister(); | 764 Register language = inner_temporary_register_scope.NewRegister(); |
765 // TODO(oth): This is problematic - can't assume contiguous here. | |
766 // literal is allocated in temporary_register_scope, whereas | |
767 // key, value, language are in another. | |
rmcilroy
2015/10/19 12:56:22
Can we use PrepareForConsecutiveAllocations at the
oth
2015/10/20 15:28:53
Done.
| |
604 DCHECK(Register::AreContiguous(literal, key, value, language)); | 768 DCHECK(Register::AreContiguous(literal, key, value, language)); |
605 Visit(property->key()); | 769 VisitForAccumulatorValue(property->key()); |
606 builder()->StoreAccumulatorInRegister(key); | 770 builder()->StoreAccumulatorInRegister(key); |
607 Visit(property->value()); | 771 VisitForAccumulatorValue(property->value()); |
608 builder()->StoreAccumulatorInRegister(value); | 772 builder()->StoreAccumulatorInRegister(value); |
609 if (property->emit_store()) { | 773 if (property->emit_store()) { |
610 builder() | 774 builder() |
611 ->LoadLiteral(Smi::FromInt(SLOPPY)) | 775 ->LoadLiteral(Smi::FromInt(SLOPPY)) |
612 .StoreAccumulatorInRegister(language) | 776 .StoreAccumulatorInRegister(language) |
613 .CallRuntime(Runtime::kSetProperty, literal, 4); | 777 .CallRuntime(Runtime::kSetProperty, literal, 4); |
614 VisitSetHomeObject(value, literal, property); | 778 VisitSetHomeObject(value, literal, property); |
615 } | 779 } |
616 } | 780 } |
617 break; | 781 break; |
618 } | 782 } |
619 case ObjectLiteral::Property::PROTOTYPE: { | 783 case ObjectLiteral::Property::PROTOTYPE: { |
620 DCHECK(property->emit_store()); | 784 DCHECK(property->emit_store()); |
621 Register value = inner_temporary_register_scope.NewRegister(); | 785 Register value = inner_temporary_register_scope.NewRegister(); |
622 DCHECK(Register::AreContiguous(literal, value)); | 786 DCHECK(Register::AreContiguous(literal, value)); |
623 Visit(property->value()); | 787 VisitForAccumulatorValue(property->value()); |
624 builder()->StoreAccumulatorInRegister(value).CallRuntime( | 788 builder()->StoreAccumulatorInRegister(value).CallRuntime( |
625 Runtime::kInternalSetPrototype, literal, 2); | 789 Runtime::kInternalSetPrototype, literal, 2); |
626 break; | 790 break; |
627 } | 791 } |
628 case ObjectLiteral::Property::GETTER: | 792 case ObjectLiteral::Property::GETTER: |
629 if (property->emit_store()) { | 793 if (property->emit_store()) { |
630 accessor_table.lookup(literal_key)->second->getter = property; | 794 accessor_table.lookup(literal_key)->second->getter = property; |
631 } | 795 } |
632 break; | 796 break; |
633 case ObjectLiteral::Property::SETTER: | 797 case ObjectLiteral::Property::SETTER: |
634 if (property->emit_store()) { | 798 if (property->emit_store()) { |
635 accessor_table.lookup(literal_key)->second->setter = property; | 799 accessor_table.lookup(literal_key)->second->setter = property; |
636 } | 800 } |
637 break; | 801 break; |
638 } | 802 } |
639 } | 803 } |
640 | 804 |
641 // Define accessors, using only a single call to the runtime for each pair of | 805 // Define accessors, using only a single call to the runtime for each pair of |
642 // corresponding getters and setters. | 806 // corresponding getters and setters. |
643 for (AccessorTable::Iterator it = accessor_table.begin(); | 807 for (AccessorTable::Iterator it = accessor_table.begin(); |
644 it != accessor_table.end(); ++it) { | 808 it != accessor_table.end(); ++it) { |
645 TemporaryRegisterScope inner_temporary_register_scope(builder()); | 809 TemporaryRegisterScope inner_temporary_register_scope(builder()); |
646 Register name = inner_temporary_register_scope.NewRegister(); | 810 Register name = inner_temporary_register_scope.NewRegister(); |
647 Register getter = inner_temporary_register_scope.NewRegister(); | 811 Register getter = inner_temporary_register_scope.NewRegister(); |
648 Register setter = inner_temporary_register_scope.NewRegister(); | 812 Register setter = inner_temporary_register_scope.NewRegister(); |
649 Register attr = inner_temporary_register_scope.NewRegister(); | 813 Register attr = inner_temporary_register_scope.NewRegister(); |
650 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); | 814 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); |
651 Visit(it->first); | 815 VisitForAccumulatorValue(it->first); |
652 builder()->StoreAccumulatorInRegister(name); | 816 builder()->StoreAccumulatorInRegister(name); |
653 VisitObjectLiteralAccessor(literal, it->second->getter, getter); | 817 VisitObjectLiteralAccessor(literal, it->second->getter, getter); |
654 VisitObjectLiteralAccessor(literal, it->second->setter, setter); | 818 VisitObjectLiteralAccessor(literal, it->second->setter, setter); |
655 builder() | 819 builder() |
656 ->LoadLiteral(Smi::FromInt(NONE)) | 820 ->LoadLiteral(Smi::FromInt(NONE)) |
657 .StoreAccumulatorInRegister(attr) | 821 .StoreAccumulatorInRegister(attr) |
658 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); | 822 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5); |
659 } | 823 } |
660 | 824 |
661 // Object literals have two parts. The "static" part on the left contains no | 825 // Object literals have two parts. The "static" part on the left contains no |
662 // computed property names, and so we can compute its map ahead of time; see | 826 // computed property names, and so we can compute its map ahead of time; see |
663 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts | 827 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts |
664 // with the first computed property name and continues with all properties to | 828 // with the first computed property name and continues with all properties to |
665 // its right. All the code from above initializes the static component of the | 829 // its right. All the code from above initializes the static component of the |
666 // object literal, and arranges for the map of the result to reflect the | 830 // object literal, and arranges for the map of the result to reflect the |
667 // static order in which the keys appear. For the dynamic properties, we | 831 // static order in which the keys appear. For the dynamic properties, we |
668 // compile them into a series of "SetOwnProperty" runtime calls. This will | 832 // compile them into a series of "SetOwnProperty" runtime calls. This will |
669 // preserve insertion order. | 833 // preserve insertion order. |
670 for (; property_index < expr->properties()->length(); property_index++) { | 834 for (; property_index < expr->properties()->length(); property_index++) { |
671 ObjectLiteral::Property* property = expr->properties()->at(property_index); | 835 ObjectLiteral::Property* property = expr->properties()->at(property_index); |
672 | 836 |
673 if (literal_in_accumulator) { | 837 if (literal_in_accumulator) { |
838 temporary_register_scope.PrepareForConsecutiveAllocations(4); | |
674 literal = temporary_register_scope.NewRegister(); | 839 literal = temporary_register_scope.NewRegister(); |
675 builder()->StoreAccumulatorInRegister(literal); | 840 builder()->StoreAccumulatorInRegister(literal); |
676 literal_in_accumulator = false; | 841 literal_in_accumulator = false; |
677 } | 842 } |
678 | 843 |
679 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { | 844 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) { |
680 DCHECK(property->emit_store()); | 845 DCHECK(property->emit_store()); |
681 TemporaryRegisterScope inner_temporary_register_scope(builder()); | 846 TemporaryRegisterScope inner_temporary_register_scope(builder()); |
682 Register value = inner_temporary_register_scope.NewRegister(); | 847 Register value = inner_temporary_register_scope.NewRegister(); |
683 DCHECK(Register::AreContiguous(literal, value)); | 848 DCHECK(Register::AreContiguous(literal, value)); |
684 Visit(property->value()); | 849 VisitForAccumulatorValue(property->value()); |
685 builder()->StoreAccumulatorInRegister(value).CallRuntime( | 850 builder()->StoreAccumulatorInRegister(value).CallRuntime( |
686 Runtime::kInternalSetPrototype, literal, 2); | 851 Runtime::kInternalSetPrototype, literal, 2); |
687 continue; | 852 continue; |
688 } | 853 } |
689 | 854 |
690 TemporaryRegisterScope inner_temporary_register_scope(builder()); | 855 TemporaryRegisterScope inner_temporary_register_scope(builder()); |
856 inner_temporary_register_scope.PrepareForConsecutiveAllocations(3); | |
691 Register key = inner_temporary_register_scope.NewRegister(); | 857 Register key = inner_temporary_register_scope.NewRegister(); |
692 Register value = inner_temporary_register_scope.NewRegister(); | 858 Register value = inner_temporary_register_scope.NewRegister(); |
693 Register attr = inner_temporary_register_scope.NewRegister(); | 859 Register attr = inner_temporary_register_scope.NewRegister(); |
694 DCHECK(Register::AreContiguous(literal, key, value, attr)); | 860 DCHECK(Register::AreContiguous(literal, key, value, attr)); |
695 | 861 |
696 Visit(property->key()); | 862 VisitForAccumulatorValue(property->key()); |
697 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); | 863 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key); |
698 Visit(property->value()); | 864 VisitForAccumulatorValue(property->value()); |
699 builder()->StoreAccumulatorInRegister(value); | 865 builder()->StoreAccumulatorInRegister(value); |
700 VisitSetHomeObject(value, literal, property); | 866 VisitSetHomeObject(value, literal, property); |
701 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); | 867 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr); |
702 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); | 868 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1); |
703 switch (property->kind()) { | 869 switch (property->kind()) { |
704 case ObjectLiteral::Property::CONSTANT: | 870 case ObjectLiteral::Property::CONSTANT: |
705 case ObjectLiteral::Property::COMPUTED: | 871 case ObjectLiteral::Property::COMPUTED: |
706 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 872 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
707 function_id = Runtime::kDefineDataPropertyUnchecked; | 873 function_id = Runtime::kDefineDataPropertyUnchecked; |
708 break; | 874 break; |
(...skipping 13 matching lines...) Expand all Loading... | |
722 // Transform literals that contain functions to fast properties. | 888 // Transform literals that contain functions to fast properties. |
723 if (expr->has_function()) { | 889 if (expr->has_function()) { |
724 DCHECK(!literal_in_accumulator); | 890 DCHECK(!literal_in_accumulator); |
725 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); | 891 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1); |
726 } | 892 } |
727 | 893 |
728 if (!literal_in_accumulator) { | 894 if (!literal_in_accumulator) { |
729 // Restore literal array into accumulator. | 895 // Restore literal array into accumulator. |
730 builder()->LoadAccumulatorWithRegister(literal); | 896 builder()->LoadAccumulatorWithRegister(literal); |
731 } | 897 } |
898 result_scope()->SetResultInAccumulator(); | |
732 } | 899 } |
733 | 900 |
734 | 901 |
735 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 902 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { |
736 // Deep-copy the literal boilerplate. | 903 // Deep-copy the literal boilerplate. |
737 builder() | 904 builder() |
738 ->LoadLiteral(expr->constant_elements()) | 905 ->LoadLiteral(expr->constant_elements()) |
739 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true)); | 906 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true)); |
740 | 907 |
741 TemporaryRegisterScope temporary_register_scope(builder()); | 908 TemporaryRegisterScope temporary_register_scope(builder()); |
(...skipping 14 matching lines...) Expand all Loading... | |
756 if (literal_in_accumulator) { | 923 if (literal_in_accumulator) { |
757 index = temporary_register_scope.NewRegister(); | 924 index = temporary_register_scope.NewRegister(); |
758 literal = temporary_register_scope.NewRegister(); | 925 literal = temporary_register_scope.NewRegister(); |
759 builder()->StoreAccumulatorInRegister(literal); | 926 builder()->StoreAccumulatorInRegister(literal); |
760 literal_in_accumulator = false; | 927 literal_in_accumulator = false; |
761 } | 928 } |
762 | 929 |
763 builder() | 930 builder() |
764 ->LoadLiteral(Smi::FromInt(array_index)) | 931 ->LoadLiteral(Smi::FromInt(array_index)) |
765 .StoreAccumulatorInRegister(index); | 932 .StoreAccumulatorInRegister(index); |
766 Visit(subexpr); | 933 VisitForAccumulatorValue(subexpr); |
767 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot(); | 934 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot(); |
rmcilroy
2015/10/19 12:56:22
nit - (I know this was my code..) could you move t
oth
2015/10/20 15:28:52
Done.
| |
768 builder()->StoreKeyedProperty(literal, index, feedback_index(slot), | 935 builder()->StoreKeyedProperty(literal, index, feedback_index(slot), |
769 language_mode()); | 936 language_mode()); |
770 } | 937 } |
771 | 938 |
772 if (!literal_in_accumulator) { | 939 if (!literal_in_accumulator) { |
773 // Restore literal array into accumulator. | 940 // Restore literal array into accumulator. |
774 builder()->LoadAccumulatorWithRegister(literal); | 941 builder()->LoadAccumulatorWithRegister(literal); |
775 } | 942 } |
943 result_scope()->SetResultInAccumulator(); | |
776 } | 944 } |
777 | 945 |
778 | 946 |
779 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { | 947 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) { |
780 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 948 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
781 } | 949 } |
782 | 950 |
783 | 951 |
784 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 952 void BytecodeGenerator::VisitVariableLoad(Variable* variable, |
785 FeedbackVectorSlot slot) { | 953 FeedbackVectorSlot slot) { |
786 switch (variable->location()) { | 954 switch (variable->location()) { |
787 case VariableLocation::LOCAL: { | 955 case VariableLocation::LOCAL: { |
788 Register source(variable->index()); | 956 Register source(Register(variable->index())); |
789 builder()->LoadAccumulatorWithRegister(source); | 957 result_scope()->SetResultInRegister(source); |
790 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and | |
791 // let variables. | |
792 break; | 958 break; |
793 } | 959 } |
794 case VariableLocation::PARAMETER: { | 960 case VariableLocation::PARAMETER: { |
795 // The parameter indices are shifted by 1 (receiver is variable | 961 // The parameter indices are shifted by 1 (receiver is variable |
796 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 962 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
797 Register source(builder()->Parameter(variable->index() + 1)); | 963 Register source = builder()->Parameter(variable->index() + 1); |
798 builder()->LoadAccumulatorWithRegister(source); | 964 result_scope()->SetResultInRegister(source); |
799 break; | 965 break; |
800 } | 966 } |
801 case VariableLocation::GLOBAL: { | 967 case VariableLocation::GLOBAL: { |
802 // Global var, const, or let variable. | 968 // Global var, const, or let variable. |
803 // TODO(rmcilroy): If context chain depth is short enough, do this using | 969 // TODO(rmcilroy): If context chain depth is short enough, do this using |
804 // a generic version of LoadGlobalViaContextStub rather than calling the | 970 // a generic version of LoadGlobalViaContextStub rather than calling the |
805 // runtime. | 971 // runtime. |
806 DCHECK(variable->IsStaticGlobalObjectProperty()); | 972 DCHECK(variable->IsStaticGlobalObjectProperty()); |
807 builder()->LoadGlobal(variable->index()); | 973 builder()->LoadGlobal(variable->index()); |
974 result_scope()->SetResultInAccumulator(); | |
808 break; | 975 break; |
809 } | 976 } |
810 case VariableLocation::UNALLOCATED: { | 977 case VariableLocation::UNALLOCATED: { |
811 TemporaryRegisterScope temporary_register_scope(builder()); | 978 TemporaryRegisterScope temporary_register_scope(builder()); |
812 Register obj = temporary_register_scope.NewRegister(); | 979 Register obj = temporary_register_scope.NewRegister(); |
813 builder()->LoadContextSlot(execution_context()->reg(), | 980 builder()->LoadContextSlot(execution_context()->reg(), |
814 Context::GLOBAL_OBJECT_INDEX); | 981 Context::GLOBAL_OBJECT_INDEX); |
815 builder()->StoreAccumulatorInRegister(obj); | 982 builder()->StoreAccumulatorInRegister(obj); |
816 builder()->LoadLiteral(variable->name()); | 983 builder()->LoadLiteral(variable->name()); |
817 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 984 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); |
985 result_scope()->SetResultInAccumulator(); | |
818 break; | 986 break; |
819 } | 987 } |
820 case VariableLocation::CONTEXT: { | 988 case VariableLocation::CONTEXT: { |
821 ContextScope* context = execution_context()->Previous(variable->scope()); | 989 ContextScope* context = execution_context()->Previous(variable->scope()); |
822 if (context) { | 990 if (context) { |
823 builder()->LoadContextSlot(context->reg(), variable->index()); | 991 builder()->LoadContextSlot(context->reg(), variable->index()); |
824 } else { | 992 } else { |
825 UNIMPLEMENTED(); | 993 UNIMPLEMENTED(); |
826 } | 994 } |
995 result_scope()->SetResultInAccumulator(); | |
827 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and | 996 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and |
828 // let variables. | 997 // let variables. |
829 break; | 998 break; |
830 } | 999 } |
831 case VariableLocation::LOOKUP: | 1000 case VariableLocation::LOOKUP: |
832 UNIMPLEMENTED(); | 1001 UNIMPLEMENTED(); |
833 } | 1002 } |
834 } | 1003 } |
835 | 1004 |
836 | 1005 |
837 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 1006 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, |
838 FeedbackVectorSlot slot) { | 1007 FeedbackVectorSlot slot) { |
839 switch (variable->location()) { | 1008 switch (variable->location()) { |
840 case VariableLocation::LOCAL: { | 1009 case VariableLocation::LOCAL: { |
841 // TODO(rmcilroy): support const mode initialization. | 1010 // TODO(rmcilroy): support const mode initialization. |
842 Register destination(variable->index()); | 1011 Register destination(variable->index()); |
843 builder()->StoreAccumulatorInRegister(destination); | 1012 builder()->StoreAccumulatorInRegister(destination); |
1013 StoreForBinaryExpression(destination); | |
rmcilroy
2015/10/19 12:56:22
I don't like this being called StoreForBinaryExpre
oth
2015/10/20 15:28:52
RecordStoreToRegister()? It'll certainly cover par
rmcilroy
2015/10/20 16:39:20
Good point, SGTM
| |
844 break; | 1014 break; |
845 } | 1015 } |
846 case VariableLocation::PARAMETER: { | 1016 case VariableLocation::PARAMETER: { |
847 // The parameter indices are shifted by 1 (receiver is variable | 1017 // The parameter indices are shifted by 1 (receiver is variable |
848 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 1018 // index -1 but is parameter index 0 in BytecodeArrayBuilder). |
849 Register destination(builder()->Parameter(variable->index() + 1)); | 1019 Register destination(builder()->Parameter(variable->index() + 1)); |
850 builder()->StoreAccumulatorInRegister(destination); | 1020 builder()->StoreAccumulatorInRegister(destination); |
1021 StoreForBinaryExpression(destination); | |
851 break; | 1022 break; |
852 } | 1023 } |
853 case VariableLocation::GLOBAL: { | 1024 case VariableLocation::GLOBAL: { |
854 // Global var, const, or let variable. | 1025 // Global var, const, or let variable. |
855 // TODO(rmcilroy): If context chain depth is short enough, do this using | 1026 // TODO(rmcilroy): If context chain depth is short enough, do this using |
856 // a generic version of LoadGlobalViaContextStub rather than calling the | 1027 // a generic version of LoadGlobalViaContextStub rather than calling the |
857 // runtime. | 1028 // runtime. |
858 DCHECK(variable->IsStaticGlobalObjectProperty()); | 1029 DCHECK(variable->IsStaticGlobalObjectProperty()); |
859 builder()->StoreGlobal(variable->index(), language_mode()); | 1030 builder()->StoreGlobal(variable->index(), language_mode()); |
860 break; | 1031 break; |
861 } | 1032 } |
862 case VariableLocation::UNALLOCATED: { | 1033 case VariableLocation::UNALLOCATED: { |
863 TemporaryRegisterScope temporary_register_scope(builder()); | 1034 Register value = result_scope()->NewRegister(); |
864 Register value = temporary_register_scope.NewRegister(); | 1035 Register obj = result_scope()->NewRegister(); |
865 Register obj = temporary_register_scope.NewRegister(); | 1036 Register name = result_scope()->NewRegister(); |
866 Register name = temporary_register_scope.NewRegister(); | 1037 |
867 // TODO(rmcilroy): Investigate whether we can avoid having to stash the | 1038 // TODO(rmcilroy): Investigate whether we can avoid having to stash the |
868 // value in a register. | 1039 // value in a register. |
869 builder()->StoreAccumulatorInRegister(value); | 1040 builder()->StoreAccumulatorInRegister(value); |
870 builder()->LoadContextSlot(execution_context()->reg(), | 1041 builder()->LoadContextSlot(execution_context()->reg(), |
871 Context::GLOBAL_OBJECT_INDEX); | 1042 Context::GLOBAL_OBJECT_INDEX); |
872 builder()->StoreAccumulatorInRegister(obj); | 1043 builder()->StoreAccumulatorInRegister(obj); |
873 builder()->LoadLiteral(variable->name()); | 1044 builder()->LoadLiteral(variable->name()); |
874 builder()->StoreAccumulatorInRegister(name); | 1045 builder()->StoreAccumulatorInRegister(name); |
875 builder()->LoadAccumulatorWithRegister(value); | 1046 builder()->LoadAccumulatorWithRegister(value); |
876 builder()->StoreNamedProperty(obj, name, feedback_index(slot), | 1047 builder()->StoreNamedProperty(obj, name, feedback_index(slot), |
(...skipping 11 matching lines...) Expand all Loading... | |
888 break; | 1059 break; |
889 } | 1060 } |
890 case VariableLocation::LOOKUP: | 1061 case VariableLocation::LOOKUP: |
891 UNIMPLEMENTED(); | 1062 UNIMPLEMENTED(); |
892 } | 1063 } |
893 } | 1064 } |
894 | 1065 |
895 | 1066 |
896 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 1067 void BytecodeGenerator::VisitAssignment(Assignment* expr) { |
897 DCHECK(expr->target()->IsValidReferenceExpression()); | 1068 DCHECK(expr->target()->IsValidReferenceExpression()); |
898 TemporaryRegisterScope temporary_register_scope(builder()); | |
899 Register object, key; | 1069 Register object, key; |
900 | 1070 |
901 // Left-hand side can only be a property, a global or a variable slot. | 1071 // Left-hand side can only be a property, a global or a variable slot. |
902 Property* property = expr->target()->AsProperty(); | 1072 Property* property = expr->target()->AsProperty(); |
903 LhsKind assign_type = Property::GetAssignType(property); | 1073 LhsKind assign_type = Property::GetAssignType(property); |
904 | 1074 |
905 // Evaluate LHS expression. | 1075 // Evaluate LHS expression. |
906 switch (assign_type) { | 1076 switch (assign_type) { |
907 case VARIABLE: | 1077 case VARIABLE: |
908 // Nothing to do to evaluate variable assignment LHS. | 1078 // Nothing to do to evaluate variable assignment LHS. |
909 break; | 1079 break; |
910 case NAMED_PROPERTY: | 1080 case NAMED_PROPERTY: { |
911 object = temporary_register_scope.NewRegister(); | 1081 object = VisitForRegisterValue(property->obj()); |
912 key = temporary_register_scope.NewRegister(); | 1082 key = result_scope()->NewRegister(); |
913 Visit(property->obj()); | |
914 builder()->StoreAccumulatorInRegister(object); | |
915 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()); | 1083 builder()->LoadLiteral(property->key()->AsLiteral()->AsPropertyName()); |
916 builder()->StoreAccumulatorInRegister(key); | 1084 builder()->StoreAccumulatorInRegister(key); |
917 break; | 1085 break; |
918 case KEYED_PROPERTY: | 1086 } |
919 object = temporary_register_scope.NewRegister(); | 1087 case KEYED_PROPERTY: { |
920 key = temporary_register_scope.NewRegister(); | 1088 object = VisitForRegisterValue(property->obj()); |
921 Visit(property->obj()); | 1089 key = VisitForRegisterValue(property->key()); |
922 builder()->StoreAccumulatorInRegister(object); | |
923 Visit(property->key()); | |
924 builder()->StoreAccumulatorInRegister(key); | |
925 break; | 1090 break; |
1091 } | |
926 case NAMED_SUPER_PROPERTY: | 1092 case NAMED_SUPER_PROPERTY: |
927 case KEYED_SUPER_PROPERTY: | 1093 case KEYED_SUPER_PROPERTY: |
928 UNIMPLEMENTED(); | 1094 UNIMPLEMENTED(); |
929 } | 1095 } |
930 | 1096 |
931 // Evaluate the value and potentially handle compound assignments by loading | 1097 // Evaluate the value and potentially handle compound assignments by loading |
932 // the left-hand side value and performing a binary operation. | 1098 // the left-hand side value and performing a binary operation. |
933 if (expr->is_compound()) { | 1099 if (expr->is_compound()) { |
934 UNIMPLEMENTED(); | 1100 UNIMPLEMENTED(); |
935 } else { | 1101 } else { |
936 Visit(expr->value()); | 1102 VisitForAccumulatorValue(expr->value()); |
1103 result_scope()->SetResultInAccumulator(); | |
937 } | 1104 } |
938 | 1105 |
939 // Store the value. | 1106 // Store the value. |
940 FeedbackVectorSlot slot = expr->AssignmentSlot(); | 1107 FeedbackVectorSlot slot = expr->AssignmentSlot(); |
941 switch (assign_type) { | 1108 switch (assign_type) { |
942 case VARIABLE: { | 1109 case VARIABLE: { |
943 Variable* variable = expr->target()->AsVariableProxy()->var(); | 1110 Variable* variable = expr->target()->AsVariableProxy()->var(); |
944 VisitVariableAssignment(variable, slot); | 1111 VisitVariableAssignment(variable, slot); |
945 break; | 1112 break; |
946 } | 1113 } |
(...skipping 20 matching lines...) Expand all Loading... | |
967 | 1134 |
968 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { | 1135 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) { |
969 LhsKind property_kind = Property::GetAssignType(expr); | 1136 LhsKind property_kind = Property::GetAssignType(expr); |
970 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); | 1137 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot(); |
971 switch (property_kind) { | 1138 switch (property_kind) { |
972 case VARIABLE: | 1139 case VARIABLE: |
973 UNREACHABLE(); | 1140 UNREACHABLE(); |
974 case NAMED_PROPERTY: { | 1141 case NAMED_PROPERTY: { |
975 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); | 1142 builder()->LoadLiteral(expr->key()->AsLiteral()->AsPropertyName()); |
976 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 1143 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); |
1144 result_scope()->SetResultInAccumulator(); | |
977 break; | 1145 break; |
978 } | 1146 } |
979 case KEYED_PROPERTY: { | 1147 case KEYED_PROPERTY: { |
980 Visit(expr->key()); | 1148 VisitForAccumulatorValue(expr->key()); |
981 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); | 1149 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode()); |
1150 result_scope()->SetResultInAccumulator(); | |
982 break; | 1151 break; |
983 } | 1152 } |
984 case NAMED_SUPER_PROPERTY: | 1153 case NAMED_SUPER_PROPERTY: |
985 case KEYED_SUPER_PROPERTY: | 1154 case KEYED_SUPER_PROPERTY: |
986 UNIMPLEMENTED(); | 1155 UNIMPLEMENTED(); |
987 } | 1156 } |
988 } | 1157 } |
989 | 1158 |
990 | 1159 |
991 void BytecodeGenerator::VisitProperty(Property* expr) { | 1160 void BytecodeGenerator::VisitProperty(Property* expr) { |
992 TemporaryRegisterScope temporary_register_scope(builder()); | 1161 Register obj = VisitForRegisterValue(expr->obj()); |
993 Register obj = temporary_register_scope.NewRegister(); | |
994 Visit(expr->obj()); | |
995 builder()->StoreAccumulatorInRegister(obj); | |
996 VisitPropertyLoad(obj, expr); | 1162 VisitPropertyLoad(obj, expr); |
997 } | 1163 } |
998 | 1164 |
999 | 1165 |
1000 Register BytecodeGenerator::VisitArguments( | 1166 Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) { |
1001 ZoneList<Expression*>* args, TemporaryRegisterScope* register_scope) { | |
1002 // Visit arguments and place in a contiguous block of temporary registers. | 1167 // Visit arguments and place in a contiguous block of temporary registers. |
1003 // Return the first temporary register corresponding to the first argument. | 1168 // Return the first temporary register corresponding to the first argument. |
1004 DCHECK_GT(args->length(), 0); | 1169 DCHECK_GT(args->length(), 0); |
1005 Register first_arg = register_scope->NewRegister(); | 1170 Register first_arg = result_scope()->NewRegister(); |
1006 Visit(args->at(0)); | 1171 VisitForAccumulatorValue(args->at(0)); |
1007 builder()->StoreAccumulatorInRegister(first_arg); | 1172 builder()->StoreAccumulatorInRegister(first_arg); |
1008 for (int i = 1; i < static_cast<int>(args->length()); i++) { | 1173 for (int i = 1; i < static_cast<int>(args->length()); i++) { |
1009 Register ith_arg = register_scope->NewRegister(); | 1174 Register ith_arg = result_scope()->NewRegister(); |
1010 Visit(args->at(i)); | 1175 VisitForAccumulatorValue(args->at(i)); |
1011 builder()->StoreAccumulatorInRegister(ith_arg); | 1176 builder()->StoreAccumulatorInRegister(ith_arg); |
1012 DCHECK(ith_arg.index() - i == first_arg.index()); | 1177 DCHECK(ith_arg.index() - i == first_arg.index()); |
1013 } | 1178 } |
1014 | 1179 |
1015 return first_arg; | 1180 return first_arg; |
1016 } | 1181 } |
1017 | 1182 |
1018 | 1183 |
1019 void BytecodeGenerator::VisitCall(Call* expr) { | 1184 void BytecodeGenerator::VisitCall(Call* expr) { |
1185 static int hits = 0; | |
1186 hits++; | |
rmcilroy
2015/10/19 12:56:23
leftover debugging code?
oth
2015/10/20 15:28:53
Done.
| |
1020 Expression* callee_expr = expr->expression(); | 1187 Expression* callee_expr = expr->expression(); |
1021 Call::CallType call_type = expr->GetCallType(isolate()); | 1188 Call::CallType call_type = expr->GetCallType(isolate()); |
1022 | 1189 |
1023 // Prepare the callee and the receiver to the function call. This depends on | 1190 // Prepare the callee and the receiver to the function call. This depends on |
1024 // the semantics of the underlying call type. | 1191 // the semantics of the underlying call type. |
1025 TemporaryRegisterScope temporary_register_scope(builder()); | 1192 Register callee = result_scope()->NewRegister(); |
1026 Register callee = temporary_register_scope.NewRegister(); | 1193 |
1027 Register receiver = temporary_register_scope.NewRegister(); | 1194 // The receiver and arguments need to be allocated consecutively for |
1195 // Call(). Future optimizations could avoid this there are no | |
1196 // arguments or the receiver and arguments are already consecutive. | |
1197 ZoneList<Expression*>* args = expr->arguments(); | |
1198 result_scope()->PrepareForConsecutiveAllocations(args->length() + 1); | |
1199 Register receiver = result_scope()->NewRegister(); | |
1028 | 1200 |
1029 switch (call_type) { | 1201 switch (call_type) { |
1030 case Call::PROPERTY_CALL: { | 1202 case Call::PROPERTY_CALL: { |
1031 Property* property = callee_expr->AsProperty(); | 1203 Property* property = callee_expr->AsProperty(); |
1032 if (property->IsSuperAccess()) { | 1204 if (property->IsSuperAccess()) { |
1033 UNIMPLEMENTED(); | 1205 UNIMPLEMENTED(); |
1034 } | 1206 } |
1035 Visit(property->obj()); | 1207 VisitForAccumulatorValue(property->obj()); |
1036 builder()->StoreAccumulatorInRegister(receiver); | 1208 builder()->StoreAccumulatorInRegister(receiver); |
1209 // Need a result scope here to keep our consecutive | |
1210 // temporaries. | |
1211 AccumulatorResultScope accumulator_result_scope(this); | |
1037 // Perform a property load of the callee. | 1212 // Perform a property load of the callee. |
1038 VisitPropertyLoad(receiver, property); | 1213 VisitPropertyLoad(receiver, property); |
1039 builder()->StoreAccumulatorInRegister(callee); | 1214 builder()->StoreAccumulatorInRegister(callee); |
1040 break; | 1215 break; |
1041 } | 1216 } |
1042 case Call::GLOBAL_CALL: { | 1217 case Call::GLOBAL_CALL: { |
1043 // Receiver is undefined for global calls. | 1218 // Receiver is undefined for global calls. |
1044 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 1219 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
1045 // Load callee as a global variable. | 1220 // Load callee as a global variable. |
1046 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 1221 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
1047 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 1222 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); |
1048 builder()->StoreAccumulatorInRegister(callee); | 1223 builder()->StoreAccumulatorInRegister(callee); |
1049 break; | 1224 break; |
1050 } | 1225 } |
1051 case Call::OTHER_CALL: { | 1226 case Call::OTHER_CALL: { |
1052 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | 1227 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); |
1053 Visit(callee_expr); | 1228 VisitForAccumulatorValue(callee_expr); |
1054 builder()->StoreAccumulatorInRegister(callee); | 1229 builder()->StoreAccumulatorInRegister(callee); |
1055 break; | 1230 break; |
1056 } | 1231 } |
1057 case Call::LOOKUP_SLOT_CALL: | 1232 case Call::LOOKUP_SLOT_CALL: |
1058 case Call::SUPER_CALL: | 1233 case Call::SUPER_CALL: |
1059 case Call::POSSIBLY_EVAL_CALL: | 1234 case Call::POSSIBLY_EVAL_CALL: |
1060 UNIMPLEMENTED(); | 1235 UNIMPLEMENTED(); |
1061 } | 1236 } |
1062 | 1237 |
1063 // Evaluate all arguments to the function call and store in sequential | 1238 // Evaluate all arguments to the function call and store in sequential |
1064 // registers. | 1239 // registers. |
1065 ZoneList<Expression*>* args = expr->arguments(); | 1240 result_scope()->PrepareForConsecutiveAllocations(args->length()); |
rmcilroy
2015/10/19 12:56:22
nit - could we move PrepareForConsecutiveAllocatio
oth
2015/10/20 15:28:52
Done.
oth
2015/10/20 15:28:52
Done.
| |
1066 if (args->length() > 0) { | 1241 for (int i = 0; i < args->length(); ++i) { |
1067 Register first_arg = VisitArguments(args, &temporary_register_scope); | 1242 VisitForAccumulatorValue(args->at(i)); |
1068 CHECK_EQ(first_arg.index(), receiver.index() + 1); | 1243 Register arg = result_scope()->NewRegister(); |
1244 DCHECK(arg.index() - i == receiver.index() + 1); | |
rmcilroy
2015/10/19 12:56:22
nit - move Register arg and DCHECK lines above Vis
oth
2015/10/20 15:28:52
Done.
| |
1245 builder()->StoreAccumulatorInRegister(arg); | |
1069 } | 1246 } |
1070 | 1247 |
1071 // TODO(rmcilroy): Deal with possible direct eval here? | 1248 // TODO(rmcilroy): Deal with possible direct eval here? |
1072 // TODO(rmcilroy): Use CallIC to allow call type feedback. | 1249 // TODO(rmcilroy): Use CallIC to allow call type feedback. |
1073 builder()->Call(callee, receiver, args->length()); | 1250 builder()->Call(callee, receiver, args->length()); |
1251 result_scope()->SetResultInAccumulator(); | |
1074 } | 1252 } |
1075 | 1253 |
1076 | 1254 |
1077 void BytecodeGenerator::VisitCallNew(CallNew* expr) { | 1255 void BytecodeGenerator::VisitCallNew(CallNew* expr) { |
1078 TemporaryRegisterScope temporary_register_scope(builder()); | 1256 Register constructor = result_scope()->NewRegister(); |
1079 Register constructor = temporary_register_scope.NewRegister(); | 1257 VisitForAccumulatorValue(expr->expression()); |
1080 Visit(expr->expression()); | |
1081 builder()->StoreAccumulatorInRegister(constructor); | 1258 builder()->StoreAccumulatorInRegister(constructor); |
1259 | |
1082 ZoneList<Expression*>* args = expr->arguments(); | 1260 ZoneList<Expression*>* args = expr->arguments(); |
1083 if (args->length() > 0) { | 1261 if (args->length() > 0) { |
1084 Register first_arg = VisitArguments(args, &temporary_register_scope); | 1262 result_scope()->PrepareForConsecutiveAllocations(args->length()); |
1263 Register first_arg = VisitArguments(args); | |
1085 builder()->New(constructor, first_arg, args->length()); | 1264 builder()->New(constructor, first_arg, args->length()); |
1086 } else { | 1265 } else { |
1087 // The second argument here will be ignored as there are zero | 1266 // The second argument here will be ignored as there are zero |
1088 // arguments. Using the constructor register avoids avoid | 1267 // arguments. Using the constructor register avoids avoid |
1089 // allocating a temporary just to fill the operands. | 1268 // allocating a temporary just to fill the operands. |
1090 builder()->New(constructor, constructor, 0); | 1269 builder()->New(constructor, constructor, 0); |
1091 } | 1270 } |
1271 | |
1272 result_scope()->SetResultInAccumulator(); | |
1092 } | 1273 } |
1093 | 1274 |
1094 | 1275 |
1095 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { | 1276 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { |
1096 if (expr->is_jsruntime()) { | 1277 if (expr->is_jsruntime()) { |
1097 UNIMPLEMENTED(); | 1278 UNIMPLEMENTED(); |
1098 } | 1279 } |
1099 | 1280 |
1100 // Evaluate all arguments to the runtime call. | 1281 // Evaluate all arguments to the runtime call. |
1101 TemporaryRegisterScope temporary_register_scope(&builder_); | |
1102 | |
1103 // TODO(rmcilroy): support multiple return values. | |
1104 DCHECK_LE(expr->function()->result_size, 1); | 1282 DCHECK_LE(expr->function()->result_size, 1); |
1105 Runtime::FunctionId function_id = expr->function()->function_id; | 1283 Runtime::FunctionId function_id = expr->function()->function_id; |
1106 ZoneList<Expression*>* args = expr->arguments(); | 1284 ZoneList<Expression*>* args = expr->arguments(); |
1285 result_scope()->PrepareForConsecutiveAllocations(args->length()); | |
1107 Register first_arg; | 1286 Register first_arg; |
1108 if (args->length() > 0) { | 1287 if (args->length() > 0) { |
1109 first_arg = VisitArguments(args, &temporary_register_scope); | 1288 first_arg = VisitArguments(args); |
1110 } else { | 1289 } else { |
1111 // Allocation here is just to fullfil the requirement that there | 1290 // Allocation here is just to fullfil the requirement that there |
1112 // is a register operand for the start of the arguments though | 1291 // is a register operand for the start of the arguments though |
1113 // there are zero when this is generated. | 1292 // there are zero when this is generated. |
1114 first_arg = temporary_register_scope.NewRegister(); | 1293 first_arg = result_scope()->NewRegister(); |
1115 } | 1294 } |
1116 builder()->CallRuntime(function_id, first_arg, args->length()); | 1295 builder()->CallRuntime(function_id, first_arg, args->length()); |
1296 // TODO(rmcilroy): support multiple return values. | |
rmcilroy
2015/10/19 12:56:22
nit - move TODO back up to DCHECK_LE (that is what
oth
2015/10/20 15:28:52
Done.
| |
1297 result_scope()->SetResultInAccumulator(); | |
1117 } | 1298 } |
1118 | 1299 |
1119 | 1300 |
1120 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { | 1301 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { |
1121 Visit(expr->expression()); | 1302 VisitForEffect(expr->expression()); |
1122 builder()->LoadUndefined(); | 1303 builder()->LoadUndefined(); |
1304 result_scope()->SetResultInAccumulator(); | |
1123 } | 1305 } |
1124 | 1306 |
1125 | 1307 |
1126 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { | 1308 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) { |
1127 Visit(expr->expression()); | 1309 VisitForAccumulatorValue(expr->expression()); |
1128 builder()->TypeOf(); | 1310 builder()->TypeOf(); |
1311 result_scope()->SetResultInAccumulator(); | |
1129 } | 1312 } |
1130 | 1313 |
1131 | 1314 |
1132 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { | 1315 void BytecodeGenerator::VisitNot(UnaryOperation* expr) { |
1133 Visit(expr->expression()); | 1316 VisitForAccumulatorValue(expr->expression()); |
1134 builder()->LogicalNot(); | 1317 builder()->LogicalNot(); |
1318 result_scope()->SetResultInAccumulator(); | |
1135 } | 1319 } |
1136 | 1320 |
1137 | 1321 |
1138 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { | 1322 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { |
1139 switch (expr->op()) { | 1323 switch (expr->op()) { |
1140 case Token::Value::NOT: | 1324 case Token::Value::NOT: |
1141 VisitNot(expr); | 1325 VisitNot(expr); |
1142 break; | 1326 break; |
1143 case Token::Value::TYPEOF: | 1327 case Token::Value::TYPEOF: |
1144 VisitTypeOf(expr); | 1328 VisitTypeOf(expr); |
(...skipping 27 matching lines...) Expand all Loading... | |
1172 VisitLogicalAndExpression(binop); | 1356 VisitLogicalAndExpression(binop); |
1173 break; | 1357 break; |
1174 default: | 1358 default: |
1175 VisitArithmeticExpression(binop); | 1359 VisitArithmeticExpression(binop); |
1176 break; | 1360 break; |
1177 } | 1361 } |
1178 } | 1362 } |
1179 | 1363 |
1180 | 1364 |
1181 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 1365 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
1182 Token::Value op = expr->op(); | 1366 // This is a potentially two pass operation if the first pass |
1183 Expression* left = expr->left(); | 1367 // detects loads-and-stores to locals and params used in the |
1184 Expression* right = expr->right(); | 1368 // expression. This is hopefully rare. |
1185 | 1369 PrepareForBinaryExpression(); |
rmcilroy
2015/10/19 12:56:22
As mentioned, this should probably be a scope allo
oth
2015/10/20 15:28:52
Done.
| |
1186 TemporaryRegisterScope temporary_register_scope(builder()); | 1370 Register lhs = VisitForRegisterValue(expr->left()); |
1187 Register temporary = temporary_register_scope.NewRegister(); | 1371 if (builder()->RegisterIsParameterOrLocal(lhs)) { |
1188 | 1372 // Result was returned in an existing local or parameter. See if |
1189 Visit(left); | 1373 // it needs to be moved to a temporary. |
1190 builder()->StoreAccumulatorInRegister(temporary); | 1374 lhs = LoadForBinaryExpression(lhs); |
1191 Visit(right); | 1375 } |
1192 builder()->CompareOperation(op, temporary, language_mode_strength()); | 1376 VisitForAccumulatorValue(expr->right()); |
1377 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); | |
1378 result_scope()->SetResultInAccumulator(); | |
1379 CompleteBinaryExpression(); | |
1193 } | 1380 } |
1194 | 1381 |
1195 | 1382 |
1196 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } | 1383 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } |
1197 | 1384 |
1198 | 1385 |
1199 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { | 1386 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { |
1200 UNREACHABLE(); | 1387 UNREACHABLE(); |
1201 } | 1388 } |
1202 | 1389 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1274 builder() | 1461 builder() |
1275 ->LoadLiteral(scope->GetScopeInfo(isolate())) | 1462 ->LoadLiteral(scope->GetScopeInfo(isolate())) |
1276 .StoreAccumulatorInRegister(scope_info); | 1463 .StoreAccumulatorInRegister(scope_info); |
1277 VisitFunctionClosureForContext(); | 1464 VisitFunctionClosureForContext(); |
1278 builder() | 1465 builder() |
1279 ->StoreAccumulatorInRegister(closure) | 1466 ->StoreAccumulatorInRegister(closure) |
1280 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2); | 1467 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2); |
1281 } | 1468 } |
1282 | 1469 |
1283 | 1470 |
1284 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { | 1471 void BytecodeGenerator::PrepareForBinaryExpression() { |
1285 Token::Value op = binop->op(); | 1472 if (binary_expression_depth_++ == 0) { |
1286 Expression* left = binop->left(); | 1473 binary_expression_hazard_set_.clear(); |
1287 Expression* right = binop->right(); | 1474 } |
1288 | |
1289 TemporaryRegisterScope temporary_register_scope(builder()); | |
1290 Register temporary = temporary_register_scope.NewRegister(); | |
1291 | |
1292 Visit(left); | |
1293 builder()->StoreAccumulatorInRegister(temporary); | |
1294 Visit(right); | |
1295 builder()->BinaryOperation(op, temporary, language_mode_strength()); | |
1296 } | 1475 } |
1297 | 1476 |
1298 | 1477 |
1478 Register BytecodeGenerator::LoadForBinaryExpression(Register reg) { | |
rmcilroy
2015/10/19 12:56:22
I think this should be done in VisitVariableLoad a
oth
2015/10/20 15:28:53
The method has been renamed and there's a TODO to
| |
1479 // TODO(oth): Follow on CL to load from re-map here. | |
1480 DCHECK(builder()->RegisterIsParameterOrLocal(reg)); | |
1481 if (binary_expression_depth_ > 0) { | |
1482 binary_expression_hazard_set_.insert(reg.index()); | |
1483 } | |
1484 return reg; | |
1485 } | |
1486 | |
1487 | |
1488 void BytecodeGenerator::StoreForBinaryExpression(Register reg) { | |
1489 DCHECK(builder()->RegisterIsParameterOrLocal(reg)); | |
1490 if (binary_expression_depth_ > 0) { | |
1491 // TODO(oth): a store to a register that's be loaded needs to be | |
1492 // remapped. | |
1493 DCHECK(binary_expression_hazard_set_.find(reg.index()) == | |
1494 binary_expression_hazard_set_.end()); | |
1495 } | |
1496 } | |
1497 | |
1498 | |
1499 void BytecodeGenerator::CompleteBinaryExpression() { | |
1500 DCHECK(binary_expression_depth_ > 0); | |
1501 binary_expression_depth_ -= 1; | |
1502 // TODO(oth): spill remapped registers into origins. | |
1503 } | |
1504 | |
1505 | |
1506 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { | |
1507 // This is a potentially two pass operation if the first pass | |
1508 // detects loads-and-stores to locals and params used in the | |
1509 // expression. This is hopefully rare. | |
rmcilroy
2015/10/19 12:56:22
Comment is out-of-date. Alsoc could we move this b
oth
2015/10/20 15:28:52
Done.
| |
1510 PrepareForBinaryExpression(); | |
1511 Register lhs = VisitForRegisterValue(expr->left()); | |
1512 if (builder()->RegisterIsParameterOrLocal(lhs)) { | |
1513 // Result was returned in an existing local or parameter. See if | |
1514 // it needs to be moved to a temporary. | |
1515 lhs = LoadForBinaryExpression(lhs); | |
1516 } | |
1517 VisitForAccumulatorValue(expr->right()); | |
1518 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength()); | |
1519 result_scope()->SetResultInAccumulator(); | |
1520 CompleteBinaryExpression(); | |
1521 } | |
1522 | |
1523 | |
1524 // Visits the expression |expr| and places the result in the accumulator. | |
1525 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { | |
1526 AccumulatorResultScope accumulator_scope(this); | |
1527 Visit(expr); | |
1528 } | |
1529 | |
1530 | |
1531 // Visits the expression |expr| and discards the result. | |
1532 void BytecodeGenerator::VisitForEffect(Expression* expr) { | |
1533 EffectResultScope effect_scope(this); | |
1534 Visit(expr); | |
1535 } | |
1536 | |
1537 | |
1538 // Visits the expression |expr| and places the result in |temporary_register| | |
1539 // if the result is not already a register value. The return value is | |
1540 // the register containing the result. The caller should check whether | |
1541 // this is the temporary register and consider releasing the temporary | |
1542 // register if not. | |
1543 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { | |
1544 RegisterResultScope register_scope(this); | |
1545 Visit(expr); | |
1546 return register_scope.ResultRegister(); | |
1547 } | |
1548 | |
1549 | |
1299 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { | 1550 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { |
1300 Expression* left = binop->left(); | 1551 Expression* left = binop->left(); |
1301 Expression* right = binop->right(); | 1552 Expression* right = binop->right(); |
1302 | 1553 |
1303 Visit(left); | 1554 VisitForAccumulatorValue(left); |
rmcilroy
2015/10/19 12:56:22
this can be VisitForEffect
oth
2015/10/20 15:28:53
Yes, and interestingly the RHS visitor should just
rmcilroy
2015/10/20 16:39:20
Nice catch :).
| |
1304 Visit(right); | 1555 VisitForAccumulatorValue(right); |
1556 result_scope()->SetResultInAccumulator(); | |
1305 } | 1557 } |
1306 | 1558 |
1307 | 1559 |
1308 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { | 1560 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { |
1309 Expression* left = binop->left(); | 1561 Expression* left = binop->left(); |
1310 Expression* right = binop->right(); | 1562 Expression* right = binop->right(); |
1311 | 1563 |
1312 // Short-circuit evaluation- If it is known that left is always true, | 1564 // Short-circuit evaluation- If it is known that left is always true, |
1313 // no need to visit right | 1565 // no need to visit right |
1314 if (left->ToBooleanIsTrue()) { | 1566 if (left->ToBooleanIsTrue()) { |
1315 Visit(left); | 1567 VisitForAccumulatorValue(left); |
1316 } else { | 1568 } else { |
1317 BytecodeLabel end_label; | 1569 BytecodeLabel end_label; |
1318 | 1570 VisitForAccumulatorValue(left); |
1319 Visit(left); | |
1320 builder()->JumpIfToBooleanTrue(&end_label); | 1571 builder()->JumpIfToBooleanTrue(&end_label); |
1321 Visit(right); | 1572 VisitForAccumulatorValue(right); |
1322 builder()->Bind(&end_label); | 1573 builder()->Bind(&end_label); |
1323 } | 1574 } |
1575 result_scope()->SetResultInAccumulator(); | |
1324 } | 1576 } |
1325 | 1577 |
1326 | 1578 |
1327 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { | 1579 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) { |
1328 Expression* left = binop->left(); | 1580 Expression* left = binop->left(); |
1329 Expression* right = binop->right(); | 1581 Expression* right = binop->right(); |
1330 | 1582 |
1331 // Short-circuit evaluation- If it is known that left is always false, | 1583 // Short-circuit evaluation- If it is known that left is always false, |
1332 // no need to visit right | 1584 // no need to visit right |
1333 if (left->ToBooleanIsFalse()) { | 1585 if (left->ToBooleanIsFalse()) { |
1334 Visit(left); | 1586 VisitForAccumulatorValue(left); |
1335 } else { | 1587 } else { |
1336 BytecodeLabel end_label; | 1588 BytecodeLabel end_label; |
1337 | 1589 VisitForAccumulatorValue(left); |
1338 Visit(left); | |
1339 builder()->JumpIfToBooleanFalse(&end_label); | 1590 builder()->JumpIfToBooleanFalse(&end_label); |
1340 Visit(right); | 1591 VisitForAccumulatorValue(right); |
1341 builder()->Bind(&end_label); | 1592 builder()->Bind(&end_label); |
1342 } | 1593 } |
1594 result_scope()->SetResultInAccumulator(); | |
1343 } | 1595 } |
1344 | 1596 |
1345 | 1597 |
1346 void BytecodeGenerator::VisitObjectLiteralAccessor( | 1598 void BytecodeGenerator::VisitObjectLiteralAccessor( |
1347 Register home_object, ObjectLiteralProperty* property, Register value_out) { | 1599 Register home_object, ObjectLiteralProperty* property, Register value_out) { |
1348 // TODO(rmcilroy): Replace value_out with VisitForRegister(); | 1600 // TODO(rmcilroy): Replace value_out with VisitForRegister(); |
1349 if (property == nullptr) { | 1601 if (property == nullptr) { |
1350 builder()->LoadNull().StoreAccumulatorInRegister(value_out); | 1602 builder()->LoadNull().StoreAccumulatorInRegister(value_out); |
1351 } else { | 1603 } else { |
1352 Visit(property->value()); | 1604 VisitForAccumulatorValue(property->value()); |
1353 builder()->StoreAccumulatorInRegister(value_out); | 1605 builder()->StoreAccumulatorInRegister(value_out); |
1354 VisitSetHomeObject(value_out, home_object, property); | 1606 VisitSetHomeObject(value_out, home_object, property); |
1355 } | 1607 } |
1356 } | 1608 } |
1357 | 1609 |
1358 | 1610 |
1359 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, | 1611 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, |
1360 ObjectLiteralProperty* property, | 1612 ObjectLiteralProperty* property, |
1361 int slot_number) { | 1613 int slot_number) { |
1362 Expression* expr = property->value(); | 1614 Expression* expr = property->value(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1421 } | 1673 } |
1422 | 1674 |
1423 | 1675 |
1424 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 1676 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
1425 return info()->feedback_vector()->GetIndex(slot); | 1677 return info()->feedback_vector()->GetIndex(slot); |
1426 } | 1678 } |
1427 | 1679 |
1428 } // namespace interpreter | 1680 } // namespace interpreter |
1429 } // namespace internal | 1681 } // namespace internal |
1430 } // namespace v8 | 1682 } // namespace v8 |
OLD | NEW |