blob: 650234a58447d506cd28659f0a9c4c49bd38a332 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
3// found in the LICENSE file.
4
5#include "src/interpreter/bytecode-generator.h"
6
7#include "src/ast/scopes.h"
Ben Murdochc5610432016-08-08 18:44:38 +01008#include "src/code-stubs.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/compiler.h"
10#include "src/interpreter/bytecode-register-allocator.h"
11#include "src/interpreter/control-flow-builders.h"
12#include "src/objects.h"
13#include "src/parsing/parser.h"
14#include "src/parsing/token.h"
15
16namespace v8 {
17namespace internal {
18namespace interpreter {
19
20
21// Scoped class tracking context objects created by the visitor. Represents
22// mutations of the context chain within the function body, allowing pushing and
23// popping of the current {context_register} during visitation.
24class BytecodeGenerator::ContextScope BASE_EMBEDDED {
25 public:
26 ContextScope(BytecodeGenerator* generator, Scope* scope,
27 bool should_pop_context = true)
28 : generator_(generator),
29 scope_(scope),
30 outer_(generator_->execution_context()),
Ben Murdoch097c5b22016-05-18 11:27:45 +010031 register_(Register::current_context()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 depth_(0),
33 should_pop_context_(should_pop_context) {
34 if (outer_) {
35 depth_ = outer_->depth_ + 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +010036
37 // Push the outer context into a new context register.
38 Register outer_context_reg(builder()->first_context_register().index() +
39 outer_->depth_);
40 outer_->set_register(outer_context_reg);
41 generator_->builder()->PushContext(outer_context_reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042 }
43 generator_->set_execution_context(this);
44 }
45
46 ~ContextScope() {
47 if (outer_ && should_pop_context_) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010048 DCHECK_EQ(register_.index(), Register::current_context().index());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 generator_->builder()->PopContext(outer_->reg());
Ben Murdoch097c5b22016-05-18 11:27:45 +010050 outer_->set_register(register_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000051 }
52 generator_->set_execution_context(outer_);
53 }
54
55 // Returns the depth of the given |scope| for the current execution context.
56 int ContextChainDepth(Scope* scope) {
57 return scope_->ContextChainLength(scope);
58 }
59
60 // Returns the execution context at |depth| in the current context chain if it
61 // is a function local execution context, otherwise returns nullptr.
62 ContextScope* Previous(int depth) {
63 if (depth > depth_) {
64 return nullptr;
65 }
66
67 ContextScope* previous = this;
68 for (int i = depth; i > 0; --i) {
69 previous = previous->outer_;
70 }
71 return previous;
72 }
73
74 Scope* scope() const { return scope_; }
75 Register reg() const { return register_; }
Ben Murdochda12d292016-06-02 14:46:10 +010076 bool ShouldPopContext() { return should_pop_context_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077
78 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +010079 const BytecodeArrayBuilder* builder() const { return generator_->builder(); }
80
81 void set_register(Register reg) { register_ = reg; }
82
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 BytecodeGenerator* generator_;
84 Scope* scope_;
85 ContextScope* outer_;
86 Register register_;
87 int depth_;
88 bool should_pop_context_;
89};
90
91
92// Scoped class for tracking control statements entered by the
93// visitor. The pattern derives AstGraphBuilder::ControlScope.
94class BytecodeGenerator::ControlScope BASE_EMBEDDED {
95 public:
96 explicit ControlScope(BytecodeGenerator* generator)
Ben Murdoch097c5b22016-05-18 11:27:45 +010097 : generator_(generator), outer_(generator->execution_control()),
98 context_(generator->execution_context()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 generator_->set_execution_control(this);
100 }
101 virtual ~ControlScope() { generator_->set_execution_control(outer()); }
102
103 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); }
104 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100105 void ReturnAccumulator() { PerformCommand(CMD_RETURN, nullptr); }
106 void ReThrowAccumulator() { PerformCommand(CMD_RETHROW, nullptr); }
107
108 class DeferredCommands;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109
110 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100111 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_RETHROW };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 void PerformCommand(Command command, Statement* statement);
113 virtual bool Execute(Command command, Statement* statement) = 0;
114
115 BytecodeGenerator* generator() const { return generator_; }
116 ControlScope* outer() const { return outer_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100117 ContextScope* context() const { return context_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118
119 private:
120 BytecodeGenerator* generator_;
121 ControlScope* outer_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100122 ContextScope* context_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123
124 DISALLOW_COPY_AND_ASSIGN(ControlScope);
125};
126
127
Ben Murdoch097c5b22016-05-18 11:27:45 +0100128// Helper class for a try-finally control scope. It can record intercepted
129// control-flow commands that cause entry into a finally-block, and re-apply
130// them after again leaving that block. Special tokens are used to identify
131// paths going through the finally-block to dispatch after leaving the block.
132class BytecodeGenerator::ControlScope::DeferredCommands final {
133 public:
134 DeferredCommands(BytecodeGenerator* generator, Register token_register,
135 Register result_register)
136 : generator_(generator),
137 deferred_(generator->zone()),
138 token_register_(token_register),
139 result_register_(result_register) {}
140
141 // One recorded control-flow command.
142 struct Entry {
143 Command command; // The command type being applied on this path.
144 Statement* statement; // The target statement for the command or {nullptr}.
145 int token; // A token identifying this particular path.
146 };
147
148 // Records a control-flow command while entering the finally-block. This also
149 // generates a new dispatch token that identifies one particular path. This
150 // expects the result to be in the accumulator.
151 void RecordCommand(Command command, Statement* statement) {
152 int token = static_cast<int>(deferred_.size());
153 deferred_.push_back({command, statement, token});
154
155 builder()->StoreAccumulatorInRegister(result_register_);
156 builder()->LoadLiteral(Smi::FromInt(token));
157 builder()->StoreAccumulatorInRegister(token_register_);
158 }
159
160 // Records the dispatch token to be used to identify the re-throw path when
161 // the finally-block has been entered through the exception handler. This
162 // expects the exception to be in the accumulator.
163 void RecordHandlerReThrowPath() {
164 // The accumulator contains the exception object.
165 RecordCommand(CMD_RETHROW, nullptr);
166 }
167
168 // Records the dispatch token to be used to identify the implicit fall-through
169 // path at the end of a try-block into the corresponding finally-block.
170 void RecordFallThroughPath() {
171 builder()->LoadLiteral(Smi::FromInt(-1));
172 builder()->StoreAccumulatorInRegister(token_register_);
173 }
174
175 // Applies all recorded control-flow commands after the finally-block again.
176 // This generates a dynamic dispatch on the token from the entry point.
177 void ApplyDeferredCommands() {
178 // The fall-through path is covered by the default case, hence +1 here.
179 SwitchBuilder dispatch(builder(), static_cast<int>(deferred_.size() + 1));
180 for (size_t i = 0; i < deferred_.size(); ++i) {
181 Entry& entry = deferred_[i];
182 builder()->LoadLiteral(Smi::FromInt(entry.token));
183 builder()->CompareOperation(Token::EQ_STRICT, token_register_);
184 dispatch.Case(static_cast<int>(i));
185 }
186 dispatch.DefaultAt(static_cast<int>(deferred_.size()));
187 for (size_t i = 0; i < deferred_.size(); ++i) {
188 Entry& entry = deferred_[i];
189 dispatch.SetCaseTarget(static_cast<int>(i));
190 builder()->LoadAccumulatorWithRegister(result_register_);
191 execution_control()->PerformCommand(entry.command, entry.statement);
192 }
193 dispatch.SetCaseTarget(static_cast<int>(deferred_.size()));
194 }
195
196 BytecodeArrayBuilder* builder() { return generator_->builder(); }
197 ControlScope* execution_control() { return generator_->execution_control(); }
198
199 private:
200 BytecodeGenerator* generator_;
201 ZoneVector<Entry> deferred_;
202 Register token_register_;
203 Register result_register_;
204};
205
206
207// Scoped class for dealing with control flow reaching the function level.
208class BytecodeGenerator::ControlScopeForTopLevel final
209 : public BytecodeGenerator::ControlScope {
210 public:
211 explicit ControlScopeForTopLevel(BytecodeGenerator* generator)
212 : ControlScope(generator) {}
213
214 protected:
215 bool Execute(Command command, Statement* statement) override {
216 switch (command) {
Ben Murdochda12d292016-06-02 14:46:10 +0100217 case CMD_BREAK: // We should never see break/continue in top-level.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100218 case CMD_CONTINUE:
Ben Murdochda12d292016-06-02 14:46:10 +0100219 UNREACHABLE();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100220 case CMD_RETURN:
221 generator()->builder()->Return();
222 return true;
223 case CMD_RETHROW:
224 generator()->builder()->ReThrow();
225 return true;
226 }
227 return false;
228 }
229};
230
231
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232// Scoped class for enabling break inside blocks and switch blocks.
233class BytecodeGenerator::ControlScopeForBreakable final
234 : public BytecodeGenerator::ControlScope {
235 public:
236 ControlScopeForBreakable(BytecodeGenerator* generator,
237 BreakableStatement* statement,
238 BreakableControlFlowBuilder* control_builder)
239 : ControlScope(generator),
240 statement_(statement),
241 control_builder_(control_builder) {}
242
243 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100244 bool Execute(Command command, Statement* statement) override {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000245 if (statement != statement_) return false;
246 switch (command) {
247 case CMD_BREAK:
248 control_builder_->Break();
249 return true;
250 case CMD_CONTINUE:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100251 case CMD_RETURN:
252 case CMD_RETHROW:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253 break;
254 }
255 return false;
256 }
257
258 private:
259 Statement* statement_;
260 BreakableControlFlowBuilder* control_builder_;
261};
262
263
264// Scoped class for enabling 'break' and 'continue' in iteration
265// constructs, e.g. do...while, while..., for...
266class BytecodeGenerator::ControlScopeForIteration final
267 : public BytecodeGenerator::ControlScope {
268 public:
269 ControlScopeForIteration(BytecodeGenerator* generator,
270 IterationStatement* statement,
271 LoopBuilder* loop_builder)
272 : ControlScope(generator),
273 statement_(statement),
274 loop_builder_(loop_builder) {}
275
276 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100277 bool Execute(Command command, Statement* statement) override {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 if (statement != statement_) return false;
279 switch (command) {
280 case CMD_BREAK:
281 loop_builder_->Break();
282 return true;
283 case CMD_CONTINUE:
284 loop_builder_->Continue();
285 return true;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100286 case CMD_RETURN:
287 case CMD_RETHROW:
288 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 }
290 return false;
291 }
292
293 private:
294 Statement* statement_;
295 LoopBuilder* loop_builder_;
296};
297
298
Ben Murdoch097c5b22016-05-18 11:27:45 +0100299// Scoped class for enabling 'throw' in try-catch constructs.
300class BytecodeGenerator::ControlScopeForTryCatch final
301 : public BytecodeGenerator::ControlScope {
302 public:
303 ControlScopeForTryCatch(BytecodeGenerator* generator,
304 TryCatchBuilder* try_catch_builder)
305 : ControlScope(generator) {
306 generator->try_catch_nesting_level_++;
307 }
308 virtual ~ControlScopeForTryCatch() {
309 generator()->try_catch_nesting_level_--;
310 }
311
312 protected:
313 bool Execute(Command command, Statement* statement) override {
314 switch (command) {
315 case CMD_BREAK:
316 case CMD_CONTINUE:
317 case CMD_RETURN:
318 break;
319 case CMD_RETHROW:
320 generator()->builder()->ReThrow();
321 return true;
322 }
323 return false;
324 }
325};
326
327
328// Scoped class for enabling control flow through try-finally constructs.
329class BytecodeGenerator::ControlScopeForTryFinally final
330 : public BytecodeGenerator::ControlScope {
331 public:
332 ControlScopeForTryFinally(BytecodeGenerator* generator,
333 TryFinallyBuilder* try_finally_builder,
334 DeferredCommands* commands)
335 : ControlScope(generator),
336 try_finally_builder_(try_finally_builder),
337 commands_(commands) {
338 generator->try_finally_nesting_level_++;
339 }
340 virtual ~ControlScopeForTryFinally() {
341 generator()->try_finally_nesting_level_--;
342 }
343
344 protected:
345 bool Execute(Command command, Statement* statement) override {
346 switch (command) {
347 case CMD_BREAK:
348 case CMD_CONTINUE:
349 case CMD_RETURN:
350 case CMD_RETHROW:
351 commands_->RecordCommand(command, statement);
352 try_finally_builder_->LeaveTry();
353 return true;
354 }
355 return false;
356 }
357
358 private:
359 TryFinallyBuilder* try_finally_builder_;
360 DeferredCommands* commands_;
361};
362
363
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000364void BytecodeGenerator::ControlScope::PerformCommand(Command command,
365 Statement* statement) {
366 ControlScope* current = this;
Ben Murdochda12d292016-06-02 14:46:10 +0100367 ContextScope* context = generator()->execution_context();
368 // Pop context to the expected depth but do not pop the outermost context.
369 if (context != current->context() && context->ShouldPopContext()) {
370 generator()->builder()->PopContext(current->context()->reg());
371 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372 do {
Ben Murdochda12d292016-06-02 14:46:10 +0100373 if (current->Execute(command, statement)) {
374 return;
375 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000376 current = current->outer();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100377 if (current->context() != context) {
378 // Pop context to the expected depth.
379 // TODO(rmcilroy): Only emit a single context pop.
380 generator()->builder()->PopContext(current->context()->reg());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100381 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000382 } while (current != nullptr);
383 UNREACHABLE();
384}
385
386
387class BytecodeGenerator::RegisterAllocationScope {
388 public:
389 explicit RegisterAllocationScope(BytecodeGenerator* generator)
390 : generator_(generator),
391 outer_(generator->register_allocator()),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100392 allocator_(builder()->zone(),
393 builder()->temporary_register_allocator()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000394 generator_->set_register_allocator(this);
395 }
396
397 virtual ~RegisterAllocationScope() {
398 generator_->set_register_allocator(outer_);
399 }
400
401 Register NewRegister() {
402 RegisterAllocationScope* current_scope = generator()->register_allocator();
403 if ((current_scope == this) ||
404 (current_scope->outer() == this &&
405 !current_scope->allocator_.HasConsecutiveAllocations())) {
406 // Regular case - Allocating registers in current or outer context.
407 // VisitForRegisterValue allocates register in outer context.
408 return allocator_.NewRegister();
409 } else {
410 // If it is required to allocate a register other than current or outer
411 // scopes, allocate a new temporary register. It might be expensive to
412 // walk the full context chain and compute the list of consecutive
413 // reservations in the innerscopes.
414 UNIMPLEMENTED();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100415 return Register::invalid_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 }
417 }
418
Ben Murdoch097c5b22016-05-18 11:27:45 +0100419 void PrepareForConsecutiveAllocations(int count) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000420 allocator_.PrepareForConsecutiveAllocations(count);
421 }
422
423 Register NextConsecutiveRegister() {
424 return allocator_.NextConsecutiveRegister();
425 }
426
427 bool RegisterIsAllocatedInThisScope(Register reg) const {
428 return allocator_.RegisterIsAllocatedInThisScope(reg);
429 }
430
431 RegisterAllocationScope* outer() const { return outer_; }
432
433 private:
434 BytecodeGenerator* generator() const { return generator_; }
435 BytecodeArrayBuilder* builder() const { return generator_->builder(); }
436
437 BytecodeGenerator* generator_;
438 RegisterAllocationScope* outer_;
439 BytecodeRegisterAllocator allocator_;
440
441 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope);
442};
443
444
445// Scoped base class for determining where the result of an expression
446// is stored.
447class BytecodeGenerator::ExpressionResultScope {
448 public:
449 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
450 : generator_(generator),
451 kind_(kind),
452 outer_(generator->execution_result()),
453 allocator_(generator),
454 result_identified_(false) {
455 generator_->set_execution_result(this);
456 }
457
458 virtual ~ExpressionResultScope() {
459 generator_->set_execution_result(outer_);
Ben Murdochda12d292016-06-02 14:46:10 +0100460 DCHECK(result_identified() || generator_->HasStackOverflow());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461 }
462
463 bool IsEffect() const { return kind_ == Expression::kEffect; }
464 bool IsValue() const { return kind_ == Expression::kValue; }
465
466 virtual void SetResultInAccumulator() = 0;
467 virtual void SetResultInRegister(Register reg) = 0;
468
469 protected:
470 ExpressionResultScope* outer() const { return outer_; }
471 BytecodeArrayBuilder* builder() const { return generator_->builder(); }
Ben Murdochda12d292016-06-02 14:46:10 +0100472 BytecodeGenerator* generator() const { return generator_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000473 const RegisterAllocationScope* allocator() const { return &allocator_; }
474
475 void set_result_identified() {
476 DCHECK(!result_identified());
477 result_identified_ = true;
478 }
479
480 bool result_identified() const { return result_identified_; }
481
482 private:
483 BytecodeGenerator* generator_;
484 Expression::Context kind_;
485 ExpressionResultScope* outer_;
486 RegisterAllocationScope allocator_;
487 bool result_identified_;
488
489 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
490};
491
492
493// Scoped class used when the result of the current expression is not
494// expected to produce a result.
495class BytecodeGenerator::EffectResultScope final
496 : public ExpressionResultScope {
497 public:
498 explicit EffectResultScope(BytecodeGenerator* generator)
499 : ExpressionResultScope(generator, Expression::kEffect) {
500 set_result_identified();
501 }
502
503 virtual void SetResultInAccumulator() {}
504 virtual void SetResultInRegister(Register reg) {}
505};
506
507
508// Scoped class used when the result of the current expression to be
509// evaluated should go into the interpreter's accumulator register.
510class BytecodeGenerator::AccumulatorResultScope final
511 : public ExpressionResultScope {
512 public:
513 explicit AccumulatorResultScope(BytecodeGenerator* generator)
514 : ExpressionResultScope(generator, Expression::kValue) {}
515
516 virtual void SetResultInAccumulator() { set_result_identified(); }
517
518 virtual void SetResultInRegister(Register reg) {
519 builder()->LoadAccumulatorWithRegister(reg);
520 set_result_identified();
521 }
522};
523
524
525// Scoped class used when the result of the current expression to be
526// evaluated should go into an interpreter register.
527class BytecodeGenerator::RegisterResultScope final
528 : public ExpressionResultScope {
529 public:
530 explicit RegisterResultScope(BytecodeGenerator* generator)
531 : ExpressionResultScope(generator, Expression::kValue) {}
532
533 virtual void SetResultInAccumulator() {
534 result_register_ = allocator()->outer()->NewRegister();
535 builder()->StoreAccumulatorInRegister(result_register_);
536 set_result_identified();
537 }
538
539 virtual void SetResultInRegister(Register reg) {
540 DCHECK(builder()->RegisterIsParameterOrLocal(reg) ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100541 (builder()->TemporaryRegisterIsLive(reg) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542 !allocator()->RegisterIsAllocatedInThisScope(reg)));
543 result_register_ = reg;
544 set_result_identified();
545 }
546
Ben Murdochda12d292016-06-02 14:46:10 +0100547 Register ResultRegister() {
548 if (generator()->HasStackOverflow() && !result_identified()) {
549 SetResultInAccumulator();
550 }
551 return result_register_;
552 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000553
554 private:
555 Register result_register_;
556};
557
Ben Murdochc5610432016-08-08 18:44:38 +0100558BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
559 : isolate_(info->isolate()),
560 zone_(info->zone()),
561 builder_(new (zone()) BytecodeArrayBuilder(
562 info->isolate(), info->zone(), info->num_parameters_including_this(),
563 info->scope()->MaxNestedContextChainLength(),
564 info->scope()->num_stack_slots(), info->literal())),
565 info_(info),
566 scope_(info->scope()),
567 globals_(0, info->zone()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 execution_control_(nullptr),
569 execution_context_(nullptr),
570 execution_result_(nullptr),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100571 register_allocator_(nullptr),
Ben Murdochc5610432016-08-08 18:44:38 +0100572 generator_resume_points_(info->literal()->yield_count(), info->zone()),
573 generator_state_(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100574 try_catch_nesting_level_(0),
575 try_finally_nesting_level_(0) {
Ben Murdochc5610432016-08-08 18:44:38 +0100576 InitializeAstVisitor(isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000577}
578
Ben Murdochc5610432016-08-08 18:44:38 +0100579Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 // Initialize the incoming context.
581 ContextScope incoming_context(this, scope(), false);
582
Ben Murdoch097c5b22016-05-18 11:27:45 +0100583 // Initialize control scope.
584 ControlScopeForTopLevel control(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585
Ben Murdochc5610432016-08-08 18:44:38 +0100586 RegisterAllocationScope register_scope(this);
587
588 if (IsGeneratorFunction(info()->literal()->kind())) {
589 generator_state_ = register_allocator()->NewRegister();
590 VisitGeneratorPrologue();
591 }
592
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000593 // Build function context only if there are context allocated variables.
594 if (scope()->NeedsContext()) {
595 // Push a new inner context scope for the function.
596 VisitNewLocalFunctionContext();
597 ContextScope local_function_context(this, scope(), false);
598 VisitBuildLocalActivationContext();
599 MakeBytecodeBody();
600 } else {
601 MakeBytecodeBody();
602 }
603
Ben Murdochc5610432016-08-08 18:44:38 +0100604 // In generator functions, we may not have visited every yield in the AST
605 // since we skip some obviously dead code. Hence the generated bytecode may
606 // contain jumps to unbound labels (resume points that will never be used).
607 // We bind these now.
608 for (auto& label : generator_resume_points_) {
609 if (!label.is_bound()) builder()->Bind(&label);
610 }
611
Ben Murdochda12d292016-06-02 14:46:10 +0100612 builder()->EnsureReturn();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100613 return builder()->ToBytecodeArray();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000614}
615
616
617void BytecodeGenerator::MakeBytecodeBody() {
618 // Build the arguments object if it is used.
619 VisitArgumentsObject(scope()->arguments());
620
Ben Murdoch097c5b22016-05-18 11:27:45 +0100621 // Build rest arguments array if it is used.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000622 int rest_index;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100623 Variable* rest_parameter = scope()->rest_parameter(&rest_index);
624 VisitRestArgumentsArray(rest_parameter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000625
626 // Build assignment to {.this_function} variable if it is used.
627 VisitThisFunctionVariable(scope()->this_function_var());
628
629 // Build assignment to {new.target} variable if it is used.
630 VisitNewTargetVariable(scope()->new_target_var());
631
632 // TODO(rmcilroy): Emit tracing call if requested to do so.
633 if (FLAG_trace) {
634 UNIMPLEMENTED();
635 }
636
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 // Visit declarations within the function scope.
638 VisitDeclarations(scope()->declarations());
639
Ben Murdoch097c5b22016-05-18 11:27:45 +0100640 // Perform a stack-check before the body.
Ben Murdochc5610432016-08-08 18:44:38 +0100641 builder()->StackCheck(info()->literal()->start_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100642
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000643 // Visit statements in the function body.
644 VisitStatements(info()->literal()->body());
645}
646
Ben Murdochc5610432016-08-08 18:44:38 +0100647void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index,
648 size_t size,
649 ZoneVector<BytecodeLabel>& targets) {
650 // TODO(neis): Optimize this by using a proper jump table.
651 for (size_t i = start_index; i < start_index + size; i++) {
652 DCHECK(0 <= i && i < targets.size());
653 builder()
654 ->LoadLiteral(Smi::FromInt(static_cast<int>(i)))
655 .CompareOperation(Token::Value::EQ_STRICT, index)
656 .JumpIfTrue(&(targets[i]));
657 }
658
659 RegisterAllocationScope register_scope(this);
660 Register reason = register_allocator()->NewRegister();
661 BailoutReason bailout_reason = BailoutReason::kInvalidJumpTableIndex;
662 builder()
663 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason)))
664 .StoreAccumulatorInRegister(reason)
665 .CallRuntime(Runtime::kAbort, reason, 1);
666}
667
668void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt,
669 LoopBuilder* loop_builder) {
670 // Recall that stmt->yield_count() is always zero inside ordinary
671 // (i.e. non-generator) functions.
672
673 // Collect all labels for generator resume points within the loop (if any) so
674 // that they can be bound to the loop header below. Also create fresh labels
675 // for these resume points, to be used inside the loop.
676 ZoneVector<BytecodeLabel> resume_points_in_loop(zone());
677 size_t first_yield = stmt->first_yield_id();
678 for (size_t id = first_yield; id < first_yield + stmt->yield_count(); id++) {
679 DCHECK(0 <= id && id < generator_resume_points_.size());
680 auto& label = generator_resume_points_[id];
681 resume_points_in_loop.push_back(label);
682 generator_resume_points_[id] = BytecodeLabel();
683 }
684
685 loop_builder->LoopHeader(&resume_points_in_loop);
686
687 if (stmt->yield_count() > 0) {
688 // If we are not resuming, fall through to loop body.
689 // If we are resuming, perform state dispatch.
690 BytecodeLabel not_resuming;
691 builder()
692 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
693 .CompareOperation(Token::Value::EQ, generator_state_)
694 .JumpIfTrue(&not_resuming);
695 BuildIndexedJump(generator_state_, first_yield,
696 stmt->yield_count(), generator_resume_points_);
697 builder()->Bind(&not_resuming);
698 }
699}
700
701void BytecodeGenerator::VisitGeneratorPrologue() {
702 // The generator resume trampoline abuses the new.target register both to
703 // indicate that this is a resume call and to pass in the generator object.
704 // In ordinary calls, new.target is always undefined because generator
705 // functions are non-constructable.
706 Register generator_object = Register::new_target();
707 BytecodeLabel regular_call;
708 builder()
709 ->LoadAccumulatorWithRegister(generator_object)
710 .JumpIfUndefined(&regular_call);
711
712 // This is a resume call. Restore registers and perform state dispatch.
713 // (The current context has already been restored by the trampoline.)
714 builder()
715 ->ResumeGenerator(generator_object)
716 .StoreAccumulatorInRegister(generator_state_);
717 BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(),
718 generator_resume_points_);
719
720 builder()->Bind(&regular_call);
721 // This is a regular call. Fall through to the ordinary function prologue,
722 // after which we will run into the generator object creation and the initial
723 // yield (both inserted by the parser).
724}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000725
726void BytecodeGenerator::VisitBlock(Block* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100727 // Visit declarations and statements.
728 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
729 VisitNewLocalBlockContext(stmt->scope());
730 ContextScope scope(this, stmt->scope());
731 VisitBlockDeclarationsAndStatements(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000732 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100733 VisitBlockDeclarationsAndStatements(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000734 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100735}
736
737
738void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
739 BlockBuilder block_builder(builder());
740 ControlScopeForBreakable execution_control(this, stmt, &block_builder);
741 if (stmt->scope() != nullptr) {
742 VisitDeclarations(stmt->scope()->declarations());
743 }
744 VisitStatements(stmt->statements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000745 if (stmt->labels() != nullptr) block_builder.EndBlock();
746}
747
748
749void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
750 Variable* variable = decl->proxy()->var();
751 VariableMode mode = decl->mode();
752 // Const and let variables are initialized with the hole so that we can
753 // check that they are only assigned once.
Ben Murdochc5610432016-08-08 18:44:38 +0100754 bool hole_init = mode == CONST || mode == LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000755 switch (variable->location()) {
756 case VariableLocation::GLOBAL:
Ben Murdochc5610432016-08-08 18:44:38 +0100757 case VariableLocation::UNALLOCATED:
758 DCHECK(!variable->binding_needs_init());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000759 globals()->push_back(variable->name());
Ben Murdochc5610432016-08-08 18:44:38 +0100760 globals()->push_back(isolate()->factory()->undefined_value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000761 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000762 case VariableLocation::LOCAL:
763 if (hole_init) {
764 Register destination(variable->index());
765 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
766 }
767 break;
768 case VariableLocation::PARAMETER:
769 if (hole_init) {
770 // The parameter indices are shifted by 1 (receiver is variable
771 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
772 Register destination(builder()->Parameter(variable->index() + 1));
773 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
774 }
775 break;
776 case VariableLocation::CONTEXT:
777 if (hole_init) {
778 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
779 variable->index());
780 }
781 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100782 case VariableLocation::LOOKUP: {
783 DCHECK(IsDeclaredVariableMode(mode));
784
785 register_allocator()->PrepareForConsecutiveAllocations(3);
786 Register name = register_allocator()->NextConsecutiveRegister();
787 Register init_value = register_allocator()->NextConsecutiveRegister();
788 Register attributes = register_allocator()->NextConsecutiveRegister();
789
790 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
791 if (hole_init) {
792 builder()->LoadTheHole().StoreAccumulatorInRegister(init_value);
793 } else {
794 // For variables, we must not use an initial value (such as 'undefined')
795 // because we may have a (legal) redeclaration and we must not destroy
796 // the current value.
797 builder()
798 ->LoadLiteral(Smi::FromInt(0))
799 .StoreAccumulatorInRegister(init_value);
800 }
801 builder()
802 ->LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes()))
803 .StoreAccumulatorInRegister(attributes)
804 .CallRuntime(Runtime::kDeclareLookupSlot, name, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000805 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100806 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807 }
808}
809
810
811void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
812 Variable* variable = decl->proxy()->var();
813 switch (variable->location()) {
814 case VariableLocation::GLOBAL:
815 case VariableLocation::UNALLOCATED: {
816 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
817 decl->fun(), info()->script(), info());
818 // Check for stack-overflow exception.
819 if (function.is_null()) return SetStackOverflow();
820 globals()->push_back(variable->name());
821 globals()->push_back(function);
822 break;
823 }
824 case VariableLocation::PARAMETER:
825 case VariableLocation::LOCAL: {
826 VisitForAccumulatorValue(decl->fun());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100827 DCHECK(variable->mode() == LET || variable->mode() == VAR ||
828 variable->mode() == CONST);
829 VisitVariableAssignment(variable, Token::INIT,
830 FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 break;
832 }
833 case VariableLocation::CONTEXT: {
834 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
835 VisitForAccumulatorValue(decl->fun());
836 builder()->StoreContextSlot(execution_context()->reg(),
837 variable->index());
838 break;
839 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100840 case VariableLocation::LOOKUP: {
841 register_allocator()->PrepareForConsecutiveAllocations(3);
842 Register name = register_allocator()->NextConsecutiveRegister();
843 Register literal = register_allocator()->NextConsecutiveRegister();
844 Register attributes = register_allocator()->NextConsecutiveRegister();
845 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
846
847 VisitForAccumulatorValue(decl->fun());
848 builder()
849 ->StoreAccumulatorInRegister(literal)
850 .LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes()))
851 .StoreAccumulatorInRegister(attributes)
852 .CallRuntime(Runtime::kDeclareLookupSlot, name, 3);
853 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000854 }
855}
856
857
858void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
859 UNIMPLEMENTED();
860}
861
862
863void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
864 UNIMPLEMENTED();
865}
866
867
868void BytecodeGenerator::VisitDeclarations(
869 ZoneList<Declaration*>* declarations) {
870 RegisterAllocationScope register_scope(this);
871 DCHECK(globals()->empty());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100872 for (int i = 0; i < declarations->length(); i++) {
873 RegisterAllocationScope register_scope(this);
874 Visit(declarations->at(i));
875 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000876 if (globals()->empty()) return;
877 int array_index = 0;
878 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
879 static_cast<int>(globals()->size()), TENURED);
880 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
Ben Murdochc5610432016-08-08 18:44:38 +0100881 int encoded_flags = info()->GetDeclareGlobalsFlags();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000882
883 Register pairs = register_allocator()->NewRegister();
884 builder()->LoadLiteral(data);
885 builder()->StoreAccumulatorInRegister(pairs);
886
887 Register flags = register_allocator()->NewRegister();
888 builder()->LoadLiteral(Smi::FromInt(encoded_flags));
889 builder()->StoreAccumulatorInRegister(flags);
890 DCHECK(flags.index() == pairs.index() + 1);
891
892 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
893 globals()->clear();
894}
895
896
897void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
898 for (int i = 0; i < statements->length(); i++) {
899 // Allocate an outer register allocations scope for the statement.
900 RegisterAllocationScope allocation_scope(this);
901 Statement* stmt = statements->at(i);
902 Visit(stmt);
903 if (stmt->IsJump()) break;
904 }
905}
906
907
908void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100909 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000910 VisitForEffect(stmt->expression());
911}
912
913
914void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
915}
916
917
918void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100919 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000920 BytecodeLabel else_label, end_label;
921 if (stmt->condition()->ToBooleanIsTrue()) {
922 // Generate then block unconditionally as always true.
923 Visit(stmt->then_statement());
924 } else if (stmt->condition()->ToBooleanIsFalse()) {
925 // Generate else block unconditionally if it exists.
926 if (stmt->HasElseStatement()) {
927 Visit(stmt->else_statement());
928 }
929 } else {
930 // TODO(oth): If then statement is BreakStatement or
931 // ContinueStatement we can reduce number of generated
932 // jump/jump_ifs here. See BasicLoops test.
933 VisitForAccumulatorValue(stmt->condition());
934 builder()->JumpIfFalse(&else_label);
935 Visit(stmt->then_statement());
936 if (stmt->HasElseStatement()) {
937 builder()->Jump(&end_label);
938 builder()->Bind(&else_label);
939 Visit(stmt->else_statement());
940 } else {
941 builder()->Bind(&else_label);
942 }
943 builder()->Bind(&end_label);
944 }
945}
946
947
948void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
949 SloppyBlockFunctionStatement* stmt) {
950 Visit(stmt->statement());
951}
952
953
954void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100955 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000956 execution_control()->Continue(stmt->target());
957}
958
959
960void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100961 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000962 execution_control()->Break(stmt->target());
963}
964
965
966void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100967 builder()->SetStatementPosition(stmt);
Ben Murdochda12d292016-06-02 14:46:10 +0100968 VisitForAccumulatorValue(stmt->expression());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100969 execution_control()->ReturnAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000970}
971
972
973void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100974 builder()->SetStatementPosition(stmt);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100975 VisitForAccumulatorValue(stmt->expression());
976 builder()->CastAccumulatorToJSObject();
977 VisitNewLocalWithContext();
978 VisitInScope(stmt->statement(), stmt->scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000979}
980
981
982void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
983 // We need this scope because we visit for register values. We have to
984 // maintain a execution result scope where registers can be allocated.
985 ZoneList<CaseClause*>* clauses = stmt->cases();
986 SwitchBuilder switch_builder(builder(), clauses->length());
987 ControlScopeForBreakable scope(this, stmt, &switch_builder);
988 int default_index = -1;
989
Ben Murdochda12d292016-06-02 14:46:10 +0100990 builder()->SetStatementPosition(stmt);
991
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000992 // Keep the switch value in a register until a case matches.
993 Register tag = VisitForRegisterValue(stmt->tag());
994
995 // Iterate over all cases and create nodes for label comparison.
996 BytecodeLabel done_label;
997 for (int i = 0; i < clauses->length(); i++) {
998 CaseClause* clause = clauses->at(i);
999
1000 // The default is not a test, remember index.
1001 if (clause->is_default()) {
1002 default_index = i;
1003 continue;
1004 }
1005
1006 // Perform label comparison as if via '===' with tag.
1007 VisitForAccumulatorValue(clause->label());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001008 builder()->CompareOperation(Token::Value::EQ_STRICT, tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001009 switch_builder.Case(i);
1010 }
1011
1012 if (default_index >= 0) {
1013 // Emit default jump if there is a default case.
1014 switch_builder.DefaultAt(default_index);
1015 } else {
1016 // Otherwise if we have reached here none of the cases matched, so jump to
1017 // done.
1018 builder()->Jump(&done_label);
1019 }
1020
1021 // Iterate over all cases and create the case bodies.
1022 for (int i = 0; i < clauses->length(); i++) {
1023 CaseClause* clause = clauses->at(i);
1024 switch_builder.SetCaseTarget(i);
1025 VisitStatements(clause->statements());
1026 }
1027 builder()->Bind(&done_label);
1028
1029 switch_builder.SetBreakTarget(done_label);
1030}
1031
1032
1033void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
1034 // Handled entirely in VisitSwitchStatement.
1035 UNREACHABLE();
1036}
1037
Ben Murdoch097c5b22016-05-18 11:27:45 +01001038void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
1039 LoopBuilder* loop_builder) {
1040 ControlScopeForIteration execution_control(this, stmt, loop_builder);
Ben Murdochc5610432016-08-08 18:44:38 +01001041 builder()->StackCheck(stmt->position());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001042 Visit(stmt->body());
Ben Murdochc5610432016-08-08 18:44:38 +01001043 loop_builder->SetContinueTarget();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001044}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001045
1046void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
1047 LoopBuilder loop_builder(builder());
Ben Murdochc5610432016-08-08 18:44:38 +01001048 VisitIterationHeader(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 if (stmt->cond()->ToBooleanIsFalse()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001050 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001051 } else if (stmt->cond()->ToBooleanIsTrue()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001052 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001053 loop_builder.JumpToHeader();
1054 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001055 VisitIterationBody(stmt, &loop_builder);
Ben Murdochda12d292016-06-02 14:46:10 +01001056 builder()->SetExpressionAsStatementPosition(stmt->cond());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001057 VisitForAccumulatorValue(stmt->cond());
1058 loop_builder.JumpToHeaderIfTrue();
1059 }
1060 loop_builder.EndLoop();
1061}
1062
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001063void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1064 if (stmt->cond()->ToBooleanIsFalse()) {
1065 // If the condition is false there is no need to generate the loop.
1066 return;
1067 }
1068
1069 LoopBuilder loop_builder(builder());
Ben Murdochc5610432016-08-08 18:44:38 +01001070 VisitIterationHeader(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001071 if (!stmt->cond()->ToBooleanIsTrue()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001072 builder()->SetExpressionAsStatementPosition(stmt->cond());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001073 VisitForAccumulatorValue(stmt->cond());
1074 loop_builder.BreakIfFalse();
1075 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001076 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001077 loop_builder.JumpToHeader();
1078 loop_builder.EndLoop();
1079}
1080
1081
1082void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
1083 if (stmt->init() != nullptr) {
1084 Visit(stmt->init());
1085 }
1086 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
1087 // If the condition is known to be false there is no need to generate
1088 // body, next or condition blocks. Init block should be generated.
1089 return;
1090 }
1091
1092 LoopBuilder loop_builder(builder());
Ben Murdochc5610432016-08-08 18:44:38 +01001093 VisitIterationHeader(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001094 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001095 builder()->SetExpressionAsStatementPosition(stmt->cond());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001096 VisitForAccumulatorValue(stmt->cond());
1097 loop_builder.BreakIfFalse();
1098 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001099 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001100 if (stmt->next() != nullptr) {
Ben Murdochda12d292016-06-02 14:46:10 +01001101 builder()->SetStatementPosition(stmt->next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001102 Visit(stmt->next());
1103 }
1104 loop_builder.JumpToHeader();
1105 loop_builder.EndLoop();
1106}
1107
1108
1109void BytecodeGenerator::VisitForInAssignment(Expression* expr,
1110 FeedbackVectorSlot slot) {
1111 DCHECK(expr->IsValidReferenceExpression());
1112
1113 // Evaluate assignment starting with the value to be stored in the
1114 // accumulator.
1115 Property* property = expr->AsProperty();
1116 LhsKind assign_type = Property::GetAssignType(property);
1117 switch (assign_type) {
1118 case VARIABLE: {
1119 Variable* variable = expr->AsVariableProxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001120 VisitVariableAssignment(variable, Token::ASSIGN, slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001121 break;
1122 }
1123 case NAMED_PROPERTY: {
1124 RegisterAllocationScope register_scope(this);
1125 Register value = register_allocator()->NewRegister();
1126 builder()->StoreAccumulatorInRegister(value);
1127 Register object = VisitForRegisterValue(property->obj());
1128 Handle<String> name = property->key()->AsLiteral()->AsPropertyName();
1129 builder()->LoadAccumulatorWithRegister(value);
1130 builder()->StoreNamedProperty(object, name, feedback_index(slot),
1131 language_mode());
1132 break;
1133 }
1134 case KEYED_PROPERTY: {
1135 RegisterAllocationScope register_scope(this);
1136 Register value = register_allocator()->NewRegister();
1137 builder()->StoreAccumulatorInRegister(value);
1138 Register object = VisitForRegisterValue(property->obj());
1139 Register key = VisitForRegisterValue(property->key());
1140 builder()->LoadAccumulatorWithRegister(value);
1141 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
1142 language_mode());
1143 break;
1144 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001145 case NAMED_SUPER_PROPERTY: {
1146 RegisterAllocationScope register_scope(this);
1147 register_allocator()->PrepareForConsecutiveAllocations(4);
1148 Register receiver = register_allocator()->NextConsecutiveRegister();
1149 Register home_object = register_allocator()->NextConsecutiveRegister();
1150 Register name = register_allocator()->NextConsecutiveRegister();
1151 Register value = register_allocator()->NextConsecutiveRegister();
1152 builder()->StoreAccumulatorInRegister(value);
1153 SuperPropertyReference* super_property =
1154 property->obj()->AsSuperPropertyReference();
1155 VisitForRegisterValue(super_property->this_var(), receiver);
1156 VisitForRegisterValue(super_property->home_object(), home_object);
1157 builder()
1158 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
1159 .StoreAccumulatorInRegister(name);
1160 BuildNamedSuperPropertyStore(receiver, home_object, name, value);
1161 break;
1162 }
1163 case KEYED_SUPER_PROPERTY: {
1164 RegisterAllocationScope register_scope(this);
1165 register_allocator()->PrepareForConsecutiveAllocations(4);
1166 Register receiver = register_allocator()->NextConsecutiveRegister();
1167 Register home_object = register_allocator()->NextConsecutiveRegister();
1168 Register key = register_allocator()->NextConsecutiveRegister();
1169 Register value = register_allocator()->NextConsecutiveRegister();
1170 builder()->StoreAccumulatorInRegister(value);
1171 SuperPropertyReference* super_property =
1172 property->obj()->AsSuperPropertyReference();
1173 VisitForRegisterValue(super_property->this_var(), receiver);
1174 VisitForRegisterValue(super_property->home_object(), home_object);
1175 VisitForRegisterValue(property->key(), key);
1176 BuildKeyedSuperPropertyStore(receiver, home_object, key, value);
1177 break;
1178 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179 }
1180}
1181
1182
1183void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1184 if (stmt->subject()->IsNullLiteral() ||
Ben Murdochda12d292016-06-02 14:46:10 +01001185 stmt->subject()->IsUndefinedLiteral()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001186 // ForIn generates lots of code, skip if it wouldn't produce any effects.
1187 return;
1188 }
1189
1190 LoopBuilder loop_builder(builder());
Ben Murdochda12d292016-06-02 14:46:10 +01001191 BytecodeLabel subject_null_label, subject_undefined_label;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001192
1193 // Prepare the state for executing ForIn.
Ben Murdochda12d292016-06-02 14:46:10 +01001194 builder()->SetExpressionAsStatementPosition(stmt->subject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195 VisitForAccumulatorValue(stmt->subject());
1196 builder()->JumpIfUndefined(&subject_undefined_label);
1197 builder()->JumpIfNull(&subject_null_label);
1198 Register receiver = register_allocator()->NewRegister();
1199 builder()->CastAccumulatorToJSObject();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001200 builder()->StoreAccumulatorInRegister(receiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001201
1202 register_allocator()->PrepareForConsecutiveAllocations(3);
1203 Register cache_type = register_allocator()->NextConsecutiveRegister();
1204 Register cache_array = register_allocator()->NextConsecutiveRegister();
1205 Register cache_length = register_allocator()->NextConsecutiveRegister();
Ben Murdochda12d292016-06-02 14:46:10 +01001206 // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001207 USE(cache_array);
1208 builder()->ForInPrepare(cache_type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001209
1210 // Set up loop counter
1211 Register index = register_allocator()->NewRegister();
1212 builder()->LoadLiteral(Smi::FromInt(0));
1213 builder()->StoreAccumulatorInRegister(index);
1214
1215 // The loop
Ben Murdochc5610432016-08-08 18:44:38 +01001216 VisitIterationHeader(stmt, &loop_builder);
Ben Murdochda12d292016-06-02 14:46:10 +01001217 builder()->SetExpressionAsStatementPosition(stmt->each());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001218 builder()->ForInDone(index, cache_length);
1219 loop_builder.BreakIfTrue();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001220 DCHECK(Register::AreContiguous(cache_type, cache_array));
Ben Murdochda12d292016-06-02 14:46:10 +01001221 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
1222 builder()->ForInNext(receiver, index, cache_type, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001223 loop_builder.ContinueIfUndefined();
1224 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001225 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001226 builder()->ForInStep(index);
1227 builder()->StoreAccumulatorInRegister(index);
1228 loop_builder.JumpToHeader();
1229 loop_builder.EndLoop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001230 builder()->Bind(&subject_null_label);
1231 builder()->Bind(&subject_undefined_label);
1232}
1233
1234
1235void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001236 LoopBuilder loop_builder(builder());
1237 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
1238
Ben Murdochc5610432016-08-08 18:44:38 +01001239 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001240 VisitForEffect(stmt->assign_iterator());
1241
Ben Murdochc5610432016-08-08 18:44:38 +01001242 VisitIterationHeader(stmt, &loop_builder);
Ben Murdochda12d292016-06-02 14:46:10 +01001243 builder()->SetExpressionAsStatementPosition(stmt->next_result());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001244 VisitForEffect(stmt->next_result());
1245 VisitForAccumulatorValue(stmt->result_done());
1246 loop_builder.BreakIfTrue();
1247
1248 VisitForEffect(stmt->assign_each());
1249 VisitIterationBody(stmt, &loop_builder);
1250 loop_builder.JumpToHeader();
1251 loop_builder.EndLoop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001252}
1253
1254
1255void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001256 TryCatchBuilder try_control_builder(builder());
1257 Register no_reg;
1258
1259 // Preserve the context in a dedicated register, so that it can be restored
1260 // when the handler is entered by the stack-unwinding machinery.
1261 // TODO(mstarzinger): Be smarter about register allocation.
1262 Register context = register_allocator()->NewRegister();
1263 builder()->MoveRegister(Register::current_context(), context);
1264
1265 // Evaluate the try-block inside a control scope. This simulates a handler
1266 // that is intercepting 'throw' control commands.
1267 try_control_builder.BeginTry(context);
1268 {
1269 ControlScopeForTryCatch scope(this, &try_control_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001270 Visit(stmt->try_block());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001271 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001272 try_control_builder.EndTry();
1273
1274 // Create a catch scope that binds the exception.
1275 VisitNewLocalCatchContext(stmt->variable());
1276 builder()->StoreAccumulatorInRegister(context);
1277
Ben Murdochda12d292016-06-02 14:46:10 +01001278 // If requested, clear message object as we enter the catch block.
1279 if (stmt->clear_pending_message()) {
1280 builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0);
1281 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001282
1283 // Load the catch context into the accumulator.
1284 builder()->LoadAccumulatorWithRegister(context);
1285
1286 // Evaluate the catch-block.
1287 VisitInScope(stmt->catch_block(), stmt->scope());
1288 try_control_builder.EndCatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001289}
1290
1291
1292void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001293 TryFinallyBuilder try_control_builder(builder(), IsInsideTryCatch());
1294 Register no_reg;
1295
1296 // We keep a record of all paths that enter the finally-block to be able to
1297 // dispatch to the correct continuation point after the statements in the
1298 // finally-block have been evaluated.
1299 //
1300 // The try-finally construct can enter the finally-block in three ways:
1301 // 1. By exiting the try-block normally, falling through at the end.
1302 // 2. By exiting the try-block with a function-local control flow transfer
1303 // (i.e. through break/continue/return statements).
1304 // 3. By exiting the try-block with a thrown exception.
1305 //
1306 // The result register semantics depend on how the block was entered:
1307 // - ReturnStatement: It represents the return value being returned.
1308 // - ThrowStatement: It represents the exception being thrown.
1309 // - BreakStatement/ContinueStatement: Undefined and not used.
1310 // - Falling through into finally-block: Undefined and not used.
1311 Register token = register_allocator()->NewRegister();
1312 Register result = register_allocator()->NewRegister();
1313 ControlScope::DeferredCommands commands(this, token, result);
1314
1315 // Preserve the context in a dedicated register, so that it can be restored
1316 // when the handler is entered by the stack-unwinding machinery.
1317 // TODO(mstarzinger): Be smarter about register allocation.
1318 Register context = register_allocator()->NewRegister();
1319 builder()->MoveRegister(Register::current_context(), context);
1320
1321 // Evaluate the try-block inside a control scope. This simulates a handler
1322 // that is intercepting all control commands.
1323 try_control_builder.BeginTry(context);
1324 {
1325 ControlScopeForTryFinally scope(this, &try_control_builder, &commands);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001326 Visit(stmt->try_block());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001327 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001328 try_control_builder.EndTry();
1329
1330 // Record fall-through and exception cases.
1331 commands.RecordFallThroughPath();
1332 try_control_builder.LeaveTry();
1333 try_control_builder.BeginHandler();
1334 commands.RecordHandlerReThrowPath();
1335
1336 // Pending message object is saved on entry.
1337 try_control_builder.BeginFinally();
1338 Register message = context; // Reuse register.
1339
1340 // Clear message object as we enter the finally block.
1341 builder()
1342 ->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0)
1343 .StoreAccumulatorInRegister(message);
1344
1345 // Evaluate the finally-block.
1346 Visit(stmt->finally_block());
1347 try_control_builder.EndFinally();
1348
1349 // Pending message object is restored on exit.
1350 builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message, 1);
1351
1352 // Dynamic dispatch after the finally-block.
1353 commands.ApplyDeferredCommands();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001354}
1355
1356
1357void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001358 builder()->SetStatementPosition(stmt);
1359 builder()->Debugger();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001360}
1361
1362
1363void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1364 // Find or build a shared function info.
1365 Handle<SharedFunctionInfo> shared_info =
1366 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
Ben Murdochda12d292016-06-02 14:46:10 +01001367 if (shared_info.is_null()) {
1368 return SetStackOverflow();
1369 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001370 builder()->CreateClosure(shared_info,
1371 expr->pretenure() ? TENURED : NOT_TENURED);
1372 execution_result()->SetResultInAccumulator();
1373}
1374
1375
1376void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001377 if (expr->scope()->ContextLocalCount() > 0) {
1378 VisitNewLocalBlockContext(expr->scope());
1379 ContextScope scope(this, expr->scope());
1380 VisitDeclarations(expr->scope()->declarations());
1381 VisitClassLiteralContents(expr);
1382 } else {
1383 VisitDeclarations(expr->scope()->declarations());
1384 VisitClassLiteralContents(expr);
1385 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001386}
1387
Ben Murdoch097c5b22016-05-18 11:27:45 +01001388void BytecodeGenerator::VisitClassLiteralContents(ClassLiteral* expr) {
1389 VisitClassLiteralForRuntimeDefinition(expr);
1390
1391 // Load the "prototype" from the constructor.
1392 register_allocator()->PrepareForConsecutiveAllocations(2);
1393 Register literal = register_allocator()->NextConsecutiveRegister();
1394 Register prototype = register_allocator()->NextConsecutiveRegister();
1395 Handle<String> name = isolate()->factory()->prototype_string();
1396 FeedbackVectorSlot slot = expr->PrototypeSlot();
1397 builder()
1398 ->StoreAccumulatorInRegister(literal)
1399 .LoadNamedProperty(literal, name, feedback_index(slot))
1400 .StoreAccumulatorInRegister(prototype);
1401
1402 VisitClassLiteralProperties(expr, literal, prototype);
Ben Murdochc5610432016-08-08 18:44:38 +01001403 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001404 // Assign to class variable.
1405 if (expr->class_variable_proxy() != nullptr) {
1406 Variable* var = expr->class_variable_proxy()->var();
1407 FeedbackVectorSlot slot = expr->NeedsProxySlot()
1408 ? expr->ProxySlot()
1409 : FeedbackVectorSlot::Invalid();
1410 VisitVariableAssignment(var, Token::INIT, slot);
1411 }
1412 execution_result()->SetResultInAccumulator();
1413}
1414
1415void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition(
1416 ClassLiteral* expr) {
1417 AccumulatorResultScope result_scope(this);
1418 register_allocator()->PrepareForConsecutiveAllocations(4);
1419 Register extends = register_allocator()->NextConsecutiveRegister();
1420 Register constructor = register_allocator()->NextConsecutiveRegister();
1421 Register start_position = register_allocator()->NextConsecutiveRegister();
1422 Register end_position = register_allocator()->NextConsecutiveRegister();
1423
1424 VisitForAccumulatorValueOrTheHole(expr->extends());
1425 builder()->StoreAccumulatorInRegister(extends);
1426
1427 VisitForAccumulatorValue(expr->constructor());
1428 builder()
1429 ->StoreAccumulatorInRegister(constructor)
1430 .LoadLiteral(Smi::FromInt(expr->start_position()))
1431 .StoreAccumulatorInRegister(start_position)
1432 .LoadLiteral(Smi::FromInt(expr->end_position()))
1433 .StoreAccumulatorInRegister(end_position)
1434 .CallRuntime(Runtime::kDefineClass, extends, 4);
1435 result_scope.SetResultInAccumulator();
1436}
1437
1438void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
1439 Register literal,
1440 Register prototype) {
1441 RegisterAllocationScope register_scope(this);
1442 register_allocator()->PrepareForConsecutiveAllocations(5);
1443 Register receiver = register_allocator()->NextConsecutiveRegister();
1444 Register key = register_allocator()->NextConsecutiveRegister();
1445 Register value = register_allocator()->NextConsecutiveRegister();
1446 Register attr = register_allocator()->NextConsecutiveRegister();
1447 Register set_function_name = register_allocator()->NextConsecutiveRegister();
1448
1449 bool attr_assigned = false;
1450 Register old_receiver = Register::invalid_value();
1451
1452 // Create nodes to store method values into the literal.
1453 for (int i = 0; i < expr->properties()->length(); i++) {
1454 ObjectLiteral::Property* property = expr->properties()->at(i);
1455
1456 // Set-up receiver.
1457 Register new_receiver = property->is_static() ? literal : prototype;
1458 if (new_receiver != old_receiver) {
1459 builder()->MoveRegister(new_receiver, receiver);
1460 old_receiver = new_receiver;
1461 }
1462
1463 VisitForAccumulatorValue(property->key());
1464 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1465 // The static prototype property is read only. We handle the non computed
1466 // property name case in the parser. Since this is the only case where we
1467 // need to check for an own read only property we special case this so we do
1468 // not need to do this for every property.
1469 if (property->is_static() && property->is_computed_name()) {
1470 VisitClassLiteralStaticPrototypeWithComputedName(key);
1471 }
1472 VisitForAccumulatorValue(property->value());
1473 builder()->StoreAccumulatorInRegister(value);
1474
1475 VisitSetHomeObject(value, receiver, property);
1476
1477 if (!attr_assigned) {
1478 builder()
1479 ->LoadLiteral(Smi::FromInt(DONT_ENUM))
1480 .StoreAccumulatorInRegister(attr);
1481 attr_assigned = true;
1482 }
1483
1484 switch (property->kind()) {
1485 case ObjectLiteral::Property::CONSTANT:
1486 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1487 case ObjectLiteral::Property::PROTOTYPE:
1488 // Invalid properties for ES6 classes.
1489 UNREACHABLE();
1490 break;
1491 case ObjectLiteral::Property::COMPUTED: {
1492 builder()
1493 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
1494 .StoreAccumulatorInRegister(set_function_name);
1495 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, receiver,
1496 5);
1497 break;
1498 }
1499 case ObjectLiteral::Property::GETTER: {
1500 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
1501 receiver, 4);
1502 break;
1503 }
1504 case ObjectLiteral::Property::SETTER: {
1505 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
1506 receiver, 4);
1507 break;
1508 }
1509 }
1510 }
1511}
1512
1513void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName(
1514 Register key) {
1515 BytecodeLabel done;
1516 builder()
1517 ->LoadLiteral(isolate()->factory()->prototype_string())
1518 .CompareOperation(Token::Value::EQ_STRICT, key)
1519 .JumpIfFalse(&done)
1520 .CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0)
1521 .Bind(&done);
1522}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001523
1524void BytecodeGenerator::VisitNativeFunctionLiteral(
1525 NativeFunctionLiteral* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001526 // Find or build a shared function info for the native function template.
1527 Handle<SharedFunctionInfo> shared_info =
1528 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name());
1529 builder()->CreateClosure(shared_info, NOT_TENURED);
1530 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001531}
1532
1533
1534void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001535 VisitBlock(expr->block());
1536 VisitVariableProxy(expr->result());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001537}
1538
1539
1540void BytecodeGenerator::VisitConditional(Conditional* expr) {
1541 // TODO(rmcilroy): Spot easy cases where there code would not need to
1542 // emit the then block or the else block, e.g. condition is
1543 // obviously true/1/false/0.
1544
1545 BytecodeLabel else_label, end_label;
1546
1547 VisitForAccumulatorValue(expr->condition());
1548 builder()->JumpIfFalse(&else_label);
1549
1550 VisitForAccumulatorValue(expr->then_expression());
1551 builder()->Jump(&end_label);
1552
1553 builder()->Bind(&else_label);
1554 VisitForAccumulatorValue(expr->else_expression());
1555 builder()->Bind(&end_label);
1556
1557 execution_result()->SetResultInAccumulator();
1558}
1559
1560
1561void BytecodeGenerator::VisitLiteral(Literal* expr) {
1562 if (!execution_result()->IsEffect()) {
1563 Handle<Object> value = expr->value();
1564 if (value->IsSmi()) {
1565 builder()->LoadLiteral(Smi::cast(*value));
1566 } else if (value->IsUndefined()) {
1567 builder()->LoadUndefined();
1568 } else if (value->IsTrue()) {
1569 builder()->LoadTrue();
1570 } else if (value->IsFalse()) {
1571 builder()->LoadFalse();
1572 } else if (value->IsNull()) {
1573 builder()->LoadNull();
1574 } else if (value->IsTheHole()) {
1575 builder()->LoadTheHole();
1576 } else {
1577 builder()->LoadLiteral(value);
1578 }
1579 execution_result()->SetResultInAccumulator();
1580 }
1581}
1582
1583
1584void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1585 // Materialize a regular expression literal.
1586 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(),
1587 expr->flags());
1588 execution_result()->SetResultInAccumulator();
1589}
1590
1591
1592void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Ben Murdochc5610432016-08-08 18:44:38 +01001593 // Copy the literal boilerplate.
1594 int fast_clone_properties_count = 0;
1595 if (FastCloneShallowObjectStub::IsSupported(expr)) {
1596 STATIC_ASSERT(
1597 FastCloneShallowObjectStub::kMaximumClonedProperties <=
1598 1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift);
1599 fast_clone_properties_count =
1600 FastCloneShallowObjectStub::PropertiesCount(expr->properties_count());
1601 }
1602 uint8_t flags =
1603 CreateObjectLiteralFlags::FlagsBits::encode(expr->ComputeFlags()) |
1604 CreateObjectLiteralFlags::FastClonePropertiesCountBits::encode(
1605 fast_clone_properties_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001606 builder()->CreateObjectLiteral(expr->constant_properties(),
Ben Murdochc5610432016-08-08 18:44:38 +01001607 expr->literal_index(), flags);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001608
1609 // Allocate in the outer scope since this register is used to return the
1610 // expression's results to the caller.
1611 Register literal = register_allocator()->outer()->NewRegister();
1612 builder()->StoreAccumulatorInRegister(literal);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001613
1614 // Store computed values into the literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001615 int property_index = 0;
1616 AccessorTable accessor_table(zone());
1617 for (; property_index < expr->properties()->length(); property_index++) {
1618 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1619 if (property->is_computed_name()) break;
1620 if (property->IsCompileTimeValue()) continue;
1621
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001622 RegisterAllocationScope inner_register_scope(this);
1623 Literal* literal_key = property->key()->AsLiteral();
1624 switch (property->kind()) {
1625 case ObjectLiteral::Property::CONSTANT:
1626 UNREACHABLE();
1627 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1628 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1629 // Fall through.
1630 case ObjectLiteral::Property::COMPUTED: {
1631 // It is safe to use [[Put]] here because the boilerplate already
1632 // contains computed properties with an uninitialized value.
1633 if (literal_key->value()->IsInternalizedString()) {
1634 if (property->emit_store()) {
1635 VisitForAccumulatorValue(property->value());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001636 if (FunctionLiteral::NeedsHomeObject(property->value())) {
1637 RegisterAllocationScope register_scope(this);
1638 Register value = register_allocator()->NewRegister();
1639 builder()->StoreAccumulatorInRegister(value);
1640 builder()->StoreNamedProperty(
1641 literal, literal_key->AsPropertyName(),
1642 feedback_index(property->GetSlot(0)), language_mode());
1643 VisitSetHomeObject(value, literal, property, 1);
1644 } else {
1645 builder()->StoreNamedProperty(
1646 literal, literal_key->AsPropertyName(),
1647 feedback_index(property->GetSlot(0)), language_mode());
1648 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001649 } else {
1650 VisitForEffect(property->value());
1651 }
1652 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001653 register_allocator()->PrepareForConsecutiveAllocations(4);
1654 Register literal_argument =
1655 register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001656 Register key = register_allocator()->NextConsecutiveRegister();
1657 Register value = register_allocator()->NextConsecutiveRegister();
1658 Register language = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001659
1660 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001661 VisitForAccumulatorValue(property->key());
1662 builder()->StoreAccumulatorInRegister(key);
1663 VisitForAccumulatorValue(property->value());
1664 builder()->StoreAccumulatorInRegister(value);
1665 if (property->emit_store()) {
1666 builder()
1667 ->LoadLiteral(Smi::FromInt(SLOPPY))
1668 .StoreAccumulatorInRegister(language)
Ben Murdoch097c5b22016-05-18 11:27:45 +01001669 .CallRuntime(Runtime::kSetProperty, literal_argument, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001670 VisitSetHomeObject(value, literal, property);
1671 }
1672 }
1673 break;
1674 }
1675 case ObjectLiteral::Property::PROTOTYPE: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001676 DCHECK(property->emit_store());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001677 register_allocator()->PrepareForConsecutiveAllocations(2);
1678 Register literal_argument =
1679 register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001680 Register value = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001681
1682 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001683 VisitForAccumulatorValue(property->value());
1684 builder()->StoreAccumulatorInRegister(value).CallRuntime(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001685 Runtime::kInternalSetPrototype, literal_argument, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001686 break;
1687 }
1688 case ObjectLiteral::Property::GETTER:
1689 if (property->emit_store()) {
1690 accessor_table.lookup(literal_key)->second->getter = property;
1691 }
1692 break;
1693 case ObjectLiteral::Property::SETTER:
1694 if (property->emit_store()) {
1695 accessor_table.lookup(literal_key)->second->setter = property;
1696 }
1697 break;
1698 }
1699 }
1700
1701 // Define accessors, using only a single call to the runtime for each pair of
1702 // corresponding getters and setters.
1703 for (AccessorTable::Iterator it = accessor_table.begin();
1704 it != accessor_table.end(); ++it) {
1705 RegisterAllocationScope inner_register_scope(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001706 register_allocator()->PrepareForConsecutiveAllocations(5);
1707 Register literal_argument = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001708 Register name = register_allocator()->NextConsecutiveRegister();
1709 Register getter = register_allocator()->NextConsecutiveRegister();
1710 Register setter = register_allocator()->NextConsecutiveRegister();
1711 Register attr = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001712
1713 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001714 VisitForAccumulatorValue(it->first);
1715 builder()->StoreAccumulatorInRegister(name);
1716 VisitObjectLiteralAccessor(literal, it->second->getter, getter);
1717 VisitObjectLiteralAccessor(literal, it->second->setter, setter);
1718 builder()
1719 ->LoadLiteral(Smi::FromInt(NONE))
1720 .StoreAccumulatorInRegister(attr)
Ben Murdoch097c5b22016-05-18 11:27:45 +01001721 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked,
1722 literal_argument, 5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001723 }
1724
1725 // Object literals have two parts. The "static" part on the left contains no
1726 // computed property names, and so we can compute its map ahead of time; see
1727 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1728 // with the first computed property name and continues with all properties to
1729 // its right. All the code from above initializes the static component of the
1730 // object literal, and arranges for the map of the result to reflect the
1731 // static order in which the keys appear. For the dynamic properties, we
1732 // compile them into a series of "SetOwnProperty" runtime calls. This will
1733 // preserve insertion order.
1734 for (; property_index < expr->properties()->length(); property_index++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001735 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1736 RegisterAllocationScope inner_register_scope(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001737
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001738 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1739 DCHECK(property->emit_store());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001740 register_allocator()->PrepareForConsecutiveAllocations(2);
1741 Register literal_argument =
1742 register_allocator()->NextConsecutiveRegister();
1743 Register value = register_allocator()->NextConsecutiveRegister();
1744
1745 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001746 VisitForAccumulatorValue(property->value());
1747 builder()->StoreAccumulatorInRegister(value).CallRuntime(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001748 Runtime::kInternalSetPrototype, literal_argument, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001749 continue;
1750 }
1751
Ben Murdoch097c5b22016-05-18 11:27:45 +01001752 register_allocator()->PrepareForConsecutiveAllocations(5);
1753 Register literal_argument = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001754 Register key = register_allocator()->NextConsecutiveRegister();
1755 Register value = register_allocator()->NextConsecutiveRegister();
1756 Register attr = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001757 DCHECK(Register::AreContiguous(literal_argument, key, value, attr));
1758 Register set_function_name =
1759 register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001760
Ben Murdoch097c5b22016-05-18 11:27:45 +01001761 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001762 VisitForAccumulatorValue(property->key());
1763 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1764 VisitForAccumulatorValue(property->value());
1765 builder()->StoreAccumulatorInRegister(value);
1766 VisitSetHomeObject(value, literal, property);
1767 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001768 switch (property->kind()) {
1769 case ObjectLiteral::Property::CONSTANT:
1770 case ObjectLiteral::Property::COMPUTED:
1771 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001772 builder()
1773 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
1774 .StoreAccumulatorInRegister(set_function_name);
1775 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral,
1776 literal_argument, 5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001777 break;
1778 case ObjectLiteral::Property::PROTOTYPE:
1779 UNREACHABLE(); // Handled specially above.
1780 break;
1781 case ObjectLiteral::Property::GETTER:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001782 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
1783 literal_argument, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001784 break;
1785 case ObjectLiteral::Property::SETTER:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001786 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
1787 literal_argument, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001788 break;
1789 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001790 }
1791
Ben Murdoch097c5b22016-05-18 11:27:45 +01001792 execution_result()->SetResultInRegister(literal);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001793}
1794
1795
1796void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1797 // Deep-copy the literal boilerplate.
1798 builder()->CreateArrayLiteral(expr->constant_elements(),
1799 expr->literal_index(),
1800 expr->ComputeFlags(true));
1801 Register index, literal;
1802
1803 // Evaluate all the non-constant subexpressions and store them into the
1804 // newly cloned array.
1805 bool literal_in_accumulator = true;
1806 for (int array_index = 0; array_index < expr->values()->length();
1807 array_index++) {
1808 Expression* subexpr = expr->values()->at(array_index);
1809 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001810 DCHECK(!subexpr->IsSpread());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001811
1812 if (literal_in_accumulator) {
1813 index = register_allocator()->NewRegister();
1814 literal = register_allocator()->NewRegister();
1815 builder()->StoreAccumulatorInRegister(literal);
1816 literal_in_accumulator = false;
1817 }
1818
1819 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot();
1820 builder()
1821 ->LoadLiteral(Smi::FromInt(array_index))
1822 .StoreAccumulatorInRegister(index);
1823 VisitForAccumulatorValue(subexpr);
1824 builder()->StoreKeyedProperty(literal, index, feedback_index(slot),
1825 language_mode());
1826 }
1827
1828 if (!literal_in_accumulator) {
1829 // Restore literal array into accumulator.
1830 builder()->LoadAccumulatorWithRegister(literal);
1831 }
1832 execution_result()->SetResultInAccumulator();
1833}
1834
1835
1836void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
Ben Murdochda12d292016-06-02 14:46:10 +01001837 builder()->SetExpressionPosition(proxy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001838 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1839}
1840
Ben Murdoch097c5b22016-05-18 11:27:45 +01001841void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
1842 Handle<String> name) {
Ben Murdochc5610432016-08-08 18:44:38 +01001843 if (mode == LET || mode == CONST) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001844 BuildThrowIfHole(name);
1845 }
1846}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001847
1848void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1849 FeedbackVectorSlot slot,
1850 TypeofMode typeof_mode) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001851 VariableMode mode = variable->mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001852 switch (variable->location()) {
1853 case VariableLocation::LOCAL: {
1854 Register source(Register(variable->index()));
1855 builder()->LoadAccumulatorWithRegister(source);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001856 BuildHoleCheckForVariableLoad(mode, variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001857 execution_result()->SetResultInAccumulator();
1858 break;
1859 }
1860 case VariableLocation::PARAMETER: {
1861 // The parameter indices are shifted by 1 (receiver is variable
1862 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1863 Register source = builder()->Parameter(variable->index() + 1);
1864 builder()->LoadAccumulatorWithRegister(source);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001865 BuildHoleCheckForVariableLoad(mode, variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001866 execution_result()->SetResultInAccumulator();
1867 break;
1868 }
1869 case VariableLocation::GLOBAL:
1870 case VariableLocation::UNALLOCATED: {
1871 builder()->LoadGlobal(variable->name(), feedback_index(slot),
Ben Murdoch097c5b22016-05-18 11:27:45 +01001872 typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001873 execution_result()->SetResultInAccumulator();
1874 break;
1875 }
1876 case VariableLocation::CONTEXT: {
1877 int depth = execution_context()->ContextChainDepth(variable->scope());
1878 ContextScope* context = execution_context()->Previous(depth);
1879 Register context_reg;
1880 if (context) {
1881 context_reg = context->reg();
1882 } else {
1883 context_reg = register_allocator()->NewRegister();
1884 // Walk the context chain to find the context at the given depth.
1885 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1886 // a generic mechanism for performing jumps in interpreter.cc.
1887 // TODO(mythria): Also update bytecode graph builder with correct depth
1888 // when this changes.
1889 builder()
1890 ->LoadAccumulatorWithRegister(execution_context()->reg())
1891 .StoreAccumulatorInRegister(context_reg);
1892 for (int i = 0; i < depth; ++i) {
1893 builder()
1894 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1895 .StoreAccumulatorInRegister(context_reg);
1896 }
1897 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001898
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001899 builder()->LoadContextSlot(context_reg, variable->index());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001900 BuildHoleCheckForVariableLoad(mode, variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001901 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001902 break;
1903 }
1904 case VariableLocation::LOOKUP: {
1905 builder()->LoadLookupSlot(variable->name(), typeof_mode);
1906 execution_result()->SetResultInAccumulator();
1907 break;
1908 }
1909 }
1910}
1911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001912void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
1913 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1914 AccumulatorResultScope accumulator_result(this);
1915 VisitVariableLoad(variable, slot, typeof_mode);
1916}
1917
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001918Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
1919 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1920 RegisterResultScope register_scope(this);
1921 VisitVariableLoad(variable, slot, typeof_mode);
1922 return register_scope.ResultRegister();
1923}
1924
Ben Murdoch097c5b22016-05-18 11:27:45 +01001925void BytecodeGenerator::BuildNamedSuperPropertyLoad(Register receiver,
1926 Register home_object,
1927 Register name) {
1928 DCHECK(Register::AreContiguous(receiver, home_object, name));
1929 builder()->CallRuntime(Runtime::kLoadFromSuper, receiver, 3);
1930}
1931
1932void BytecodeGenerator::BuildKeyedSuperPropertyLoad(Register receiver,
1933 Register home_object,
1934 Register key) {
1935 DCHECK(Register::AreContiguous(receiver, home_object, key));
1936 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, receiver, 3);
1937}
1938
1939void BytecodeGenerator::BuildNamedSuperPropertyStore(Register receiver,
1940 Register home_object,
1941 Register name,
1942 Register value) {
1943 DCHECK(Register::AreContiguous(receiver, home_object, name, value));
1944 Runtime::FunctionId function_id = is_strict(language_mode())
1945 ? Runtime::kStoreToSuper_Strict
1946 : Runtime::kStoreToSuper_Sloppy;
1947 builder()->CallRuntime(function_id, receiver, 4);
1948}
1949
1950void BytecodeGenerator::BuildKeyedSuperPropertyStore(Register receiver,
1951 Register home_object,
1952 Register key,
1953 Register value) {
1954 DCHECK(Register::AreContiguous(receiver, home_object, key, value));
1955 Runtime::FunctionId function_id = is_strict(language_mode())
1956 ? Runtime::kStoreKeyedToSuper_Strict
1957 : Runtime::kStoreKeyedToSuper_Sloppy;
1958 builder()->CallRuntime(function_id, receiver, 4);
1959}
1960
1961void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) {
1962 RegisterAllocationScope register_scope(this);
1963 Register name_reg = register_allocator()->NewRegister();
1964 builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime(
1965 Runtime::kThrowReferenceError, name_reg, 1);
1966}
1967
1968void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
1969 // TODO(interpreter): Can the parser reduce the number of checks
1970 // performed? Or should there be a ThrowIfHole bytecode.
1971 BytecodeLabel no_reference_error;
1972 builder()->JumpIfNotHole(&no_reference_error);
1973 BuildThrowReferenceError(name);
1974 builder()->Bind(&no_reference_error);
1975}
1976
1977void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
1978 // TODO(interpreter): Can the parser reduce the number of checks
1979 // performed? Or should there be a ThrowIfNotHole bytecode.
1980 BytecodeLabel no_reference_error, reference_error;
1981 builder()
1982 ->JumpIfNotHole(&reference_error)
1983 .Jump(&no_reference_error)
1984 .Bind(&reference_error);
1985 BuildThrowReferenceError(name);
1986 builder()->Bind(&no_reference_error);
1987}
1988
1989void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
1990 // TODO(mythria): This will be replaced by a new bytecode that throws an
1991 // appropriate error depending on the whether the value is a hole or not.
1992 BytecodeLabel const_assign_error;
1993 builder()->JumpIfNotHole(&const_assign_error);
1994 BuildThrowReferenceError(name);
1995 builder()
1996 ->Bind(&const_assign_error)
1997 .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
1998}
1999
2000void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
2001 Token::Value op) {
2002 VariableMode mode = variable->mode();
2003 DCHECK(mode != CONST_LEGACY);
2004 if (mode == CONST && op != Token::INIT) {
2005 // Non-intializing assignments to constant is not allowed.
2006 BuildThrowReassignConstant(variable->name());
2007 } else if (mode == LET && op != Token::INIT) {
2008 // Perform an initialization check for let declared variables.
2009 // E.g. let x = (x = 20); is not allowed.
2010 BuildThrowIfHole(variable->name());
2011 } else {
2012 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
2013 // Perform an initialization check for 'this'. 'this' variable is the
2014 // only variable able to trigger bind operations outside the TDZ
2015 // via 'super' calls.
2016 BuildThrowIfNotHole(variable->name());
2017 }
2018}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002019
2020void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
Ben Murdoch097c5b22016-05-18 11:27:45 +01002021 Token::Value op,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002022 FeedbackVectorSlot slot) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002023 VariableMode mode = variable->mode();
2024 RegisterAllocationScope assignment_register_scope(this);
2025 BytecodeLabel end_label;
2026 bool hole_check_required =
Ben Murdochc5610432016-08-08 18:44:38 +01002027 (mode == LET && op != Token::INIT) ||
Ben Murdoch097c5b22016-05-18 11:27:45 +01002028 (mode == CONST && op != Token::INIT) ||
2029 (mode == CONST && op == Token::INIT && variable->is_this());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002030 switch (variable->location()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002031 case VariableLocation::PARAMETER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002032 case VariableLocation::LOCAL: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002033 Register destination;
2034 if (VariableLocation::PARAMETER == variable->location()) {
2035 destination = Register(builder()->Parameter(variable->index() + 1));
2036 } else {
2037 destination = Register(variable->index());
2038 }
2039
Ben Murdochc5610432016-08-08 18:44:38 +01002040 if (mode == CONST_LEGACY && op != Token::INIT) {
2041 if (is_strict(language_mode())) {
2042 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
2043 0);
2044 }
2045 // Non-initializing assignments to legacy constants are ignored
2046 // in sloppy mode. Break here to avoid storing into variable.
2047 break;
2048 }
2049
Ben Murdoch097c5b22016-05-18 11:27:45 +01002050 if (hole_check_required) {
2051 // Load destination to check for hole.
2052 Register value_temp = register_allocator()->NewRegister();
2053 builder()
2054 ->StoreAccumulatorInRegister(value_temp)
2055 .LoadAccumulatorWithRegister(destination);
2056
Ben Murdochc5610432016-08-08 18:44:38 +01002057 BuildHoleCheckForVariableAssignment(variable, op);
2058 builder()->LoadAccumulatorWithRegister(value_temp);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002059 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002060 builder()->StoreAccumulatorInRegister(destination);
2061 break;
2062 }
2063 case VariableLocation::GLOBAL:
2064 case VariableLocation::UNALLOCATED: {
2065 builder()->StoreGlobal(variable->name(), feedback_index(slot),
2066 language_mode());
2067 break;
2068 }
2069 case VariableLocation::CONTEXT: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002070 int depth = execution_context()->ContextChainDepth(variable->scope());
2071 ContextScope* context = execution_context()->Previous(depth);
2072 Register context_reg;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002073
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002074 if (context) {
2075 context_reg = context->reg();
2076 } else {
2077 Register value_temp = register_allocator()->NewRegister();
2078 context_reg = register_allocator()->NewRegister();
2079 // Walk the context chain to find the context at the given depth.
2080 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
2081 // a generic mechanism for performing jumps in interpreter.cc.
2082 // TODO(mythria): Also update bytecode graph builder with correct depth
2083 // when this changes.
2084 builder()
2085 ->StoreAccumulatorInRegister(value_temp)
2086 .LoadAccumulatorWithRegister(execution_context()->reg())
2087 .StoreAccumulatorInRegister(context_reg);
2088 for (int i = 0; i < depth; ++i) {
2089 builder()
2090 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
2091 .StoreAccumulatorInRegister(context_reg);
2092 }
2093 builder()->LoadAccumulatorWithRegister(value_temp);
2094 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002095
Ben Murdochc5610432016-08-08 18:44:38 +01002096 if (mode == CONST_LEGACY && op != Token::INIT) {
2097 if (is_strict(language_mode())) {
2098 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
2099 0);
2100 }
2101 // Non-initializing assignments to legacy constants are ignored
2102 // in sloppy mode. Break here to avoid storing into variable.
2103 break;
2104 }
2105
Ben Murdoch097c5b22016-05-18 11:27:45 +01002106 if (hole_check_required) {
2107 // Load destination to check for hole.
2108 Register value_temp = register_allocator()->NewRegister();
2109 builder()
2110 ->StoreAccumulatorInRegister(value_temp)
2111 .LoadContextSlot(context_reg, variable->index());
2112
Ben Murdochc5610432016-08-08 18:44:38 +01002113 BuildHoleCheckForVariableAssignment(variable, op);
2114 builder()->LoadAccumulatorWithRegister(value_temp);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002115 }
2116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002117 builder()->StoreContextSlot(context_reg, variable->index());
2118 break;
2119 }
2120 case VariableLocation::LOOKUP: {
Ben Murdochc5610432016-08-08 18:44:38 +01002121 DCHECK_NE(CONST_LEGACY, variable->mode());
2122 builder()->StoreLookupSlot(variable->name(), language_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002123 break;
2124 }
2125 }
2126}
2127
2128
2129void BytecodeGenerator::VisitAssignment(Assignment* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002130 DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
2131 Register object, key, home_object, value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002132 Handle<String> name;
2133
2134 // Left-hand side can only be a property, a global or a variable slot.
2135 Property* property = expr->target()->AsProperty();
2136 LhsKind assign_type = Property::GetAssignType(property);
2137
2138 // Evaluate LHS expression.
2139 switch (assign_type) {
2140 case VARIABLE:
2141 // Nothing to do to evaluate variable assignment LHS.
2142 break;
2143 case NAMED_PROPERTY: {
2144 object = VisitForRegisterValue(property->obj());
2145 name = property->key()->AsLiteral()->AsPropertyName();
2146 break;
2147 }
2148 case KEYED_PROPERTY: {
2149 object = VisitForRegisterValue(property->obj());
2150 if (expr->is_compound()) {
2151 // Use VisitForAccumulator and store to register so that the key is
2152 // still in the accumulator for loading the old value below.
2153 key = register_allocator()->NewRegister();
2154 VisitForAccumulatorValue(property->key());
2155 builder()->StoreAccumulatorInRegister(key);
2156 } else {
2157 key = VisitForRegisterValue(property->key());
2158 }
2159 break;
2160 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002161 case NAMED_SUPER_PROPERTY: {
2162 register_allocator()->PrepareForConsecutiveAllocations(4);
2163 object = register_allocator()->NextConsecutiveRegister();
2164 home_object = register_allocator()->NextConsecutiveRegister();
2165 key = register_allocator()->NextConsecutiveRegister();
2166 value = register_allocator()->NextConsecutiveRegister();
2167 SuperPropertyReference* super_property =
2168 property->obj()->AsSuperPropertyReference();
2169 VisitForRegisterValue(super_property->this_var(), object);
2170 VisitForRegisterValue(super_property->home_object(), home_object);
2171 builder()
2172 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2173 .StoreAccumulatorInRegister(key);
2174 break;
2175 }
2176 case KEYED_SUPER_PROPERTY: {
2177 register_allocator()->PrepareForConsecutiveAllocations(4);
2178 object = register_allocator()->NextConsecutiveRegister();
2179 home_object = register_allocator()->NextConsecutiveRegister();
2180 key = register_allocator()->NextConsecutiveRegister();
2181 value = register_allocator()->NextConsecutiveRegister();
2182 builder()->StoreAccumulatorInRegister(value);
2183 SuperPropertyReference* super_property =
2184 property->obj()->AsSuperPropertyReference();
2185 VisitForRegisterValue(super_property->this_var(), object);
2186 VisitForRegisterValue(super_property->home_object(), home_object);
2187 VisitForRegisterValue(property->key(), key);
2188 break;
2189 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002190 }
2191
2192 // Evaluate the value and potentially handle compound assignments by loading
2193 // the left-hand side value and performing a binary operation.
2194 if (expr->is_compound()) {
2195 Register old_value;
2196 switch (assign_type) {
2197 case VARIABLE: {
2198 VariableProxy* proxy = expr->target()->AsVariableProxy();
2199 old_value = VisitVariableLoadForRegisterValue(
2200 proxy->var(), proxy->VariableFeedbackSlot());
2201 break;
2202 }
2203 case NAMED_PROPERTY: {
2204 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2205 old_value = register_allocator()->NewRegister();
2206 builder()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002207 ->LoadNamedProperty(object, name, feedback_index(slot))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002208 .StoreAccumulatorInRegister(old_value);
2209 break;
2210 }
2211 case KEYED_PROPERTY: {
2212 // Key is already in accumulator at this point due to evaluating the
2213 // LHS above.
2214 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2215 old_value = register_allocator()->NewRegister();
2216 builder()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002217 ->LoadKeyedProperty(object, feedback_index(slot))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002218 .StoreAccumulatorInRegister(old_value);
2219 break;
2220 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002221 case NAMED_SUPER_PROPERTY: {
2222 old_value = register_allocator()->NewRegister();
2223 BuildNamedSuperPropertyLoad(object, home_object, key);
2224 builder()->StoreAccumulatorInRegister(old_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002225 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002226 }
2227 case KEYED_SUPER_PROPERTY: {
2228 old_value = register_allocator()->NewRegister();
2229 BuildKeyedSuperPropertyLoad(object, home_object, key);
2230 builder()->StoreAccumulatorInRegister(old_value);
2231 break;
2232 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002233 }
2234 VisitForAccumulatorValue(expr->value());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002235 builder()->BinaryOperation(expr->binary_op(), old_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002236 } else {
2237 VisitForAccumulatorValue(expr->value());
2238 }
2239
2240 // Store the value.
Ben Murdochda12d292016-06-02 14:46:10 +01002241 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002242 FeedbackVectorSlot slot = expr->AssignmentSlot();
2243 switch (assign_type) {
2244 case VARIABLE: {
2245 // TODO(oth): The VisitVariableAssignment() call is hard to reason about.
2246 // Is the value in the accumulator safe? Yes, but scary.
2247 Variable* variable = expr->target()->AsVariableProxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002248 VisitVariableAssignment(variable, expr->op(), slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002249 break;
2250 }
2251 case NAMED_PROPERTY:
2252 builder()->StoreNamedProperty(object, name, feedback_index(slot),
2253 language_mode());
2254 break;
2255 case KEYED_PROPERTY:
2256 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
2257 language_mode());
2258 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002259 case NAMED_SUPER_PROPERTY: {
2260 builder()->StoreAccumulatorInRegister(value);
2261 BuildNamedSuperPropertyStore(object, home_object, key, value);
2262 break;
2263 }
2264 case KEYED_SUPER_PROPERTY: {
2265 builder()->StoreAccumulatorInRegister(value);
2266 BuildKeyedSuperPropertyStore(object, home_object, key, value);
2267 break;
2268 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002269 }
2270 execution_result()->SetResultInAccumulator();
2271}
2272
Ben Murdochc5610432016-08-08 18:44:38 +01002273void BytecodeGenerator::VisitYield(Yield* expr) {
2274 builder()->SetExpressionPosition(expr);
2275 Register value = VisitForRegisterValue(expr->expression());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002276
Ben Murdochc5610432016-08-08 18:44:38 +01002277 Register generator = VisitForRegisterValue(expr->generator_object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002278
Ben Murdochc5610432016-08-08 18:44:38 +01002279 // Save context, registers, and state. Then return.
2280 builder()
2281 ->LoadLiteral(Smi::FromInt(expr->yield_id()))
2282 .SuspendGenerator(generator)
2283 .LoadAccumulatorWithRegister(value)
2284 .Return(); // Hard return (ignore any finally blocks).
2285
2286 builder()->Bind(&(generator_resume_points_[expr->yield_id()]));
2287 // Upon resume, we continue here.
2288
2289 {
2290 RegisterAllocationScope register_scope(this);
2291
2292 // Update state to indicate that we have finished resuming. Loop headers
2293 // rely on this.
2294 builder()
2295 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
2296 .StoreAccumulatorInRegister(generator_state_);
2297
2298 Register input = register_allocator()->NewRegister();
2299 builder()
2300 ->CallRuntime(Runtime::kGeneratorGetInput, generator, 1)
2301 .StoreAccumulatorInRegister(input);
2302
2303 Register resume_mode = register_allocator()->NewRegister();
2304 builder()
2305 ->CallRuntime(Runtime::kGeneratorGetResumeMode, generator, 1)
2306 .StoreAccumulatorInRegister(resume_mode);
2307
2308 // Now dispatch on resume mode.
2309
2310 BytecodeLabel resume_with_next;
2311 BytecodeLabel resume_with_return;
2312 BytecodeLabel resume_with_throw;
2313
2314 builder()
2315 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
2316 .CompareOperation(Token::EQ_STRICT, resume_mode)
2317 .JumpIfTrue(&resume_with_next)
2318 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow))
2319 .CompareOperation(Token::EQ_STRICT, resume_mode)
2320 .JumpIfTrue(&resume_with_throw)
2321 .Jump(&resume_with_return);
2322
2323 builder()->Bind(&resume_with_return);
2324 {
2325 register_allocator()->PrepareForConsecutiveAllocations(2);
2326 Register value = register_allocator()->NextConsecutiveRegister();
2327 Register done = register_allocator()->NextConsecutiveRegister();
2328 builder()
2329 ->MoveRegister(input, value)
2330 .LoadTrue()
2331 .StoreAccumulatorInRegister(done)
2332 .CallRuntime(Runtime::kCreateIterResultObject, value, 2);
2333 execution_control()->ReturnAccumulator();
2334 }
2335
2336 builder()->Bind(&resume_with_throw);
2337 builder()
2338 ->LoadAccumulatorWithRegister(input)
2339 .Throw();
2340
2341 builder()->Bind(&resume_with_next);
2342 builder()->LoadAccumulatorWithRegister(input);
2343 }
2344 execution_result()->SetResultInAccumulator();
2345}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002346
2347void BytecodeGenerator::VisitThrow(Throw* expr) {
2348 VisitForAccumulatorValue(expr->exception());
Ben Murdochda12d292016-06-02 14:46:10 +01002349 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002350 builder()->Throw();
Ben Murdochc5610432016-08-08 18:44:38 +01002351 // Throw statements are modeled as expressions instead of statements. These
2352 // are converted from assignment statements in Rewriter::ReWrite pass. An
Ben Murdoch097c5b22016-05-18 11:27:45 +01002353 // assignment statement expects a value in the accumulator. This is a hack to
2354 // avoid DCHECK fails assert accumulator has been set.
2355 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002356}
2357
2358
2359void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
2360 LhsKind property_kind = Property::GetAssignType(expr);
2361 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
Ben Murdochda12d292016-06-02 14:46:10 +01002362 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002363 switch (property_kind) {
2364 case VARIABLE:
2365 UNREACHABLE();
2366 case NAMED_PROPERTY: {
2367 builder()->LoadNamedProperty(obj,
2368 expr->key()->AsLiteral()->AsPropertyName(),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002369 feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002370 break;
2371 }
2372 case KEYED_PROPERTY: {
2373 VisitForAccumulatorValue(expr->key());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002374 builder()->LoadKeyedProperty(obj, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002375 break;
2376 }
2377 case NAMED_SUPER_PROPERTY:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002378 VisitNamedSuperPropertyLoad(expr, Register::invalid_value());
2379 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002380 case KEYED_SUPER_PROPERTY:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002381 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value());
2382 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002383 }
2384 execution_result()->SetResultInAccumulator();
2385}
2386
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002387void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj,
2388 Property* expr) {
2389 AccumulatorResultScope result_scope(this);
2390 VisitPropertyLoad(obj, expr);
2391}
2392
Ben Murdoch097c5b22016-05-18 11:27:45 +01002393void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
2394 Register opt_receiver_out) {
2395 RegisterAllocationScope register_scope(this);
2396 register_allocator()->PrepareForConsecutiveAllocations(3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002397
Ben Murdoch097c5b22016-05-18 11:27:45 +01002398 Register receiver, home_object, name;
2399 receiver = register_allocator()->NextConsecutiveRegister();
2400 home_object = register_allocator()->NextConsecutiveRegister();
2401 name = register_allocator()->NextConsecutiveRegister();
2402 SuperPropertyReference* super_property =
2403 property->obj()->AsSuperPropertyReference();
2404 VisitForRegisterValue(super_property->this_var(), receiver);
2405 VisitForRegisterValue(super_property->home_object(), home_object);
2406 builder()
2407 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2408 .StoreAccumulatorInRegister(name);
2409 BuildNamedSuperPropertyLoad(receiver, home_object, name);
2410
2411 if (opt_receiver_out.is_valid()) {
2412 builder()->MoveRegister(receiver, opt_receiver_out);
2413 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002414}
2415
Ben Murdoch097c5b22016-05-18 11:27:45 +01002416void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
2417 Register opt_receiver_out) {
2418 RegisterAllocationScope register_scope(this);
2419 register_allocator()->PrepareForConsecutiveAllocations(3);
2420
2421 Register receiver, home_object, key;
2422 receiver = register_allocator()->NextConsecutiveRegister();
2423 home_object = register_allocator()->NextConsecutiveRegister();
2424 key = register_allocator()->NextConsecutiveRegister();
2425 SuperPropertyReference* super_property =
2426 property->obj()->AsSuperPropertyReference();
2427 VisitForRegisterValue(super_property->this_var(), receiver);
2428 VisitForRegisterValue(super_property->home_object(), home_object);
2429 VisitForRegisterValue(property->key(), key);
2430 BuildKeyedSuperPropertyLoad(receiver, home_object, key);
2431
2432 if (opt_receiver_out.is_valid()) {
2433 builder()->MoveRegister(receiver, opt_receiver_out);
2434 }
2435}
2436
2437void BytecodeGenerator::VisitProperty(Property* expr) {
2438 LhsKind property_kind = Property::GetAssignType(expr);
2439 if (property_kind != NAMED_SUPER_PROPERTY &&
2440 property_kind != KEYED_SUPER_PROPERTY) {
2441 Register obj = VisitForRegisterValue(expr->obj());
2442 VisitPropertyLoad(obj, expr);
2443 } else {
2444 VisitPropertyLoad(Register::invalid_value(), expr);
2445 }
2446}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002447
2448Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
2449 if (args->length() == 0) {
2450 return Register();
2451 }
2452
2453 // Visit arguments and place in a contiguous block of temporary
2454 // registers. Return the first temporary register corresponding to
2455 // the first argument.
2456 //
2457 // NB the caller may have already called
2458 // PrepareForConsecutiveAllocations() with args->length() + N. The
2459 // second call here will be a no-op provided there have been N or
2460 // less calls to NextConsecutiveRegister(). Otherwise, the arguments
2461 // here will be consecutive, but they will not be consecutive with
2462 // earlier consecutive allocations made by the caller.
2463 register_allocator()->PrepareForConsecutiveAllocations(args->length());
2464
2465 // Visit for first argument that goes into returned register
2466 Register first_arg = register_allocator()->NextConsecutiveRegister();
2467 VisitForAccumulatorValue(args->at(0));
2468 builder()->StoreAccumulatorInRegister(first_arg);
2469
2470 // Visit remaining arguments
2471 for (int i = 1; i < static_cast<int>(args->length()); i++) {
2472 Register ith_arg = register_allocator()->NextConsecutiveRegister();
2473 VisitForAccumulatorValue(args->at(i));
2474 builder()->StoreAccumulatorInRegister(ith_arg);
2475 DCHECK(ith_arg.index() - i == first_arg.index());
2476 }
2477 return first_arg;
2478}
2479
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002480void BytecodeGenerator::VisitCall(Call* expr) {
2481 Expression* callee_expr = expr->expression();
2482 Call::CallType call_type = expr->GetCallType(isolate());
2483
Ben Murdoch097c5b22016-05-18 11:27:45 +01002484 if (call_type == Call::SUPER_CALL) {
2485 return VisitCallSuper(expr);
2486 }
2487
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002488 // Prepare the callee and the receiver to the function call. This depends on
2489 // the semantics of the underlying call type.
2490
2491 // The receiver and arguments need to be allocated consecutively for
2492 // Call(). We allocate the callee and receiver consecutively for calls to
Ben Murdoch097c5b22016-05-18 11:27:45 +01002493 // %LoadLookupSlotForCall. Future optimizations could avoid this there are
2494 // no arguments or the receiver and arguments are already consecutive.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002495 ZoneList<Expression*>* args = expr->arguments();
2496 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2);
2497 Register callee = register_allocator()->NextConsecutiveRegister();
2498 Register receiver = register_allocator()->NextConsecutiveRegister();
2499
2500 switch (call_type) {
2501 case Call::NAMED_PROPERTY_CALL:
2502 case Call::KEYED_PROPERTY_CALL: {
2503 Property* property = callee_expr->AsProperty();
2504 VisitForAccumulatorValue(property->obj());
2505 builder()->StoreAccumulatorInRegister(receiver);
2506 VisitPropertyLoadForAccumulator(receiver, property);
2507 builder()->StoreAccumulatorInRegister(callee);
2508 break;
2509 }
2510 case Call::GLOBAL_CALL: {
2511 // Receiver is undefined for global calls.
2512 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2513 // Load callee as a global variable.
2514 VariableProxy* proxy = callee_expr->AsVariableProxy();
2515 VisitVariableLoadForAccumulatorValue(proxy->var(),
2516 proxy->VariableFeedbackSlot());
2517 builder()->StoreAccumulatorInRegister(callee);
2518 break;
2519 }
2520 case Call::LOOKUP_SLOT_CALL:
2521 case Call::POSSIBLY_EVAL_CALL: {
2522 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) {
2523 RegisterAllocationScope inner_register_scope(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002524 Register name = register_allocator()->NewRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002525
Ben Murdoch097c5b22016-05-18 11:27:45 +01002526 // Call %LoadLookupSlotForCall to get the callee and receiver.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002527 DCHECK(Register::AreContiguous(callee, receiver));
2528 Variable* variable = callee_expr->AsVariableProxy()->var();
2529 builder()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002530 ->LoadLiteral(variable->name())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002531 .StoreAccumulatorInRegister(name)
Ben Murdoch097c5b22016-05-18 11:27:45 +01002532 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 1,
2533 callee);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002534 break;
2535 }
2536 // Fall through.
2537 DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL);
2538 }
2539 case Call::OTHER_CALL: {
2540 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2541 VisitForAccumulatorValue(callee_expr);
2542 builder()->StoreAccumulatorInRegister(callee);
2543 break;
2544 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002545 case Call::NAMED_SUPER_PROPERTY_CALL: {
2546 Property* property = callee_expr->AsProperty();
2547 VisitNamedSuperPropertyLoad(property, receiver);
2548 builder()->StoreAccumulatorInRegister(callee);
2549 break;
2550 }
2551 case Call::KEYED_SUPER_PROPERTY_CALL: {
2552 Property* property = callee_expr->AsProperty();
2553 VisitKeyedSuperPropertyLoad(property, receiver);
2554 builder()->StoreAccumulatorInRegister(callee);
2555 break;
2556 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002557 case Call::SUPER_CALL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002558 UNREACHABLE();
2559 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002560 }
2561
2562 // Evaluate all arguments to the function call and store in sequential
2563 // registers.
2564 Register arg = VisitArguments(args);
2565 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1);
2566
2567 // Resolve callee for a potential direct eval call. This block will mutate the
2568 // callee value.
2569 if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) {
2570 RegisterAllocationScope inner_register_scope(this);
Ben Murdochc5610432016-08-08 18:44:38 +01002571 register_allocator()->PrepareForConsecutiveAllocations(6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002572 Register callee_for_eval = register_allocator()->NextConsecutiveRegister();
2573 Register source = register_allocator()->NextConsecutiveRegister();
2574 Register function = register_allocator()->NextConsecutiveRegister();
2575 Register language = register_allocator()->NextConsecutiveRegister();
Ben Murdochc5610432016-08-08 18:44:38 +01002576 Register eval_scope_position =
2577 register_allocator()->NextConsecutiveRegister();
2578 Register eval_position = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002579
2580 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
2581 // strings and function closure, and loading language and
2582 // position.
2583 builder()
2584 ->MoveRegister(callee, callee_for_eval)
2585 .MoveRegister(arg, source)
2586 .MoveRegister(Register::function_closure(), function)
2587 .LoadLiteral(Smi::FromInt(language_mode()))
2588 .StoreAccumulatorInRegister(language)
2589 .LoadLiteral(
2590 Smi::FromInt(execution_context()->scope()->start_position()))
Ben Murdochc5610432016-08-08 18:44:38 +01002591 .StoreAccumulatorInRegister(eval_scope_position)
2592 .LoadLiteral(Smi::FromInt(expr->position()))
2593 .StoreAccumulatorInRegister(eval_position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002594
2595 // Call ResolvePossiblyDirectEval and modify the callee.
2596 builder()
Ben Murdochc5610432016-08-08 18:44:38 +01002597 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 6)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002598 .StoreAccumulatorInRegister(callee);
2599 }
2600
Ben Murdoch097c5b22016-05-18 11:27:45 +01002601 builder()->SetExpressionPosition(expr);
2602 builder()->Call(callee, receiver, 1 + args->length(),
2603 feedback_index(expr->CallFeedbackICSlot()),
2604 expr->tail_call_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002605 execution_result()->SetResultInAccumulator();
2606}
2607
Ben Murdoch097c5b22016-05-18 11:27:45 +01002608void BytecodeGenerator::VisitCallSuper(Call* expr) {
2609 RegisterAllocationScope register_scope(this);
2610 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2611
2612 // Prepare the constructor to the super call.
2613 Register this_function = register_allocator()->NewRegister();
2614 VisitForAccumulatorValue(super->this_function_var());
2615 builder()
2616 ->StoreAccumulatorInRegister(this_function)
2617 .CallRuntime(Runtime::kInlineGetSuperConstructor, this_function, 1);
2618
2619 Register constructor = this_function; // Re-use dead this_function register.
2620 builder()->StoreAccumulatorInRegister(constructor);
2621
2622 ZoneList<Expression*>* args = expr->arguments();
2623 Register first_arg = VisitArguments(args);
2624
2625 // The new target is loaded into the accumulator from the
2626 // {new.target} variable.
2627 VisitForAccumulatorValue(super->new_target_var());
2628
2629 // Call construct.
2630 builder()->SetExpressionPosition(expr);
2631 builder()->New(constructor, first_arg, args->length());
2632 execution_result()->SetResultInAccumulator();
2633}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002634
2635void BytecodeGenerator::VisitCallNew(CallNew* expr) {
2636 Register constructor = register_allocator()->NewRegister();
2637 VisitForAccumulatorValue(expr->expression());
2638 builder()->StoreAccumulatorInRegister(constructor);
2639
2640 ZoneList<Expression*>* args = expr->arguments();
2641 Register first_arg = VisitArguments(args);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002642
2643 builder()->SetExpressionPosition(expr);
2644 // The accumulator holds new target which is the same as the
2645 // constructor for CallNew.
2646 builder()
2647 ->LoadAccumulatorWithRegister(constructor)
2648 .New(constructor, first_arg, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002649 execution_result()->SetResultInAccumulator();
2650}
2651
2652
2653void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2654 ZoneList<Expression*>* args = expr->arguments();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002655 if (expr->is_jsruntime()) {
2656 // Allocate a register for the receiver and load it with undefined.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002657 register_allocator()->PrepareForConsecutiveAllocations(1 + args->length());
2658 Register receiver = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002659 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002660 Register first_arg = VisitArguments(args);
2661 CHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1);
2662 builder()->CallJSRuntime(expr->context_index(), receiver,
2663 1 + args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002664 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002665 // Evaluate all arguments to the runtime call.
2666 Register first_arg = VisitArguments(args);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002667 Runtime::FunctionId function_id = expr->function()->function_id;
2668 builder()->CallRuntime(function_id, first_arg, args->length());
2669 }
2670 execution_result()->SetResultInAccumulator();
2671}
2672
2673
2674void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
2675 VisitForEffect(expr->expression());
2676 builder()->LoadUndefined();
2677 execution_result()->SetResultInAccumulator();
2678}
2679
2680
2681void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
2682 if (expr->expression()->IsVariableProxy()) {
2683 // Typeof does not throw a reference error on global variables, hence we
2684 // perform a non-contextual load in case the operand is a variable proxy.
2685 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2686 VisitVariableLoadForAccumulatorValue(
2687 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF);
2688 } else {
2689 VisitForAccumulatorValue(expr->expression());
2690 }
2691 builder()->TypeOf();
2692 execution_result()->SetResultInAccumulator();
2693}
2694
2695
2696void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
2697 VisitForAccumulatorValue(expr->expression());
2698 builder()->LogicalNot();
2699 execution_result()->SetResultInAccumulator();
2700}
2701
2702
2703void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2704 switch (expr->op()) {
2705 case Token::Value::NOT:
2706 VisitNot(expr);
2707 break;
2708 case Token::Value::TYPEOF:
2709 VisitTypeOf(expr);
2710 break;
2711 case Token::Value::VOID:
2712 VisitVoid(expr);
2713 break;
2714 case Token::Value::DELETE:
2715 VisitDelete(expr);
2716 break;
2717 case Token::Value::BIT_NOT:
2718 case Token::Value::ADD:
2719 case Token::Value::SUB:
2720 // These operators are converted to an equivalent binary operators in
2721 // the parser. These operators are not expected to be visited here.
2722 UNREACHABLE();
2723 default:
2724 UNREACHABLE();
2725 }
2726}
2727
2728
2729void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
2730 if (expr->expression()->IsProperty()) {
2731 // Delete of an object property is allowed both in sloppy
2732 // and strict modes.
2733 Property* property = expr->expression()->AsProperty();
2734 Register object = VisitForRegisterValue(property->obj());
2735 VisitForAccumulatorValue(property->key());
2736 builder()->Delete(object, language_mode());
2737 } else if (expr->expression()->IsVariableProxy()) {
2738 // Delete of an unqualified identifier is allowed in sloppy mode but is
2739 // not allowed in strict mode. Deleting 'this' is allowed in both modes.
2740 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2741 Variable* variable = proxy->var();
2742 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
2743 switch (variable->location()) {
2744 case VariableLocation::GLOBAL:
2745 case VariableLocation::UNALLOCATED: {
2746 // Global var, let, const or variables not explicitly declared.
2747 Register native_context = register_allocator()->NewRegister();
2748 Register global_object = register_allocator()->NewRegister();
2749 builder()
2750 ->LoadContextSlot(execution_context()->reg(),
2751 Context::NATIVE_CONTEXT_INDEX)
2752 .StoreAccumulatorInRegister(native_context)
2753 .LoadContextSlot(native_context, Context::EXTENSION_INDEX)
2754 .StoreAccumulatorInRegister(global_object)
2755 .LoadLiteral(variable->name())
2756 .Delete(global_object, language_mode());
2757 break;
2758 }
2759 case VariableLocation::PARAMETER:
2760 case VariableLocation::LOCAL:
2761 case VariableLocation::CONTEXT: {
2762 // Deleting local var/let/const, context variables, and arguments
2763 // does not have any effect.
2764 if (variable->HasThisName(isolate())) {
2765 builder()->LoadTrue();
2766 } else {
2767 builder()->LoadFalse();
2768 }
2769 break;
2770 }
2771 case VariableLocation::LOOKUP: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002772 Register name_reg = register_allocator()->NewRegister();
2773 builder()
2774 ->LoadLiteral(variable->name())
2775 .StoreAccumulatorInRegister(name_reg)
2776 .CallRuntime(Runtime::kDeleteLookupSlot, name_reg, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002777 break;
2778 }
2779 default:
2780 UNREACHABLE();
2781 }
2782 } else {
2783 // Delete of an unresolvable reference returns true.
2784 VisitForEffect(expr->expression());
2785 builder()->LoadTrue();
2786 }
2787 execution_result()->SetResultInAccumulator();
2788}
2789
2790
2791void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
2792 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2793
2794 // Left-hand side can only be a property, a global or a variable slot.
2795 Property* property = expr->expression()->AsProperty();
2796 LhsKind assign_type = Property::GetAssignType(property);
2797
2798 // TODO(rmcilroy): Set is_postfix to false if visiting for effect.
2799 bool is_postfix = expr->is_postfix();
2800
2801 // Evaluate LHS expression and get old value.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002802 Register object, home_object, key, old_value, value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002803 Handle<String> name;
2804 switch (assign_type) {
2805 case VARIABLE: {
2806 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2807 VisitVariableLoadForAccumulatorValue(proxy->var(),
2808 proxy->VariableFeedbackSlot());
2809 break;
2810 }
2811 case NAMED_PROPERTY: {
2812 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002813 object = VisitForRegisterValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002814 name = property->key()->AsLiteral()->AsPropertyName();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002815 builder()->LoadNamedProperty(object, name, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002816 break;
2817 }
2818 case KEYED_PROPERTY: {
2819 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002820 object = VisitForRegisterValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002821 // Use visit for accumulator here since we need the key in the accumulator
2822 // for the LoadKeyedProperty.
2823 key = register_allocator()->NewRegister();
2824 VisitForAccumulatorValue(property->key());
2825 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002826 object, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002827 break;
2828 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002829 case NAMED_SUPER_PROPERTY: {
2830 register_allocator()->PrepareForConsecutiveAllocations(4);
2831 object = register_allocator()->NextConsecutiveRegister();
2832 home_object = register_allocator()->NextConsecutiveRegister();
2833 key = register_allocator()->NextConsecutiveRegister();
2834 value = register_allocator()->NextConsecutiveRegister();
2835 SuperPropertyReference* super_property =
2836 property->obj()->AsSuperPropertyReference();
2837 VisitForRegisterValue(super_property->this_var(), object);
2838 VisitForRegisterValue(super_property->home_object(), home_object);
2839 builder()
2840 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2841 .StoreAccumulatorInRegister(key);
2842 BuildNamedSuperPropertyLoad(object, home_object, key);
2843 break;
2844 }
2845 case KEYED_SUPER_PROPERTY: {
2846 register_allocator()->PrepareForConsecutiveAllocations(4);
2847 object = register_allocator()->NextConsecutiveRegister();
2848 home_object = register_allocator()->NextConsecutiveRegister();
2849 key = register_allocator()->NextConsecutiveRegister();
2850 value = register_allocator()->NextConsecutiveRegister();
2851 builder()->StoreAccumulatorInRegister(value);
2852 SuperPropertyReference* super_property =
2853 property->obj()->AsSuperPropertyReference();
2854 VisitForRegisterValue(super_property->this_var(), object);
2855 VisitForRegisterValue(super_property->home_object(), home_object);
2856 VisitForRegisterValue(property->key(), key);
2857 BuildKeyedSuperPropertyLoad(object, home_object, key);
2858 break;
2859 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002860 }
2861
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002862 // Save result for postfix expressions.
2863 if (is_postfix) {
2864 old_value = register_allocator()->outer()->NewRegister();
Ben Murdochc5610432016-08-08 18:44:38 +01002865
2866 // Convert old value into a number before saving it.
2867 builder()->CastAccumulatorToNumber().StoreAccumulatorInRegister(old_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002868 }
2869
2870 // Perform +1/-1 operation.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002871 builder()->CountOperation(expr->binary_op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002872
2873 // Store the value.
Ben Murdochda12d292016-06-02 14:46:10 +01002874 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002875 FeedbackVectorSlot feedback_slot = expr->CountSlot();
2876 switch (assign_type) {
2877 case VARIABLE: {
2878 Variable* variable = expr->expression()->AsVariableProxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002879 VisitVariableAssignment(variable, expr->op(), feedback_slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002880 break;
2881 }
2882 case NAMED_PROPERTY: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002883 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002884 language_mode());
2885 break;
2886 }
2887 case KEYED_PROPERTY: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002888 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002889 language_mode());
2890 break;
2891 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002892 case NAMED_SUPER_PROPERTY: {
2893 builder()->StoreAccumulatorInRegister(value);
2894 BuildNamedSuperPropertyStore(object, home_object, key, value);
2895 break;
2896 }
2897 case KEYED_SUPER_PROPERTY: {
2898 builder()->StoreAccumulatorInRegister(value);
2899 BuildKeyedSuperPropertyStore(object, home_object, key, value);
2900 break;
2901 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002902 }
2903
2904 // Restore old value for postfix expressions.
2905 if (is_postfix) {
2906 execution_result()->SetResultInRegister(old_value);
2907 } else {
2908 execution_result()->SetResultInAccumulator();
2909 }
2910}
2911
2912
2913void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
2914 switch (binop->op()) {
2915 case Token::COMMA:
2916 VisitCommaExpression(binop);
2917 break;
2918 case Token::OR:
2919 VisitLogicalOrExpression(binop);
2920 break;
2921 case Token::AND:
2922 VisitLogicalAndExpression(binop);
2923 break;
2924 default:
2925 VisitArithmeticExpression(binop);
2926 break;
2927 }
2928}
2929
2930
2931void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2932 Register lhs = VisitForRegisterValue(expr->left());
2933 VisitForAccumulatorValue(expr->right());
Ben Murdochda12d292016-06-02 14:46:10 +01002934 builder()->SetExpressionPosition(expr);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002935 builder()->CompareOperation(expr->op(), lhs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002936 execution_result()->SetResultInAccumulator();
2937}
2938
2939
2940void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
2941 Register lhs = VisitForRegisterValue(expr->left());
2942 VisitForAccumulatorValue(expr->right());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002943 builder()->BinaryOperation(expr->op(), lhs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002944 execution_result()->SetResultInAccumulator();
2945}
2946
2947
2948void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
2949
2950
2951void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
2952 UNREACHABLE();
2953}
2954
2955
2956void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
2957 execution_result()->SetResultInRegister(Register::function_closure());
2958}
2959
2960
2961void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002962 // Handled by VisitCall().
2963 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002964}
2965
2966
2967void BytecodeGenerator::VisitSuperPropertyReference(
2968 SuperPropertyReference* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002969 builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0);
2970 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002971}
2972
2973
2974void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
2975 VisitForEffect(binop->left());
2976 Visit(binop->right());
2977}
2978
2979
2980void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
2981 Expression* left = binop->left();
2982 Expression* right = binop->right();
2983
2984 // Short-circuit evaluation- If it is known that left is always true,
2985 // no need to visit right
2986 if (left->ToBooleanIsTrue()) {
2987 VisitForAccumulatorValue(left);
2988 } else {
2989 BytecodeLabel end_label;
2990 VisitForAccumulatorValue(left);
2991 builder()->JumpIfTrue(&end_label);
2992 VisitForAccumulatorValue(right);
2993 builder()->Bind(&end_label);
2994 }
2995 execution_result()->SetResultInAccumulator();
2996}
2997
2998
2999void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
3000 Expression* left = binop->left();
3001 Expression* right = binop->right();
3002
3003 // Short-circuit evaluation- If it is known that left is always false,
3004 // no need to visit right
3005 if (left->ToBooleanIsFalse()) {
3006 VisitForAccumulatorValue(left);
3007 } else {
3008 BytecodeLabel end_label;
3009 VisitForAccumulatorValue(left);
3010 builder()->JumpIfFalse(&end_label);
3011 VisitForAccumulatorValue(right);
3012 builder()->Bind(&end_label);
3013 }
3014 execution_result()->SetResultInAccumulator();
3015}
3016
3017
Ben Murdoch097c5b22016-05-18 11:27:45 +01003018void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003019 Visit(expr->expression());
3020}
3021
3022
3023void BytecodeGenerator::VisitNewLocalFunctionContext() {
3024 AccumulatorResultScope accumulator_execution_result(this);
3025 Scope* scope = this->scope();
3026
3027 // Allocate a new local context.
3028 if (scope->is_script_scope()) {
3029 RegisterAllocationScope register_scope(this);
3030 Register closure = register_allocator()->NewRegister();
3031 Register scope_info = register_allocator()->NewRegister();
3032 DCHECK(Register::AreContiguous(closure, scope_info));
3033 builder()
3034 ->LoadAccumulatorWithRegister(Register::function_closure())
3035 .StoreAccumulatorInRegister(closure)
3036 .LoadLiteral(scope->GetScopeInfo(isolate()))
3037 .StoreAccumulatorInRegister(scope_info)
3038 .CallRuntime(Runtime::kNewScriptContext, closure, 2);
3039 } else {
3040 builder()->CallRuntime(Runtime::kNewFunctionContext,
3041 Register::function_closure(), 1);
3042 }
3043 execution_result()->SetResultInAccumulator();
3044}
3045
3046
3047void BytecodeGenerator::VisitBuildLocalActivationContext() {
3048 Scope* scope = this->scope();
3049
3050 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
3051 Variable* variable = scope->receiver();
3052 Register receiver(builder()->Parameter(0));
3053 // Context variable (at bottom of the context chain).
3054 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3055 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
3056 execution_context()->reg(), variable->index());
3057 }
3058
3059 // Copy parameters into context if necessary.
3060 int num_parameters = scope->num_parameters();
3061 for (int i = 0; i < num_parameters; i++) {
3062 Variable* variable = scope->parameter(i);
3063 if (!variable->IsContextSlot()) continue;
3064
3065 // The parameter indices are shifted by 1 (receiver is variable
3066 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
3067 Register parameter(builder()->Parameter(i + 1));
3068 // Context variable (at bottom of the context chain).
3069 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3070 builder()->LoadAccumulatorWithRegister(parameter)
3071 .StoreContextSlot(execution_context()->reg(), variable->index());
3072 }
3073}
3074
3075
3076void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
3077 AccumulatorResultScope accumulator_execution_result(this);
3078 DCHECK(scope->is_block_scope());
3079
3080 // Allocate a new local block context.
3081 register_allocator()->PrepareForConsecutiveAllocations(2);
3082 Register scope_info = register_allocator()->NextConsecutiveRegister();
3083 Register closure = register_allocator()->NextConsecutiveRegister();
3084
3085 builder()
3086 ->LoadLiteral(scope->GetScopeInfo(isolate()))
3087 .StoreAccumulatorInRegister(scope_info);
3088 VisitFunctionClosureForContext();
3089 builder()
3090 ->StoreAccumulatorInRegister(closure)
3091 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2);
3092 execution_result()->SetResultInAccumulator();
3093}
3094
Ben Murdoch097c5b22016-05-18 11:27:45 +01003095void BytecodeGenerator::VisitNewLocalWithContext() {
3096 AccumulatorResultScope accumulator_execution_result(this);
3097
3098 register_allocator()->PrepareForConsecutiveAllocations(2);
3099 Register extension_object = register_allocator()->NextConsecutiveRegister();
3100 Register closure = register_allocator()->NextConsecutiveRegister();
3101
3102 builder()->StoreAccumulatorInRegister(extension_object);
3103 VisitFunctionClosureForContext();
3104 builder()->StoreAccumulatorInRegister(closure).CallRuntime(
3105 Runtime::kPushWithContext, extension_object, 2);
3106 execution_result()->SetResultInAccumulator();
3107}
3108
3109void BytecodeGenerator::VisitNewLocalCatchContext(Variable* variable) {
3110 AccumulatorResultScope accumulator_execution_result(this);
3111 DCHECK(variable->IsContextSlot());
3112
3113 // Allocate a new local block context.
3114 register_allocator()->PrepareForConsecutiveAllocations(3);
3115 Register name = register_allocator()->NextConsecutiveRegister();
3116 Register exception = register_allocator()->NextConsecutiveRegister();
3117 Register closure = register_allocator()->NextConsecutiveRegister();
3118
3119 builder()
3120 ->StoreAccumulatorInRegister(exception)
3121 .LoadLiteral(variable->name())
3122 .StoreAccumulatorInRegister(name);
3123 VisitFunctionClosureForContext();
3124 builder()->StoreAccumulatorInRegister(closure).CallRuntime(
3125 Runtime::kPushCatchContext, name, 3);
3126 execution_result()->SetResultInAccumulator();
3127}
3128
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003129
3130void BytecodeGenerator::VisitObjectLiteralAccessor(
3131 Register home_object, ObjectLiteralProperty* property, Register value_out) {
3132 // TODO(rmcilroy): Replace value_out with VisitForRegister();
3133 if (property == nullptr) {
3134 builder()->LoadNull().StoreAccumulatorInRegister(value_out);
3135 } else {
3136 VisitForAccumulatorValue(property->value());
3137 builder()->StoreAccumulatorInRegister(value_out);
3138 VisitSetHomeObject(value_out, home_object, property);
3139 }
3140}
3141
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003142void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
3143 ObjectLiteralProperty* property,
3144 int slot_number) {
3145 Expression* expr = property->value();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003146 if (FunctionLiteral::NeedsHomeObject(expr)) {
3147 Handle<Name> name = isolate()->factory()->home_object_symbol();
3148 FeedbackVectorSlot slot = property->GetSlot(slot_number);
3149 builder()
3150 ->LoadAccumulatorWithRegister(home_object)
3151 .StoreNamedProperty(value, name, feedback_index(slot), language_mode());
3152 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003153}
3154
3155
3156void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
3157 if (variable == nullptr) return;
3158
3159 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
3160
3161 // Allocate and initialize a new arguments object and assign to the
3162 // {arguments} variable.
3163 CreateArgumentsType type =
3164 is_strict(language_mode()) || !info()->has_simple_parameters()
3165 ? CreateArgumentsType::kUnmappedArguments
3166 : CreateArgumentsType::kMappedArguments;
3167 builder()->CreateArguments(type);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003168 VisitVariableAssignment(variable, Token::ASSIGN,
3169 FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003170}
3171
Ben Murdoch097c5b22016-05-18 11:27:45 +01003172void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
3173 if (rest == nullptr) return;
3174
3175 // Allocate and initialize a new rest parameter and assign to the {rest}
3176 // variable.
3177 builder()->CreateArguments(CreateArgumentsType::kRestParameter);
3178 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3179 VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid());
3180}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003181
3182void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
3183 if (variable == nullptr) return;
3184
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003185 // Store the closure we were called with in the given variable.
3186 builder()->LoadAccumulatorWithRegister(Register::function_closure());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003187 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003188}
3189
3190
3191void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
3192 if (variable == nullptr) return;
3193
3194 // Store the new target we were called with in the given variable.
3195 builder()->LoadAccumulatorWithRegister(Register::new_target());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003196 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003197}
3198
3199
3200void BytecodeGenerator::VisitFunctionClosureForContext() {
3201 AccumulatorResultScope accumulator_execution_result(this);
3202 Scope* closure_scope = execution_context()->scope()->ClosureScope();
3203 if (closure_scope->is_script_scope() ||
3204 closure_scope->is_module_scope()) {
3205 // Contexts nested in the native context have a canonical empty function as
3206 // their closure, not the anonymous closure containing the global code.
3207 Register native_context = register_allocator()->NewRegister();
3208 builder()
3209 ->LoadContextSlot(execution_context()->reg(),
3210 Context::NATIVE_CONTEXT_INDEX)
3211 .StoreAccumulatorInRegister(native_context)
3212 .LoadContextSlot(native_context, Context::CLOSURE_INDEX);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003213 } else if (closure_scope->is_eval_scope()) {
3214 // Contexts created by a call to eval have the same closure as the
3215 // context calling eval, not the anonymous closure containing the eval
3216 // code. Fetch it from the context.
3217 builder()->LoadContextSlot(execution_context()->reg(),
3218 Context::CLOSURE_INDEX);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003219 } else {
3220 DCHECK(closure_scope->is_function_scope());
3221 builder()->LoadAccumulatorWithRegister(Register::function_closure());
3222 }
3223 execution_result()->SetResultInAccumulator();
3224}
3225
3226
3227// Visits the expression |expr| and places the result in the accumulator.
3228void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
3229 AccumulatorResultScope accumulator_scope(this);
3230 Visit(expr);
3231}
3232
Ben Murdoch097c5b22016-05-18 11:27:45 +01003233void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
3234 if (expr == nullptr) {
3235 builder()->LoadTheHole();
3236 } else {
3237 VisitForAccumulatorValue(expr);
3238 }
3239}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003240
3241// Visits the expression |expr| and discards the result.
3242void BytecodeGenerator::VisitForEffect(Expression* expr) {
3243 EffectResultScope effect_scope(this);
3244 Visit(expr);
3245}
3246
3247
3248// Visits the expression |expr| and returns the register containing
3249// the expression result.
3250Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
3251 RegisterResultScope register_scope(this);
3252 Visit(expr);
3253 return register_scope.ResultRegister();
3254}
3255
Ben Murdoch097c5b22016-05-18 11:27:45 +01003256// Visits the expression |expr| and stores the expression result in
3257// |destination|.
3258void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
3259 Register destination) {
3260 AccumulatorResultScope register_scope(this);
3261 Visit(expr);
3262 builder()->StoreAccumulatorInRegister(destination);
3263}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003264
Ben Murdoch097c5b22016-05-18 11:27:45 +01003265void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
3266 ContextScope context_scope(this, scope);
3267 DCHECK(scope->declarations()->is_empty());
3268 Visit(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003269}
3270
3271
3272LanguageMode BytecodeGenerator::language_mode() const {
Ben Murdochda12d292016-06-02 14:46:10 +01003273 return execution_context()->scope()->language_mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003274}
3275
3276
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003277int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
Ben Murdochda12d292016-06-02 14:46:10 +01003278 return info()->shared_info()->feedback_vector()->GetIndex(slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003279}
3280
3281} // namespace interpreter
3282} // namespace internal
3283} // namespace v8