blob: b7cfd49497d248df1d733282d2f2149e06951410 [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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020// Scoped class tracking context objects created by the visitor. Represents
21// mutations of the context chain within the function body, allowing pushing and
22// popping of the current {context_register} during visitation.
23class BytecodeGenerator::ContextScope BASE_EMBEDDED {
24 public:
25 ContextScope(BytecodeGenerator* generator, Scope* scope,
26 bool should_pop_context = true)
27 : generator_(generator),
28 scope_(scope),
29 outer_(generator_->execution_context()),
Ben Murdoch097c5b22016-05-18 11:27:45 +010030 register_(Register::current_context()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031 depth_(0),
32 should_pop_context_(should_pop_context) {
33 if (outer_) {
34 depth_ = outer_->depth_ + 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +010035
36 // Push the outer context into a new context register.
37 Register outer_context_reg(builder()->first_context_register().index() +
38 outer_->depth_);
39 outer_->set_register(outer_context_reg);
40 generator_->builder()->PushContext(outer_context_reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041 }
42 generator_->set_execution_context(this);
43 }
44
45 ~ContextScope() {
46 if (outer_ && should_pop_context_) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010047 DCHECK_EQ(register_.index(), Register::current_context().index());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048 generator_->builder()->PopContext(outer_->reg());
Ben Murdoch097c5b22016-05-18 11:27:45 +010049 outer_->set_register(register_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 }
51 generator_->set_execution_context(outer_);
52 }
53
54 // Returns the depth of the given |scope| for the current execution context.
55 int ContextChainDepth(Scope* scope) {
56 return scope_->ContextChainLength(scope);
57 }
58
59 // Returns the execution context at |depth| in the current context chain if it
60 // is a function local execution context, otherwise returns nullptr.
61 ContextScope* Previous(int depth) {
62 if (depth > depth_) {
63 return nullptr;
64 }
65
66 ContextScope* previous = this;
67 for (int i = depth; i > 0; --i) {
68 previous = previous->outer_;
69 }
70 return previous;
71 }
72
73 Scope* scope() const { return scope_; }
74 Register reg() const { return register_; }
Ben Murdochda12d292016-06-02 14:46:10 +010075 bool ShouldPopContext() { return should_pop_context_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076
77 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +010078 const BytecodeArrayBuilder* builder() const { return generator_->builder(); }
79
80 void set_register(Register reg) { register_ = reg; }
81
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 BytecodeGenerator* generator_;
83 Scope* scope_;
84 ContextScope* outer_;
85 Register register_;
86 int depth_;
87 bool should_pop_context_;
88};
89
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090// Scoped class for tracking control statements entered by the
91// visitor. The pattern derives AstGraphBuilder::ControlScope.
92class BytecodeGenerator::ControlScope BASE_EMBEDDED {
93 public:
94 explicit ControlScope(BytecodeGenerator* generator)
Ben Murdoch097c5b22016-05-18 11:27:45 +010095 : generator_(generator), outer_(generator->execution_control()),
96 context_(generator->execution_context()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097 generator_->set_execution_control(this);
98 }
99 virtual ~ControlScope() { generator_->set_execution_control(outer()); }
100
101 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); }
102 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100103 void ReturnAccumulator() { PerformCommand(CMD_RETURN, nullptr); }
104 void ReThrowAccumulator() { PerformCommand(CMD_RETHROW, nullptr); }
105
106 class DeferredCommands;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000107
108 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100109 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_RETHROW };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000110 void PerformCommand(Command command, Statement* statement);
111 virtual bool Execute(Command command, Statement* statement) = 0;
112
113 BytecodeGenerator* generator() const { return generator_; }
114 ControlScope* outer() const { return outer_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100115 ContextScope* context() const { return context_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000116
117 private:
118 BytecodeGenerator* generator_;
119 ControlScope* outer_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100120 ContextScope* context_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000121
122 DISALLOW_COPY_AND_ASSIGN(ControlScope);
123};
124
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125// Helper class for a try-finally control scope. It can record intercepted
126// control-flow commands that cause entry into a finally-block, and re-apply
127// them after again leaving that block. Special tokens are used to identify
128// paths going through the finally-block to dispatch after leaving the block.
129class BytecodeGenerator::ControlScope::DeferredCommands final {
130 public:
131 DeferredCommands(BytecodeGenerator* generator, Register token_register,
132 Register result_register)
133 : generator_(generator),
134 deferred_(generator->zone()),
135 token_register_(token_register),
136 result_register_(result_register) {}
137
138 // One recorded control-flow command.
139 struct Entry {
140 Command command; // The command type being applied on this path.
141 Statement* statement; // The target statement for the command or {nullptr}.
142 int token; // A token identifying this particular path.
143 };
144
145 // Records a control-flow command while entering the finally-block. This also
146 // generates a new dispatch token that identifies one particular path. This
147 // expects the result to be in the accumulator.
148 void RecordCommand(Command command, Statement* statement) {
149 int token = static_cast<int>(deferred_.size());
150 deferred_.push_back({command, statement, token});
151
152 builder()->StoreAccumulatorInRegister(result_register_);
153 builder()->LoadLiteral(Smi::FromInt(token));
154 builder()->StoreAccumulatorInRegister(token_register_);
155 }
156
157 // Records the dispatch token to be used to identify the re-throw path when
158 // the finally-block has been entered through the exception handler. This
159 // expects the exception to be in the accumulator.
160 void RecordHandlerReThrowPath() {
161 // The accumulator contains the exception object.
162 RecordCommand(CMD_RETHROW, nullptr);
163 }
164
165 // Records the dispatch token to be used to identify the implicit fall-through
166 // path at the end of a try-block into the corresponding finally-block.
167 void RecordFallThroughPath() {
168 builder()->LoadLiteral(Smi::FromInt(-1));
169 builder()->StoreAccumulatorInRegister(token_register_);
170 }
171
172 // Applies all recorded control-flow commands after the finally-block again.
173 // This generates a dynamic dispatch on the token from the entry point.
174 void ApplyDeferredCommands() {
175 // The fall-through path is covered by the default case, hence +1 here.
176 SwitchBuilder dispatch(builder(), static_cast<int>(deferred_.size() + 1));
177 for (size_t i = 0; i < deferred_.size(); ++i) {
178 Entry& entry = deferred_[i];
179 builder()->LoadLiteral(Smi::FromInt(entry.token));
180 builder()->CompareOperation(Token::EQ_STRICT, token_register_);
181 dispatch.Case(static_cast<int>(i));
182 }
183 dispatch.DefaultAt(static_cast<int>(deferred_.size()));
184 for (size_t i = 0; i < deferred_.size(); ++i) {
185 Entry& entry = deferred_[i];
186 dispatch.SetCaseTarget(static_cast<int>(i));
187 builder()->LoadAccumulatorWithRegister(result_register_);
188 execution_control()->PerformCommand(entry.command, entry.statement);
189 }
190 dispatch.SetCaseTarget(static_cast<int>(deferred_.size()));
191 }
192
193 BytecodeArrayBuilder* builder() { return generator_->builder(); }
194 ControlScope* execution_control() { return generator_->execution_control(); }
195
196 private:
197 BytecodeGenerator* generator_;
198 ZoneVector<Entry> deferred_;
199 Register token_register_;
200 Register result_register_;
201};
202
Ben Murdoch097c5b22016-05-18 11:27:45 +0100203// Scoped class for dealing with control flow reaching the function level.
204class BytecodeGenerator::ControlScopeForTopLevel final
205 : public BytecodeGenerator::ControlScope {
206 public:
207 explicit ControlScopeForTopLevel(BytecodeGenerator* generator)
208 : ControlScope(generator) {}
209
210 protected:
211 bool Execute(Command command, Statement* statement) override {
212 switch (command) {
Ben Murdochda12d292016-06-02 14:46:10 +0100213 case CMD_BREAK: // We should never see break/continue in top-level.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100214 case CMD_CONTINUE:
Ben Murdochda12d292016-06-02 14:46:10 +0100215 UNREACHABLE();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100216 case CMD_RETURN:
217 generator()->builder()->Return();
218 return true;
219 case CMD_RETHROW:
220 generator()->builder()->ReThrow();
221 return true;
222 }
223 return false;
224 }
225};
226
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227// Scoped class for enabling break inside blocks and switch blocks.
228class BytecodeGenerator::ControlScopeForBreakable final
229 : public BytecodeGenerator::ControlScope {
230 public:
231 ControlScopeForBreakable(BytecodeGenerator* generator,
232 BreakableStatement* statement,
233 BreakableControlFlowBuilder* control_builder)
234 : ControlScope(generator),
235 statement_(statement),
236 control_builder_(control_builder) {}
237
238 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100239 bool Execute(Command command, Statement* statement) override {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 if (statement != statement_) return false;
241 switch (command) {
242 case CMD_BREAK:
243 control_builder_->Break();
244 return true;
245 case CMD_CONTINUE:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100246 case CMD_RETURN:
247 case CMD_RETHROW:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 break;
249 }
250 return false;
251 }
252
253 private:
254 Statement* statement_;
255 BreakableControlFlowBuilder* control_builder_;
256};
257
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258// Scoped class for enabling 'break' and 'continue' in iteration
259// constructs, e.g. do...while, while..., for...
260class BytecodeGenerator::ControlScopeForIteration final
261 : public BytecodeGenerator::ControlScope {
262 public:
263 ControlScopeForIteration(BytecodeGenerator* generator,
264 IterationStatement* statement,
265 LoopBuilder* loop_builder)
266 : ControlScope(generator),
267 statement_(statement),
268 loop_builder_(loop_builder) {}
269
270 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100271 bool Execute(Command command, Statement* statement) override {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 if (statement != statement_) return false;
273 switch (command) {
274 case CMD_BREAK:
275 loop_builder_->Break();
276 return true;
277 case CMD_CONTINUE:
278 loop_builder_->Continue();
279 return true;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100280 case CMD_RETURN:
281 case CMD_RETHROW:
282 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000283 }
284 return false;
285 }
286
287 private:
288 Statement* statement_;
289 LoopBuilder* loop_builder_;
290};
291
Ben Murdoch097c5b22016-05-18 11:27:45 +0100292// Scoped class for enabling 'throw' in try-catch constructs.
293class BytecodeGenerator::ControlScopeForTryCatch final
294 : public BytecodeGenerator::ControlScope {
295 public:
296 ControlScopeForTryCatch(BytecodeGenerator* generator,
297 TryCatchBuilder* try_catch_builder)
298 : ControlScope(generator) {
299 generator->try_catch_nesting_level_++;
300 }
301 virtual ~ControlScopeForTryCatch() {
302 generator()->try_catch_nesting_level_--;
303 }
304
305 protected:
306 bool Execute(Command command, Statement* statement) override {
307 switch (command) {
308 case CMD_BREAK:
309 case CMD_CONTINUE:
310 case CMD_RETURN:
311 break;
312 case CMD_RETHROW:
313 generator()->builder()->ReThrow();
314 return true;
315 }
316 return false;
317 }
318};
319
Ben Murdoch097c5b22016-05-18 11:27:45 +0100320// Scoped class for enabling control flow through try-finally constructs.
321class BytecodeGenerator::ControlScopeForTryFinally final
322 : public BytecodeGenerator::ControlScope {
323 public:
324 ControlScopeForTryFinally(BytecodeGenerator* generator,
325 TryFinallyBuilder* try_finally_builder,
326 DeferredCommands* commands)
327 : ControlScope(generator),
328 try_finally_builder_(try_finally_builder),
329 commands_(commands) {
330 generator->try_finally_nesting_level_++;
331 }
332 virtual ~ControlScopeForTryFinally() {
333 generator()->try_finally_nesting_level_--;
334 }
335
336 protected:
337 bool Execute(Command command, Statement* statement) override {
338 switch (command) {
339 case CMD_BREAK:
340 case CMD_CONTINUE:
341 case CMD_RETURN:
342 case CMD_RETHROW:
343 commands_->RecordCommand(command, statement);
344 try_finally_builder_->LeaveTry();
345 return true;
346 }
347 return false;
348 }
349
350 private:
351 TryFinallyBuilder* try_finally_builder_;
352 DeferredCommands* commands_;
353};
354
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355void BytecodeGenerator::ControlScope::PerformCommand(Command command,
356 Statement* statement) {
357 ControlScope* current = this;
Ben Murdochda12d292016-06-02 14:46:10 +0100358 ContextScope* context = generator()->execution_context();
359 // Pop context to the expected depth but do not pop the outermost context.
360 if (context != current->context() && context->ShouldPopContext()) {
361 generator()->builder()->PopContext(current->context()->reg());
362 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 do {
Ben Murdochda12d292016-06-02 14:46:10 +0100364 if (current->Execute(command, statement)) {
365 return;
366 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000367 current = current->outer();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100368 if (current->context() != context) {
369 // Pop context to the expected depth.
370 // TODO(rmcilroy): Only emit a single context pop.
371 generator()->builder()->PopContext(current->context()->reg());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100372 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000373 } while (current != nullptr);
374 UNREACHABLE();
375}
376
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000377class BytecodeGenerator::RegisterAllocationScope {
378 public:
379 explicit RegisterAllocationScope(BytecodeGenerator* generator)
380 : generator_(generator),
381 outer_(generator->register_allocator()),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100382 allocator_(builder()->zone(),
383 builder()->temporary_register_allocator()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 generator_->set_register_allocator(this);
385 }
386
387 virtual ~RegisterAllocationScope() {
388 generator_->set_register_allocator(outer_);
389 }
390
391 Register NewRegister() {
392 RegisterAllocationScope* current_scope = generator()->register_allocator();
393 if ((current_scope == this) ||
394 (current_scope->outer() == this &&
395 !current_scope->allocator_.HasConsecutiveAllocations())) {
396 // Regular case - Allocating registers in current or outer context.
397 // VisitForRegisterValue allocates register in outer context.
398 return allocator_.NewRegister();
399 } else {
400 // If it is required to allocate a register other than current or outer
401 // scopes, allocate a new temporary register. It might be expensive to
402 // walk the full context chain and compute the list of consecutive
403 // reservations in the innerscopes.
404 UNIMPLEMENTED();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100405 return Register::invalid_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000406 }
407 }
408
Ben Murdoch097c5b22016-05-18 11:27:45 +0100409 void PrepareForConsecutiveAllocations(int count) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000410 allocator_.PrepareForConsecutiveAllocations(count);
411 }
412
413 Register NextConsecutiveRegister() {
414 return allocator_.NextConsecutiveRegister();
415 }
416
417 bool RegisterIsAllocatedInThisScope(Register reg) const {
418 return allocator_.RegisterIsAllocatedInThisScope(reg);
419 }
420
421 RegisterAllocationScope* outer() const { return outer_; }
422
423 private:
424 BytecodeGenerator* generator() const { return generator_; }
425 BytecodeArrayBuilder* builder() const { return generator_->builder(); }
426
427 BytecodeGenerator* generator_;
428 RegisterAllocationScope* outer_;
429 BytecodeRegisterAllocator allocator_;
430
431 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope);
432};
433
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434// Scoped base class for determining where the result of an expression
435// is stored.
436class BytecodeGenerator::ExpressionResultScope {
437 public:
438 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
439 : generator_(generator),
440 kind_(kind),
441 outer_(generator->execution_result()),
442 allocator_(generator),
443 result_identified_(false) {
444 generator_->set_execution_result(this);
445 }
446
447 virtual ~ExpressionResultScope() {
448 generator_->set_execution_result(outer_);
Ben Murdochda12d292016-06-02 14:46:10 +0100449 DCHECK(result_identified() || generator_->HasStackOverflow());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 }
451
452 bool IsEffect() const { return kind_ == Expression::kEffect; }
453 bool IsValue() const { return kind_ == Expression::kValue; }
454
455 virtual void SetResultInAccumulator() = 0;
456 virtual void SetResultInRegister(Register reg) = 0;
457
458 protected:
459 ExpressionResultScope* outer() const { return outer_; }
460 BytecodeArrayBuilder* builder() const { return generator_->builder(); }
Ben Murdochda12d292016-06-02 14:46:10 +0100461 BytecodeGenerator* generator() const { return generator_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000462 const RegisterAllocationScope* allocator() const { return &allocator_; }
463
464 void set_result_identified() {
465 DCHECK(!result_identified());
466 result_identified_ = true;
467 }
468
469 bool result_identified() const { return result_identified_; }
470
471 private:
472 BytecodeGenerator* generator_;
473 Expression::Context kind_;
474 ExpressionResultScope* outer_;
475 RegisterAllocationScope allocator_;
476 bool result_identified_;
477
478 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
479};
480
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000481// Scoped class used when the result of the current expression is not
482// expected to produce a result.
483class BytecodeGenerator::EffectResultScope final
484 : public ExpressionResultScope {
485 public:
486 explicit EffectResultScope(BytecodeGenerator* generator)
487 : ExpressionResultScope(generator, Expression::kEffect) {
488 set_result_identified();
489 }
490
491 virtual void SetResultInAccumulator() {}
492 virtual void SetResultInRegister(Register reg) {}
493};
494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495// Scoped class used when the result of the current expression to be
496// evaluated should go into the interpreter's accumulator register.
497class BytecodeGenerator::AccumulatorResultScope final
498 : public ExpressionResultScope {
499 public:
500 explicit AccumulatorResultScope(BytecodeGenerator* generator)
501 : ExpressionResultScope(generator, Expression::kValue) {}
502
503 virtual void SetResultInAccumulator() { set_result_identified(); }
504
505 virtual void SetResultInRegister(Register reg) {
506 builder()->LoadAccumulatorWithRegister(reg);
507 set_result_identified();
508 }
509};
510
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000511// Scoped class used when the result of the current expression to be
512// evaluated should go into an interpreter register.
513class BytecodeGenerator::RegisterResultScope final
514 : public ExpressionResultScope {
515 public:
516 explicit RegisterResultScope(BytecodeGenerator* generator)
517 : ExpressionResultScope(generator, Expression::kValue) {}
518
519 virtual void SetResultInAccumulator() {
520 result_register_ = allocator()->outer()->NewRegister();
521 builder()->StoreAccumulatorInRegister(result_register_);
522 set_result_identified();
523 }
524
525 virtual void SetResultInRegister(Register reg) {
526 DCHECK(builder()->RegisterIsParameterOrLocal(reg) ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100527 (builder()->TemporaryRegisterIsLive(reg) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000528 !allocator()->RegisterIsAllocatedInThisScope(reg)));
529 result_register_ = reg;
530 set_result_identified();
531 }
532
Ben Murdochda12d292016-06-02 14:46:10 +0100533 Register ResultRegister() {
534 if (generator()->HasStackOverflow() && !result_identified()) {
535 SetResultInAccumulator();
536 }
537 return result_register_;
538 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000539
540 private:
541 Register result_register_;
542};
543
Ben Murdochc5610432016-08-08 18:44:38 +0100544BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
545 : isolate_(info->isolate()),
546 zone_(info->zone()),
547 builder_(new (zone()) BytecodeArrayBuilder(
548 info->isolate(), info->zone(), info->num_parameters_including_this(),
549 info->scope()->MaxNestedContextChainLength(),
550 info->scope()->num_stack_slots(), info->literal())),
551 info_(info),
552 scope_(info->scope()),
553 globals_(0, info->zone()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000554 execution_control_(nullptr),
555 execution_context_(nullptr),
556 execution_result_(nullptr),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100557 register_allocator_(nullptr),
Ben Murdochc5610432016-08-08 18:44:38 +0100558 generator_resume_points_(info->literal()->yield_count(), info->zone()),
559 generator_state_(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100560 try_catch_nesting_level_(0),
561 try_finally_nesting_level_(0) {
Ben Murdochc5610432016-08-08 18:44:38 +0100562 InitializeAstVisitor(isolate());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563}
564
Ben Murdochc5610432016-08-08 18:44:38 +0100565Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566 // Initialize the incoming context.
567 ContextScope incoming_context(this, scope(), false);
568
Ben Murdoch097c5b22016-05-18 11:27:45 +0100569 // Initialize control scope.
570 ControlScopeForTopLevel control(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571
Ben Murdochc5610432016-08-08 18:44:38 +0100572 RegisterAllocationScope register_scope(this);
573
Ben Murdoch61f157c2016-09-16 13:49:30 +0100574 if (IsResumableFunction(info()->literal()->kind())) {
Ben Murdochc5610432016-08-08 18:44:38 +0100575 generator_state_ = register_allocator()->NewRegister();
576 VisitGeneratorPrologue();
577 }
578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579 // Build function context only if there are context allocated variables.
580 if (scope()->NeedsContext()) {
581 // Push a new inner context scope for the function.
582 VisitNewLocalFunctionContext();
583 ContextScope local_function_context(this, scope(), false);
584 VisitBuildLocalActivationContext();
585 MakeBytecodeBody();
586 } else {
587 MakeBytecodeBody();
588 }
589
Ben Murdochc5610432016-08-08 18:44:38 +0100590 // In generator functions, we may not have visited every yield in the AST
591 // since we skip some obviously dead code. Hence the generated bytecode may
592 // contain jumps to unbound labels (resume points that will never be used).
593 // We bind these now.
594 for (auto& label : generator_resume_points_) {
595 if (!label.is_bound()) builder()->Bind(&label);
596 }
597
Ben Murdochda12d292016-06-02 14:46:10 +0100598 builder()->EnsureReturn();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100599 return builder()->ToBytecodeArray();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600}
601
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000602void BytecodeGenerator::MakeBytecodeBody() {
603 // Build the arguments object if it is used.
604 VisitArgumentsObject(scope()->arguments());
605
Ben Murdoch097c5b22016-05-18 11:27:45 +0100606 // Build rest arguments array if it is used.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000607 int rest_index;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100608 Variable* rest_parameter = scope()->rest_parameter(&rest_index);
609 VisitRestArgumentsArray(rest_parameter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610
611 // Build assignment to {.this_function} variable if it is used.
612 VisitThisFunctionVariable(scope()->this_function_var());
613
614 // Build assignment to {new.target} variable if it is used.
615 VisitNewTargetVariable(scope()->new_target_var());
616
617 // TODO(rmcilroy): Emit tracing call if requested to do so.
618 if (FLAG_trace) {
619 UNIMPLEMENTED();
620 }
621
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000622 // Visit declarations within the function scope.
623 VisitDeclarations(scope()->declarations());
624
Ben Murdoch097c5b22016-05-18 11:27:45 +0100625 // Perform a stack-check before the body.
Ben Murdochc5610432016-08-08 18:44:38 +0100626 builder()->StackCheck(info()->literal()->start_position());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100627
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628 // Visit statements in the function body.
629 VisitStatements(info()->literal()->body());
630}
631
Ben Murdochc5610432016-08-08 18:44:38 +0100632void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index,
633 size_t size,
634 ZoneVector<BytecodeLabel>& targets) {
635 // TODO(neis): Optimize this by using a proper jump table.
636 for (size_t i = start_index; i < start_index + size; i++) {
637 DCHECK(0 <= i && i < targets.size());
638 builder()
639 ->LoadLiteral(Smi::FromInt(static_cast<int>(i)))
640 .CompareOperation(Token::Value::EQ_STRICT, index)
641 .JumpIfTrue(&(targets[i]));
642 }
643
Ben Murdoch61f157c2016-09-16 13:49:30 +0100644 BuildAbort(BailoutReason::kInvalidJumpTableIndex);
Ben Murdochc5610432016-08-08 18:44:38 +0100645}
646
647void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt,
648 LoopBuilder* loop_builder) {
649 // Recall that stmt->yield_count() is always zero inside ordinary
650 // (i.e. non-generator) functions.
651
652 // Collect all labels for generator resume points within the loop (if any) so
653 // that they can be bound to the loop header below. Also create fresh labels
654 // for these resume points, to be used inside the loop.
655 ZoneVector<BytecodeLabel> resume_points_in_loop(zone());
656 size_t first_yield = stmt->first_yield_id();
657 for (size_t id = first_yield; id < first_yield + stmt->yield_count(); id++) {
658 DCHECK(0 <= id && id < generator_resume_points_.size());
659 auto& label = generator_resume_points_[id];
660 resume_points_in_loop.push_back(label);
661 generator_resume_points_[id] = BytecodeLabel();
662 }
663
664 loop_builder->LoopHeader(&resume_points_in_loop);
665
666 if (stmt->yield_count() > 0) {
667 // If we are not resuming, fall through to loop body.
668 // If we are resuming, perform state dispatch.
669 BytecodeLabel not_resuming;
670 builder()
671 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
672 .CompareOperation(Token::Value::EQ, generator_state_)
673 .JumpIfTrue(&not_resuming);
674 BuildIndexedJump(generator_state_, first_yield,
675 stmt->yield_count(), generator_resume_points_);
676 builder()->Bind(&not_resuming);
677 }
678}
679
680void BytecodeGenerator::VisitGeneratorPrologue() {
681 // The generator resume trampoline abuses the new.target register both to
682 // indicate that this is a resume call and to pass in the generator object.
683 // In ordinary calls, new.target is always undefined because generator
684 // functions are non-constructable.
685 Register generator_object = Register::new_target();
686 BytecodeLabel regular_call;
687 builder()
688 ->LoadAccumulatorWithRegister(generator_object)
689 .JumpIfUndefined(&regular_call);
690
691 // This is a resume call. Restore registers and perform state dispatch.
692 // (The current context has already been restored by the trampoline.)
693 builder()
694 ->ResumeGenerator(generator_object)
695 .StoreAccumulatorInRegister(generator_state_);
696 BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(),
697 generator_resume_points_);
698
Ben Murdoch61f157c2016-09-16 13:49:30 +0100699 builder()
700 ->Bind(&regular_call)
701 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
702 .StoreAccumulatorInRegister(generator_state_);
Ben Murdochc5610432016-08-08 18:44:38 +0100703 // This is a regular call. Fall through to the ordinary function prologue,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100704 // after which we will run into the generator object creation and other extra
705 // code inserted by the parser.
Ben Murdochc5610432016-08-08 18:44:38 +0100706}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707
708void BytecodeGenerator::VisitBlock(Block* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100709 // Visit declarations and statements.
710 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
711 VisitNewLocalBlockContext(stmt->scope());
712 ContextScope scope(this, stmt->scope());
713 VisitBlockDeclarationsAndStatements(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000714 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100715 VisitBlockDeclarationsAndStatements(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000716 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100717}
718
Ben Murdoch097c5b22016-05-18 11:27:45 +0100719void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
720 BlockBuilder block_builder(builder());
721 ControlScopeForBreakable execution_control(this, stmt, &block_builder);
722 if (stmt->scope() != nullptr) {
723 VisitDeclarations(stmt->scope()->declarations());
724 }
725 VisitStatements(stmt->statements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000726 if (stmt->labels() != nullptr) block_builder.EndBlock();
727}
728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
730 Variable* variable = decl->proxy()->var();
731 VariableMode mode = decl->mode();
732 // Const and let variables are initialized with the hole so that we can
733 // check that they are only assigned once.
Ben Murdochc5610432016-08-08 18:44:38 +0100734 bool hole_init = mode == CONST || mode == LET;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 switch (variable->location()) {
736 case VariableLocation::GLOBAL:
Ben Murdochc5610432016-08-08 18:44:38 +0100737 case VariableLocation::UNALLOCATED:
738 DCHECK(!variable->binding_needs_init());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000739 globals()->push_back(variable->name());
Ben Murdochc5610432016-08-08 18:44:38 +0100740 globals()->push_back(isolate()->factory()->undefined_value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000741 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000742 case VariableLocation::LOCAL:
743 if (hole_init) {
744 Register destination(variable->index());
745 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
746 }
747 break;
748 case VariableLocation::PARAMETER:
749 if (hole_init) {
750 // The parameter indices are shifted by 1 (receiver is variable
751 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
752 Register destination(builder()->Parameter(variable->index() + 1));
753 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
754 }
755 break;
756 case VariableLocation::CONTEXT:
757 if (hole_init) {
758 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
759 variable->index());
760 }
761 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100762 case VariableLocation::LOOKUP: {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100763 DCHECK_EQ(VAR, mode);
764 DCHECK(!hole_init);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100765
Ben Murdoch61f157c2016-09-16 13:49:30 +0100766 Register name = register_allocator()->NewRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100767
Ben Murdoch097c5b22016-05-18 11:27:45 +0100768 builder()
Ben Murdoch61f157c2016-09-16 13:49:30 +0100769 ->LoadLiteral(variable->name())
770 .StoreAccumulatorInRegister(name)
771 .CallRuntime(Runtime::kDeclareEvalVar, name, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100773 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000774 }
775}
776
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000777void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
778 Variable* variable = decl->proxy()->var();
779 switch (variable->location()) {
780 case VariableLocation::GLOBAL:
781 case VariableLocation::UNALLOCATED: {
782 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
783 decl->fun(), info()->script(), info());
784 // Check for stack-overflow exception.
785 if (function.is_null()) return SetStackOverflow();
786 globals()->push_back(variable->name());
787 globals()->push_back(function);
788 break;
789 }
790 case VariableLocation::PARAMETER:
791 case VariableLocation::LOCAL: {
792 VisitForAccumulatorValue(decl->fun());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100793 DCHECK(variable->mode() == LET || variable->mode() == VAR ||
794 variable->mode() == CONST);
795 VisitVariableAssignment(variable, Token::INIT,
796 FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000797 break;
798 }
799 case VariableLocation::CONTEXT: {
800 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
801 VisitForAccumulatorValue(decl->fun());
802 builder()->StoreContextSlot(execution_context()->reg(),
803 variable->index());
804 break;
805 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100806 case VariableLocation::LOOKUP: {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100807 register_allocator()->PrepareForConsecutiveAllocations(2);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100808 Register name = register_allocator()->NextConsecutiveRegister();
809 Register literal = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100810 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
811
812 VisitForAccumulatorValue(decl->fun());
Ben Murdoch61f157c2016-09-16 13:49:30 +0100813 builder()->StoreAccumulatorInRegister(literal).CallRuntime(
814 Runtime::kDeclareEvalFunction, name, 2);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100815 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 }
817}
818
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000819void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
820 UNIMPLEMENTED();
821}
822
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000823void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
824 UNIMPLEMENTED();
825}
826
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000827void BytecodeGenerator::VisitDeclarations(
828 ZoneList<Declaration*>* declarations) {
829 RegisterAllocationScope register_scope(this);
830 DCHECK(globals()->empty());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100831 for (int i = 0; i < declarations->length(); i++) {
832 RegisterAllocationScope register_scope(this);
833 Visit(declarations->at(i));
834 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 if (globals()->empty()) return;
836 int array_index = 0;
837 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
838 static_cast<int>(globals()->size()), TENURED);
839 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
Ben Murdochc5610432016-08-08 18:44:38 +0100840 int encoded_flags = info()->GetDeclareGlobalsFlags();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000841
842 Register pairs = register_allocator()->NewRegister();
843 builder()->LoadLiteral(data);
844 builder()->StoreAccumulatorInRegister(pairs);
845
846 Register flags = register_allocator()->NewRegister();
847 builder()->LoadLiteral(Smi::FromInt(encoded_flags));
848 builder()->StoreAccumulatorInRegister(flags);
849 DCHECK(flags.index() == pairs.index() + 1);
850
851 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
852 globals()->clear();
853}
854
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000855void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
856 for (int i = 0; i < statements->length(); i++) {
857 // Allocate an outer register allocations scope for the statement.
858 RegisterAllocationScope allocation_scope(this);
859 Statement* stmt = statements->at(i);
860 Visit(stmt);
861 if (stmt->IsJump()) break;
862 }
863}
864
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000865void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100866 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000867 VisitForEffect(stmt->expression());
868}
869
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000870void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
871}
872
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100874 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000875 BytecodeLabel else_label, end_label;
876 if (stmt->condition()->ToBooleanIsTrue()) {
877 // Generate then block unconditionally as always true.
878 Visit(stmt->then_statement());
879 } else if (stmt->condition()->ToBooleanIsFalse()) {
880 // Generate else block unconditionally if it exists.
881 if (stmt->HasElseStatement()) {
882 Visit(stmt->else_statement());
883 }
884 } else {
885 // TODO(oth): If then statement is BreakStatement or
886 // ContinueStatement we can reduce number of generated
887 // jump/jump_ifs here. See BasicLoops test.
888 VisitForAccumulatorValue(stmt->condition());
889 builder()->JumpIfFalse(&else_label);
890 Visit(stmt->then_statement());
891 if (stmt->HasElseStatement()) {
892 builder()->Jump(&end_label);
893 builder()->Bind(&else_label);
894 Visit(stmt->else_statement());
895 } else {
896 builder()->Bind(&else_label);
897 }
898 builder()->Bind(&end_label);
899 }
900}
901
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000902void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
903 SloppyBlockFunctionStatement* stmt) {
904 Visit(stmt->statement());
905}
906
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000907void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100908 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000909 execution_control()->Continue(stmt->target());
910}
911
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000912void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100913 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000914 execution_control()->Break(stmt->target());
915}
916
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000917void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100918 builder()->SetStatementPosition(stmt);
Ben Murdochda12d292016-06-02 14:46:10 +0100919 VisitForAccumulatorValue(stmt->expression());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100920 execution_control()->ReturnAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000921}
922
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000923void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100924 builder()->SetStatementPosition(stmt);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100925 VisitForAccumulatorValue(stmt->expression());
926 builder()->CastAccumulatorToJSObject();
927 VisitNewLocalWithContext();
928 VisitInScope(stmt->statement(), stmt->scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929}
930
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
932 // We need this scope because we visit for register values. We have to
933 // maintain a execution result scope where registers can be allocated.
934 ZoneList<CaseClause*>* clauses = stmt->cases();
935 SwitchBuilder switch_builder(builder(), clauses->length());
936 ControlScopeForBreakable scope(this, stmt, &switch_builder);
937 int default_index = -1;
938
Ben Murdochda12d292016-06-02 14:46:10 +0100939 builder()->SetStatementPosition(stmt);
940
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000941 // Keep the switch value in a register until a case matches.
942 Register tag = VisitForRegisterValue(stmt->tag());
943
944 // Iterate over all cases and create nodes for label comparison.
945 BytecodeLabel done_label;
946 for (int i = 0; i < clauses->length(); i++) {
947 CaseClause* clause = clauses->at(i);
948
949 // The default is not a test, remember index.
950 if (clause->is_default()) {
951 default_index = i;
952 continue;
953 }
954
955 // Perform label comparison as if via '===' with tag.
956 VisitForAccumulatorValue(clause->label());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100957 builder()->CompareOperation(Token::Value::EQ_STRICT, tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000958 switch_builder.Case(i);
959 }
960
961 if (default_index >= 0) {
962 // Emit default jump if there is a default case.
963 switch_builder.DefaultAt(default_index);
964 } else {
965 // Otherwise if we have reached here none of the cases matched, so jump to
966 // done.
967 builder()->Jump(&done_label);
968 }
969
970 // Iterate over all cases and create the case bodies.
971 for (int i = 0; i < clauses->length(); i++) {
972 CaseClause* clause = clauses->at(i);
973 switch_builder.SetCaseTarget(i);
974 VisitStatements(clause->statements());
975 }
976 builder()->Bind(&done_label);
977
978 switch_builder.SetBreakTarget(done_label);
979}
980
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000981void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
982 // Handled entirely in VisitSwitchStatement.
983 UNREACHABLE();
984}
985
Ben Murdoch097c5b22016-05-18 11:27:45 +0100986void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
987 LoopBuilder* loop_builder) {
988 ControlScopeForIteration execution_control(this, stmt, loop_builder);
Ben Murdochc5610432016-08-08 18:44:38 +0100989 builder()->StackCheck(stmt->position());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100990 Visit(stmt->body());
Ben Murdochc5610432016-08-08 18:44:38 +0100991 loop_builder->SetContinueTarget();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100992}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993
994void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
995 LoopBuilder loop_builder(builder());
Ben Murdochc5610432016-08-08 18:44:38 +0100996 VisitIterationHeader(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 if (stmt->cond()->ToBooleanIsFalse()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100998 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 } else if (stmt->cond()->ToBooleanIsTrue()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001000 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 loop_builder.JumpToHeader();
1002 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001003 VisitIterationBody(stmt, &loop_builder);
Ben Murdochda12d292016-06-02 14:46:10 +01001004 builder()->SetExpressionAsStatementPosition(stmt->cond());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 VisitForAccumulatorValue(stmt->cond());
1006 loop_builder.JumpToHeaderIfTrue();
1007 }
1008 loop_builder.EndLoop();
1009}
1010
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001011void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1012 if (stmt->cond()->ToBooleanIsFalse()) {
1013 // If the condition is false there is no need to generate the loop.
1014 return;
1015 }
1016
1017 LoopBuilder loop_builder(builder());
Ben Murdochc5610432016-08-08 18:44:38 +01001018 VisitIterationHeader(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001019 if (!stmt->cond()->ToBooleanIsTrue()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001020 builder()->SetExpressionAsStatementPosition(stmt->cond());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 VisitForAccumulatorValue(stmt->cond());
1022 loop_builder.BreakIfFalse();
1023 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001024 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001025 loop_builder.JumpToHeader();
1026 loop_builder.EndLoop();
1027}
1028
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001029void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
1030 if (stmt->init() != nullptr) {
1031 Visit(stmt->init());
1032 }
1033 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
1034 // If the condition is known to be false there is no need to generate
1035 // body, next or condition blocks. Init block should be generated.
1036 return;
1037 }
1038
1039 LoopBuilder loop_builder(builder());
Ben Murdochc5610432016-08-08 18:44:38 +01001040 VisitIterationHeader(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001041 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001042 builder()->SetExpressionAsStatementPosition(stmt->cond());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 VisitForAccumulatorValue(stmt->cond());
1044 loop_builder.BreakIfFalse();
1045 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001046 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001047 if (stmt->next() != nullptr) {
Ben Murdochda12d292016-06-02 14:46:10 +01001048 builder()->SetStatementPosition(stmt->next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001049 Visit(stmt->next());
1050 }
1051 loop_builder.JumpToHeader();
1052 loop_builder.EndLoop();
1053}
1054
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055void BytecodeGenerator::VisitForInAssignment(Expression* expr,
1056 FeedbackVectorSlot slot) {
1057 DCHECK(expr->IsValidReferenceExpression());
1058
1059 // Evaluate assignment starting with the value to be stored in the
1060 // accumulator.
1061 Property* property = expr->AsProperty();
1062 LhsKind assign_type = Property::GetAssignType(property);
1063 switch (assign_type) {
1064 case VARIABLE: {
1065 Variable* variable = expr->AsVariableProxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001066 VisitVariableAssignment(variable, Token::ASSIGN, slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067 break;
1068 }
1069 case NAMED_PROPERTY: {
1070 RegisterAllocationScope register_scope(this);
1071 Register value = register_allocator()->NewRegister();
1072 builder()->StoreAccumulatorInRegister(value);
1073 Register object = VisitForRegisterValue(property->obj());
1074 Handle<String> name = property->key()->AsLiteral()->AsPropertyName();
1075 builder()->LoadAccumulatorWithRegister(value);
1076 builder()->StoreNamedProperty(object, name, feedback_index(slot),
1077 language_mode());
1078 break;
1079 }
1080 case KEYED_PROPERTY: {
1081 RegisterAllocationScope register_scope(this);
1082 Register value = register_allocator()->NewRegister();
1083 builder()->StoreAccumulatorInRegister(value);
1084 Register object = VisitForRegisterValue(property->obj());
1085 Register key = VisitForRegisterValue(property->key());
1086 builder()->LoadAccumulatorWithRegister(value);
1087 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
1088 language_mode());
1089 break;
1090 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001091 case NAMED_SUPER_PROPERTY: {
1092 RegisterAllocationScope register_scope(this);
1093 register_allocator()->PrepareForConsecutiveAllocations(4);
1094 Register receiver = register_allocator()->NextConsecutiveRegister();
1095 Register home_object = register_allocator()->NextConsecutiveRegister();
1096 Register name = register_allocator()->NextConsecutiveRegister();
1097 Register value = register_allocator()->NextConsecutiveRegister();
1098 builder()->StoreAccumulatorInRegister(value);
1099 SuperPropertyReference* super_property =
1100 property->obj()->AsSuperPropertyReference();
1101 VisitForRegisterValue(super_property->this_var(), receiver);
1102 VisitForRegisterValue(super_property->home_object(), home_object);
1103 builder()
1104 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
1105 .StoreAccumulatorInRegister(name);
1106 BuildNamedSuperPropertyStore(receiver, home_object, name, value);
1107 break;
1108 }
1109 case KEYED_SUPER_PROPERTY: {
1110 RegisterAllocationScope register_scope(this);
1111 register_allocator()->PrepareForConsecutiveAllocations(4);
1112 Register receiver = register_allocator()->NextConsecutiveRegister();
1113 Register home_object = register_allocator()->NextConsecutiveRegister();
1114 Register key = register_allocator()->NextConsecutiveRegister();
1115 Register value = register_allocator()->NextConsecutiveRegister();
1116 builder()->StoreAccumulatorInRegister(value);
1117 SuperPropertyReference* super_property =
1118 property->obj()->AsSuperPropertyReference();
1119 VisitForRegisterValue(super_property->this_var(), receiver);
1120 VisitForRegisterValue(super_property->home_object(), home_object);
1121 VisitForRegisterValue(property->key(), key);
1122 BuildKeyedSuperPropertyStore(receiver, home_object, key, value);
1123 break;
1124 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001125 }
1126}
1127
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001128void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1129 if (stmt->subject()->IsNullLiteral() ||
Ben Murdochda12d292016-06-02 14:46:10 +01001130 stmt->subject()->IsUndefinedLiteral()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131 // ForIn generates lots of code, skip if it wouldn't produce any effects.
1132 return;
1133 }
1134
1135 LoopBuilder loop_builder(builder());
Ben Murdochda12d292016-06-02 14:46:10 +01001136 BytecodeLabel subject_null_label, subject_undefined_label;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001137
1138 // Prepare the state for executing ForIn.
Ben Murdochda12d292016-06-02 14:46:10 +01001139 builder()->SetExpressionAsStatementPosition(stmt->subject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 VisitForAccumulatorValue(stmt->subject());
1141 builder()->JumpIfUndefined(&subject_undefined_label);
1142 builder()->JumpIfNull(&subject_null_label);
1143 Register receiver = register_allocator()->NewRegister();
1144 builder()->CastAccumulatorToJSObject();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001145 builder()->StoreAccumulatorInRegister(receiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001146
1147 register_allocator()->PrepareForConsecutiveAllocations(3);
1148 Register cache_type = register_allocator()->NextConsecutiveRegister();
1149 Register cache_array = register_allocator()->NextConsecutiveRegister();
1150 Register cache_length = register_allocator()->NextConsecutiveRegister();
Ben Murdochda12d292016-06-02 14:46:10 +01001151 // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001152 USE(cache_array);
1153 builder()->ForInPrepare(cache_type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001154
1155 // Set up loop counter
1156 Register index = register_allocator()->NewRegister();
1157 builder()->LoadLiteral(Smi::FromInt(0));
1158 builder()->StoreAccumulatorInRegister(index);
1159
1160 // The loop
Ben Murdochc5610432016-08-08 18:44:38 +01001161 VisitIterationHeader(stmt, &loop_builder);
Ben Murdochda12d292016-06-02 14:46:10 +01001162 builder()->SetExpressionAsStatementPosition(stmt->each());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001163 builder()->ForInDone(index, cache_length);
1164 loop_builder.BreakIfTrue();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001165 DCHECK(Register::AreContiguous(cache_type, cache_array));
Ben Murdochda12d292016-06-02 14:46:10 +01001166 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
1167 builder()->ForInNext(receiver, index, cache_type, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001168 loop_builder.ContinueIfUndefined();
1169 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001170 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001171 builder()->ForInStep(index);
1172 builder()->StoreAccumulatorInRegister(index);
1173 loop_builder.JumpToHeader();
1174 loop_builder.EndLoop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001175 builder()->Bind(&subject_null_label);
1176 builder()->Bind(&subject_undefined_label);
1177}
1178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001179void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001180 LoopBuilder loop_builder(builder());
1181 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
1182
Ben Murdochc5610432016-08-08 18:44:38 +01001183 builder()->SetExpressionAsStatementPosition(stmt->assign_iterator());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001184 VisitForEffect(stmt->assign_iterator());
1185
Ben Murdochc5610432016-08-08 18:44:38 +01001186 VisitIterationHeader(stmt, &loop_builder);
Ben Murdochda12d292016-06-02 14:46:10 +01001187 builder()->SetExpressionAsStatementPosition(stmt->next_result());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001188 VisitForEffect(stmt->next_result());
1189 VisitForAccumulatorValue(stmt->result_done());
1190 loop_builder.BreakIfTrue();
1191
1192 VisitForEffect(stmt->assign_each());
1193 VisitIterationBody(stmt, &loop_builder);
1194 loop_builder.JumpToHeader();
1195 loop_builder.EndLoop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196}
1197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001198void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001199 TryCatchBuilder try_control_builder(builder());
1200 Register no_reg;
1201
1202 // Preserve the context in a dedicated register, so that it can be restored
1203 // when the handler is entered by the stack-unwinding machinery.
1204 // TODO(mstarzinger): Be smarter about register allocation.
1205 Register context = register_allocator()->NewRegister();
1206 builder()->MoveRegister(Register::current_context(), context);
1207
1208 // Evaluate the try-block inside a control scope. This simulates a handler
1209 // that is intercepting 'throw' control commands.
1210 try_control_builder.BeginTry(context);
1211 {
1212 ControlScopeForTryCatch scope(this, &try_control_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 Visit(stmt->try_block());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001214 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001215 try_control_builder.EndTry();
1216
1217 // Create a catch scope that binds the exception.
1218 VisitNewLocalCatchContext(stmt->variable());
1219 builder()->StoreAccumulatorInRegister(context);
1220
Ben Murdochda12d292016-06-02 14:46:10 +01001221 // If requested, clear message object as we enter the catch block.
1222 if (stmt->clear_pending_message()) {
1223 builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0);
1224 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001225
1226 // Load the catch context into the accumulator.
1227 builder()->LoadAccumulatorWithRegister(context);
1228
1229 // Evaluate the catch-block.
1230 VisitInScope(stmt->catch_block(), stmt->scope());
1231 try_control_builder.EndCatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001232}
1233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001234void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001235 TryFinallyBuilder try_control_builder(builder(), IsInsideTryCatch());
1236 Register no_reg;
1237
1238 // We keep a record of all paths that enter the finally-block to be able to
1239 // dispatch to the correct continuation point after the statements in the
1240 // finally-block have been evaluated.
1241 //
1242 // The try-finally construct can enter the finally-block in three ways:
1243 // 1. By exiting the try-block normally, falling through at the end.
1244 // 2. By exiting the try-block with a function-local control flow transfer
1245 // (i.e. through break/continue/return statements).
1246 // 3. By exiting the try-block with a thrown exception.
1247 //
1248 // The result register semantics depend on how the block was entered:
1249 // - ReturnStatement: It represents the return value being returned.
1250 // - ThrowStatement: It represents the exception being thrown.
1251 // - BreakStatement/ContinueStatement: Undefined and not used.
1252 // - Falling through into finally-block: Undefined and not used.
1253 Register token = register_allocator()->NewRegister();
1254 Register result = register_allocator()->NewRegister();
1255 ControlScope::DeferredCommands commands(this, token, result);
1256
1257 // Preserve the context in a dedicated register, so that it can be restored
1258 // when the handler is entered by the stack-unwinding machinery.
1259 // TODO(mstarzinger): Be smarter about register allocation.
1260 Register context = register_allocator()->NewRegister();
1261 builder()->MoveRegister(Register::current_context(), context);
1262
1263 // Evaluate the try-block inside a control scope. This simulates a handler
1264 // that is intercepting all control commands.
1265 try_control_builder.BeginTry(context);
1266 {
1267 ControlScopeForTryFinally scope(this, &try_control_builder, &commands);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001268 Visit(stmt->try_block());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001269 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001270 try_control_builder.EndTry();
1271
1272 // Record fall-through and exception cases.
1273 commands.RecordFallThroughPath();
1274 try_control_builder.LeaveTry();
1275 try_control_builder.BeginHandler();
1276 commands.RecordHandlerReThrowPath();
1277
1278 // Pending message object is saved on entry.
1279 try_control_builder.BeginFinally();
1280 Register message = context; // Reuse register.
1281
1282 // Clear message object as we enter the finally block.
1283 builder()
1284 ->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0)
1285 .StoreAccumulatorInRegister(message);
1286
1287 // Evaluate the finally-block.
1288 Visit(stmt->finally_block());
1289 try_control_builder.EndFinally();
1290
1291 // Pending message object is restored on exit.
1292 builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message, 1);
1293
1294 // Dynamic dispatch after the finally-block.
1295 commands.ApplyDeferredCommands();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001296}
1297
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001298void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001299 builder()->SetStatementPosition(stmt);
1300 builder()->Debugger();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001301}
1302
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001303void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1304 // Find or build a shared function info.
1305 Handle<SharedFunctionInfo> shared_info =
1306 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
Ben Murdochda12d292016-06-02 14:46:10 +01001307 if (shared_info.is_null()) {
1308 return SetStackOverflow();
1309 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310 builder()->CreateClosure(shared_info,
1311 expr->pretenure() ? TENURED : NOT_TENURED);
1312 execution_result()->SetResultInAccumulator();
1313}
1314
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001315void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001316 if (expr->scope()->ContextLocalCount() > 0) {
1317 VisitNewLocalBlockContext(expr->scope());
1318 ContextScope scope(this, expr->scope());
1319 VisitDeclarations(expr->scope()->declarations());
1320 VisitClassLiteralContents(expr);
1321 } else {
1322 VisitDeclarations(expr->scope()->declarations());
1323 VisitClassLiteralContents(expr);
1324 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001325}
1326
Ben Murdoch097c5b22016-05-18 11:27:45 +01001327void BytecodeGenerator::VisitClassLiteralContents(ClassLiteral* expr) {
1328 VisitClassLiteralForRuntimeDefinition(expr);
1329
1330 // Load the "prototype" from the constructor.
1331 register_allocator()->PrepareForConsecutiveAllocations(2);
1332 Register literal = register_allocator()->NextConsecutiveRegister();
1333 Register prototype = register_allocator()->NextConsecutiveRegister();
1334 Handle<String> name = isolate()->factory()->prototype_string();
1335 FeedbackVectorSlot slot = expr->PrototypeSlot();
1336 builder()
1337 ->StoreAccumulatorInRegister(literal)
1338 .LoadNamedProperty(literal, name, feedback_index(slot))
1339 .StoreAccumulatorInRegister(prototype);
1340
1341 VisitClassLiteralProperties(expr, literal, prototype);
Ben Murdochc5610432016-08-08 18:44:38 +01001342 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001343 // Assign to class variable.
1344 if (expr->class_variable_proxy() != nullptr) {
1345 Variable* var = expr->class_variable_proxy()->var();
1346 FeedbackVectorSlot slot = expr->NeedsProxySlot()
1347 ? expr->ProxySlot()
1348 : FeedbackVectorSlot::Invalid();
1349 VisitVariableAssignment(var, Token::INIT, slot);
1350 }
1351 execution_result()->SetResultInAccumulator();
1352}
1353
1354void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition(
1355 ClassLiteral* expr) {
1356 AccumulatorResultScope result_scope(this);
1357 register_allocator()->PrepareForConsecutiveAllocations(4);
1358 Register extends = register_allocator()->NextConsecutiveRegister();
1359 Register constructor = register_allocator()->NextConsecutiveRegister();
1360 Register start_position = register_allocator()->NextConsecutiveRegister();
1361 Register end_position = register_allocator()->NextConsecutiveRegister();
1362
1363 VisitForAccumulatorValueOrTheHole(expr->extends());
1364 builder()->StoreAccumulatorInRegister(extends);
1365
1366 VisitForAccumulatorValue(expr->constructor());
1367 builder()
1368 ->StoreAccumulatorInRegister(constructor)
1369 .LoadLiteral(Smi::FromInt(expr->start_position()))
1370 .StoreAccumulatorInRegister(start_position)
1371 .LoadLiteral(Smi::FromInt(expr->end_position()))
1372 .StoreAccumulatorInRegister(end_position)
1373 .CallRuntime(Runtime::kDefineClass, extends, 4);
1374 result_scope.SetResultInAccumulator();
1375}
1376
1377void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
1378 Register literal,
1379 Register prototype) {
1380 RegisterAllocationScope register_scope(this);
1381 register_allocator()->PrepareForConsecutiveAllocations(5);
1382 Register receiver = register_allocator()->NextConsecutiveRegister();
1383 Register key = register_allocator()->NextConsecutiveRegister();
1384 Register value = register_allocator()->NextConsecutiveRegister();
1385 Register attr = register_allocator()->NextConsecutiveRegister();
1386 Register set_function_name = register_allocator()->NextConsecutiveRegister();
1387
1388 bool attr_assigned = false;
1389 Register old_receiver = Register::invalid_value();
1390
1391 // Create nodes to store method values into the literal.
1392 for (int i = 0; i < expr->properties()->length(); i++) {
1393 ObjectLiteral::Property* property = expr->properties()->at(i);
1394
1395 // Set-up receiver.
1396 Register new_receiver = property->is_static() ? literal : prototype;
1397 if (new_receiver != old_receiver) {
1398 builder()->MoveRegister(new_receiver, receiver);
1399 old_receiver = new_receiver;
1400 }
1401
1402 VisitForAccumulatorValue(property->key());
1403 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1404 // The static prototype property is read only. We handle the non computed
1405 // property name case in the parser. Since this is the only case where we
1406 // need to check for an own read only property we special case this so we do
1407 // not need to do this for every property.
1408 if (property->is_static() && property->is_computed_name()) {
1409 VisitClassLiteralStaticPrototypeWithComputedName(key);
1410 }
1411 VisitForAccumulatorValue(property->value());
1412 builder()->StoreAccumulatorInRegister(value);
1413
1414 VisitSetHomeObject(value, receiver, property);
1415
1416 if (!attr_assigned) {
1417 builder()
1418 ->LoadLiteral(Smi::FromInt(DONT_ENUM))
1419 .StoreAccumulatorInRegister(attr);
1420 attr_assigned = true;
1421 }
1422
1423 switch (property->kind()) {
1424 case ObjectLiteral::Property::CONSTANT:
1425 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1426 case ObjectLiteral::Property::PROTOTYPE:
1427 // Invalid properties for ES6 classes.
1428 UNREACHABLE();
1429 break;
1430 case ObjectLiteral::Property::COMPUTED: {
1431 builder()
1432 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
1433 .StoreAccumulatorInRegister(set_function_name);
1434 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, receiver,
1435 5);
1436 break;
1437 }
1438 case ObjectLiteral::Property::GETTER: {
1439 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
1440 receiver, 4);
1441 break;
1442 }
1443 case ObjectLiteral::Property::SETTER: {
1444 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
1445 receiver, 4);
1446 break;
1447 }
1448 }
1449 }
1450}
1451
1452void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName(
1453 Register key) {
1454 BytecodeLabel done;
1455 builder()
1456 ->LoadLiteral(isolate()->factory()->prototype_string())
1457 .CompareOperation(Token::Value::EQ_STRICT, key)
1458 .JumpIfFalse(&done)
1459 .CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0)
1460 .Bind(&done);
1461}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001462
1463void BytecodeGenerator::VisitNativeFunctionLiteral(
1464 NativeFunctionLiteral* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001465 // Find or build a shared function info for the native function template.
1466 Handle<SharedFunctionInfo> shared_info =
1467 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name());
1468 builder()->CreateClosure(shared_info, NOT_TENURED);
1469 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001470}
1471
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001472void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001473 VisitBlock(expr->block());
1474 VisitVariableProxy(expr->result());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001475}
1476
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001477void BytecodeGenerator::VisitConditional(Conditional* expr) {
1478 // TODO(rmcilroy): Spot easy cases where there code would not need to
1479 // emit the then block or the else block, e.g. condition is
1480 // obviously true/1/false/0.
1481
1482 BytecodeLabel else_label, end_label;
1483
1484 VisitForAccumulatorValue(expr->condition());
1485 builder()->JumpIfFalse(&else_label);
1486
1487 VisitForAccumulatorValue(expr->then_expression());
1488 builder()->Jump(&end_label);
1489
1490 builder()->Bind(&else_label);
1491 VisitForAccumulatorValue(expr->else_expression());
1492 builder()->Bind(&end_label);
1493
1494 execution_result()->SetResultInAccumulator();
1495}
1496
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001497void BytecodeGenerator::VisitLiteral(Literal* expr) {
1498 if (!execution_result()->IsEffect()) {
1499 Handle<Object> value = expr->value();
1500 if (value->IsSmi()) {
1501 builder()->LoadLiteral(Smi::cast(*value));
Ben Murdoch61f157c2016-09-16 13:49:30 +01001502 } else if (value->IsUndefined(isolate())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001503 builder()->LoadUndefined();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001504 } else if (value->IsTrue(isolate())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001505 builder()->LoadTrue();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001506 } else if (value->IsFalse(isolate())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001507 builder()->LoadFalse();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001508 } else if (value->IsNull(isolate())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001509 builder()->LoadNull();
Ben Murdoch61f157c2016-09-16 13:49:30 +01001510 } else if (value->IsTheHole(isolate())) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001511 builder()->LoadTheHole();
1512 } else {
1513 builder()->LoadLiteral(value);
1514 }
1515 execution_result()->SetResultInAccumulator();
1516 }
1517}
1518
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001519void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1520 // Materialize a regular expression literal.
1521 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(),
1522 expr->flags());
1523 execution_result()->SetResultInAccumulator();
1524}
1525
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001526void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
Ben Murdochc5610432016-08-08 18:44:38 +01001527 // Copy the literal boilerplate.
1528 int fast_clone_properties_count = 0;
1529 if (FastCloneShallowObjectStub::IsSupported(expr)) {
1530 STATIC_ASSERT(
1531 FastCloneShallowObjectStub::kMaximumClonedProperties <=
1532 1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift);
1533 fast_clone_properties_count =
1534 FastCloneShallowObjectStub::PropertiesCount(expr->properties_count());
1535 }
1536 uint8_t flags =
1537 CreateObjectLiteralFlags::FlagsBits::encode(expr->ComputeFlags()) |
1538 CreateObjectLiteralFlags::FastClonePropertiesCountBits::encode(
1539 fast_clone_properties_count);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001540 builder()->CreateObjectLiteral(expr->constant_properties(),
Ben Murdochc5610432016-08-08 18:44:38 +01001541 expr->literal_index(), flags);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001542
1543 // Allocate in the outer scope since this register is used to return the
1544 // expression's results to the caller.
1545 Register literal = register_allocator()->outer()->NewRegister();
1546 builder()->StoreAccumulatorInRegister(literal);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001547
1548 // Store computed values into the literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001549 int property_index = 0;
1550 AccessorTable accessor_table(zone());
1551 for (; property_index < expr->properties()->length(); property_index++) {
1552 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1553 if (property->is_computed_name()) break;
1554 if (property->IsCompileTimeValue()) continue;
1555
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001556 RegisterAllocationScope inner_register_scope(this);
1557 Literal* literal_key = property->key()->AsLiteral();
1558 switch (property->kind()) {
1559 case ObjectLiteral::Property::CONSTANT:
1560 UNREACHABLE();
1561 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1562 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1563 // Fall through.
1564 case ObjectLiteral::Property::COMPUTED: {
1565 // It is safe to use [[Put]] here because the boilerplate already
1566 // contains computed properties with an uninitialized value.
1567 if (literal_key->value()->IsInternalizedString()) {
1568 if (property->emit_store()) {
1569 VisitForAccumulatorValue(property->value());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001570 if (FunctionLiteral::NeedsHomeObject(property->value())) {
1571 RegisterAllocationScope register_scope(this);
1572 Register value = register_allocator()->NewRegister();
1573 builder()->StoreAccumulatorInRegister(value);
1574 builder()->StoreNamedProperty(
1575 literal, literal_key->AsPropertyName(),
1576 feedback_index(property->GetSlot(0)), language_mode());
1577 VisitSetHomeObject(value, literal, property, 1);
1578 } else {
1579 builder()->StoreNamedProperty(
1580 literal, literal_key->AsPropertyName(),
1581 feedback_index(property->GetSlot(0)), language_mode());
1582 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001583 } else {
1584 VisitForEffect(property->value());
1585 }
1586 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001587 register_allocator()->PrepareForConsecutiveAllocations(4);
1588 Register literal_argument =
1589 register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001590 Register key = register_allocator()->NextConsecutiveRegister();
1591 Register value = register_allocator()->NextConsecutiveRegister();
1592 Register language = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001593
1594 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001595 VisitForAccumulatorValue(property->key());
1596 builder()->StoreAccumulatorInRegister(key);
1597 VisitForAccumulatorValue(property->value());
1598 builder()->StoreAccumulatorInRegister(value);
1599 if (property->emit_store()) {
1600 builder()
1601 ->LoadLiteral(Smi::FromInt(SLOPPY))
1602 .StoreAccumulatorInRegister(language)
Ben Murdoch097c5b22016-05-18 11:27:45 +01001603 .CallRuntime(Runtime::kSetProperty, literal_argument, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001604 VisitSetHomeObject(value, literal, property);
1605 }
1606 }
1607 break;
1608 }
1609 case ObjectLiteral::Property::PROTOTYPE: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001610 DCHECK(property->emit_store());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001611 register_allocator()->PrepareForConsecutiveAllocations(2);
1612 Register literal_argument =
1613 register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001614 Register value = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001615
1616 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001617 VisitForAccumulatorValue(property->value());
1618 builder()->StoreAccumulatorInRegister(value).CallRuntime(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001619 Runtime::kInternalSetPrototype, literal_argument, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001620 break;
1621 }
1622 case ObjectLiteral::Property::GETTER:
1623 if (property->emit_store()) {
1624 accessor_table.lookup(literal_key)->second->getter = property;
1625 }
1626 break;
1627 case ObjectLiteral::Property::SETTER:
1628 if (property->emit_store()) {
1629 accessor_table.lookup(literal_key)->second->setter = property;
1630 }
1631 break;
1632 }
1633 }
1634
1635 // Define accessors, using only a single call to the runtime for each pair of
1636 // corresponding getters and setters.
1637 for (AccessorTable::Iterator it = accessor_table.begin();
1638 it != accessor_table.end(); ++it) {
1639 RegisterAllocationScope inner_register_scope(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001640 register_allocator()->PrepareForConsecutiveAllocations(5);
1641 Register literal_argument = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001642 Register name = register_allocator()->NextConsecutiveRegister();
1643 Register getter = register_allocator()->NextConsecutiveRegister();
1644 Register setter = register_allocator()->NextConsecutiveRegister();
1645 Register attr = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001646
1647 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001648 VisitForAccumulatorValue(it->first);
1649 builder()->StoreAccumulatorInRegister(name);
1650 VisitObjectLiteralAccessor(literal, it->second->getter, getter);
1651 VisitObjectLiteralAccessor(literal, it->second->setter, setter);
1652 builder()
1653 ->LoadLiteral(Smi::FromInt(NONE))
1654 .StoreAccumulatorInRegister(attr)
Ben Murdoch097c5b22016-05-18 11:27:45 +01001655 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked,
1656 literal_argument, 5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001657 }
1658
1659 // Object literals have two parts. The "static" part on the left contains no
1660 // computed property names, and so we can compute its map ahead of time; see
1661 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1662 // with the first computed property name and continues with all properties to
1663 // its right. All the code from above initializes the static component of the
1664 // object literal, and arranges for the map of the result to reflect the
1665 // static order in which the keys appear. For the dynamic properties, we
1666 // compile them into a series of "SetOwnProperty" runtime calls. This will
1667 // preserve insertion order.
1668 for (; property_index < expr->properties()->length(); property_index++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001669 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1670 RegisterAllocationScope inner_register_scope(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001671
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001672 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1673 DCHECK(property->emit_store());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001674 register_allocator()->PrepareForConsecutiveAllocations(2);
1675 Register literal_argument =
1676 register_allocator()->NextConsecutiveRegister();
1677 Register value = register_allocator()->NextConsecutiveRegister();
1678
1679 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001680 VisitForAccumulatorValue(property->value());
1681 builder()->StoreAccumulatorInRegister(value).CallRuntime(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001682 Runtime::kInternalSetPrototype, literal_argument, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001683 continue;
1684 }
1685
Ben Murdoch097c5b22016-05-18 11:27:45 +01001686 register_allocator()->PrepareForConsecutiveAllocations(5);
1687 Register literal_argument = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001688 Register key = register_allocator()->NextConsecutiveRegister();
1689 Register value = register_allocator()->NextConsecutiveRegister();
1690 Register attr = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001691 DCHECK(Register::AreContiguous(literal_argument, key, value, attr));
1692 Register set_function_name =
1693 register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001694
Ben Murdoch097c5b22016-05-18 11:27:45 +01001695 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001696 VisitForAccumulatorValue(property->key());
1697 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1698 VisitForAccumulatorValue(property->value());
1699 builder()->StoreAccumulatorInRegister(value);
1700 VisitSetHomeObject(value, literal, property);
1701 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001702 switch (property->kind()) {
1703 case ObjectLiteral::Property::CONSTANT:
1704 case ObjectLiteral::Property::COMPUTED:
1705 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001706 builder()
1707 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
1708 .StoreAccumulatorInRegister(set_function_name);
1709 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral,
1710 literal_argument, 5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001711 break;
1712 case ObjectLiteral::Property::PROTOTYPE:
1713 UNREACHABLE(); // Handled specially above.
1714 break;
1715 case ObjectLiteral::Property::GETTER:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001716 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
1717 literal_argument, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001718 break;
1719 case ObjectLiteral::Property::SETTER:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001720 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
1721 literal_argument, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001722 break;
1723 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001724 }
1725
Ben Murdoch097c5b22016-05-18 11:27:45 +01001726 execution_result()->SetResultInRegister(literal);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001727}
1728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001729void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1730 // Deep-copy the literal boilerplate.
1731 builder()->CreateArrayLiteral(expr->constant_elements(),
1732 expr->literal_index(),
1733 expr->ComputeFlags(true));
1734 Register index, literal;
1735
1736 // Evaluate all the non-constant subexpressions and store them into the
1737 // newly cloned array.
1738 bool literal_in_accumulator = true;
1739 for (int array_index = 0; array_index < expr->values()->length();
1740 array_index++) {
1741 Expression* subexpr = expr->values()->at(array_index);
1742 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001743 DCHECK(!subexpr->IsSpread());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001744
1745 if (literal_in_accumulator) {
1746 index = register_allocator()->NewRegister();
1747 literal = register_allocator()->NewRegister();
1748 builder()->StoreAccumulatorInRegister(literal);
1749 literal_in_accumulator = false;
1750 }
1751
1752 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot();
1753 builder()
1754 ->LoadLiteral(Smi::FromInt(array_index))
1755 .StoreAccumulatorInRegister(index);
1756 VisitForAccumulatorValue(subexpr);
1757 builder()->StoreKeyedProperty(literal, index, feedback_index(slot),
1758 language_mode());
1759 }
1760
1761 if (!literal_in_accumulator) {
1762 // Restore literal array into accumulator.
1763 builder()->LoadAccumulatorWithRegister(literal);
1764 }
1765 execution_result()->SetResultInAccumulator();
1766}
1767
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001768void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
Ben Murdochda12d292016-06-02 14:46:10 +01001769 builder()->SetExpressionPosition(proxy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001770 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1771}
1772
Ben Murdoch097c5b22016-05-18 11:27:45 +01001773void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
1774 Handle<String> name) {
Ben Murdochc5610432016-08-08 18:44:38 +01001775 if (mode == LET || mode == CONST) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001776 BuildThrowIfHole(name);
1777 }
1778}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001779
1780void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1781 FeedbackVectorSlot slot,
1782 TypeofMode typeof_mode) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001783 VariableMode mode = variable->mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001784 switch (variable->location()) {
1785 case VariableLocation::LOCAL: {
1786 Register source(Register(variable->index()));
1787 builder()->LoadAccumulatorWithRegister(source);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001788 BuildHoleCheckForVariableLoad(mode, variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001789 execution_result()->SetResultInAccumulator();
1790 break;
1791 }
1792 case VariableLocation::PARAMETER: {
1793 // The parameter indices are shifted by 1 (receiver is variable
1794 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1795 Register source = builder()->Parameter(variable->index() + 1);
1796 builder()->LoadAccumulatorWithRegister(source);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001797 BuildHoleCheckForVariableLoad(mode, variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001798 execution_result()->SetResultInAccumulator();
1799 break;
1800 }
1801 case VariableLocation::GLOBAL:
1802 case VariableLocation::UNALLOCATED: {
Ben Murdoch61f157c2016-09-16 13:49:30 +01001803 builder()->LoadGlobal(feedback_index(slot), typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001804 execution_result()->SetResultInAccumulator();
1805 break;
1806 }
1807 case VariableLocation::CONTEXT: {
1808 int depth = execution_context()->ContextChainDepth(variable->scope());
1809 ContextScope* context = execution_context()->Previous(depth);
1810 Register context_reg;
1811 if (context) {
1812 context_reg = context->reg();
1813 } else {
1814 context_reg = register_allocator()->NewRegister();
1815 // Walk the context chain to find the context at the given depth.
1816 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1817 // a generic mechanism for performing jumps in interpreter.cc.
1818 // TODO(mythria): Also update bytecode graph builder with correct depth
1819 // when this changes.
1820 builder()
1821 ->LoadAccumulatorWithRegister(execution_context()->reg())
1822 .StoreAccumulatorInRegister(context_reg);
1823 for (int i = 0; i < depth; ++i) {
1824 builder()
1825 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1826 .StoreAccumulatorInRegister(context_reg);
1827 }
1828 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001829
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001830 builder()->LoadContextSlot(context_reg, variable->index());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001831 BuildHoleCheckForVariableLoad(mode, variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001832 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001833 break;
1834 }
1835 case VariableLocation::LOOKUP: {
1836 builder()->LoadLookupSlot(variable->name(), typeof_mode);
1837 execution_result()->SetResultInAccumulator();
1838 break;
1839 }
1840 }
1841}
1842
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001843void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
1844 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1845 AccumulatorResultScope accumulator_result(this);
1846 VisitVariableLoad(variable, slot, typeof_mode);
1847}
1848
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001849Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
1850 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1851 RegisterResultScope register_scope(this);
1852 VisitVariableLoad(variable, slot, typeof_mode);
1853 return register_scope.ResultRegister();
1854}
1855
Ben Murdoch097c5b22016-05-18 11:27:45 +01001856void BytecodeGenerator::BuildNamedSuperPropertyLoad(Register receiver,
1857 Register home_object,
1858 Register name) {
1859 DCHECK(Register::AreContiguous(receiver, home_object, name));
1860 builder()->CallRuntime(Runtime::kLoadFromSuper, receiver, 3);
1861}
1862
1863void BytecodeGenerator::BuildKeyedSuperPropertyLoad(Register receiver,
1864 Register home_object,
1865 Register key) {
1866 DCHECK(Register::AreContiguous(receiver, home_object, key));
1867 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, receiver, 3);
1868}
1869
1870void BytecodeGenerator::BuildNamedSuperPropertyStore(Register receiver,
1871 Register home_object,
1872 Register name,
1873 Register value) {
1874 DCHECK(Register::AreContiguous(receiver, home_object, name, value));
1875 Runtime::FunctionId function_id = is_strict(language_mode())
1876 ? Runtime::kStoreToSuper_Strict
1877 : Runtime::kStoreToSuper_Sloppy;
1878 builder()->CallRuntime(function_id, receiver, 4);
1879}
1880
1881void BytecodeGenerator::BuildKeyedSuperPropertyStore(Register receiver,
1882 Register home_object,
1883 Register key,
1884 Register value) {
1885 DCHECK(Register::AreContiguous(receiver, home_object, key, value));
1886 Runtime::FunctionId function_id = is_strict(language_mode())
1887 ? Runtime::kStoreKeyedToSuper_Strict
1888 : Runtime::kStoreKeyedToSuper_Sloppy;
1889 builder()->CallRuntime(function_id, receiver, 4);
1890}
1891
Ben Murdoch61f157c2016-09-16 13:49:30 +01001892void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) {
1893 RegisterAllocationScope register_scope(this);
1894 Register reason = register_allocator()->NewRegister();
1895 builder()
1896 ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason)))
1897 .StoreAccumulatorInRegister(reason)
1898 .CallRuntime(Runtime::kAbort, reason, 1);
1899}
1900
Ben Murdoch097c5b22016-05-18 11:27:45 +01001901void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) {
1902 RegisterAllocationScope register_scope(this);
1903 Register name_reg = register_allocator()->NewRegister();
1904 builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime(
1905 Runtime::kThrowReferenceError, name_reg, 1);
1906}
1907
1908void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
1909 // TODO(interpreter): Can the parser reduce the number of checks
1910 // performed? Or should there be a ThrowIfHole bytecode.
1911 BytecodeLabel no_reference_error;
1912 builder()->JumpIfNotHole(&no_reference_error);
1913 BuildThrowReferenceError(name);
1914 builder()->Bind(&no_reference_error);
1915}
1916
1917void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
1918 // TODO(interpreter): Can the parser reduce the number of checks
1919 // performed? Or should there be a ThrowIfNotHole bytecode.
1920 BytecodeLabel no_reference_error, reference_error;
1921 builder()
1922 ->JumpIfNotHole(&reference_error)
1923 .Jump(&no_reference_error)
1924 .Bind(&reference_error);
1925 BuildThrowReferenceError(name);
1926 builder()->Bind(&no_reference_error);
1927}
1928
1929void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
1930 // TODO(mythria): This will be replaced by a new bytecode that throws an
1931 // appropriate error depending on the whether the value is a hole or not.
1932 BytecodeLabel const_assign_error;
1933 builder()->JumpIfNotHole(&const_assign_error);
1934 BuildThrowReferenceError(name);
1935 builder()
1936 ->Bind(&const_assign_error)
1937 .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
1938}
1939
1940void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
1941 Token::Value op) {
1942 VariableMode mode = variable->mode();
1943 DCHECK(mode != CONST_LEGACY);
1944 if (mode == CONST && op != Token::INIT) {
1945 // Non-intializing assignments to constant is not allowed.
1946 BuildThrowReassignConstant(variable->name());
1947 } else if (mode == LET && op != Token::INIT) {
1948 // Perform an initialization check for let declared variables.
1949 // E.g. let x = (x = 20); is not allowed.
1950 BuildThrowIfHole(variable->name());
1951 } else {
1952 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
1953 // Perform an initialization check for 'this'. 'this' variable is the
1954 // only variable able to trigger bind operations outside the TDZ
1955 // via 'super' calls.
1956 BuildThrowIfNotHole(variable->name());
1957 }
1958}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001959
1960void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001961 Token::Value op,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001962 FeedbackVectorSlot slot) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001963 VariableMode mode = variable->mode();
1964 RegisterAllocationScope assignment_register_scope(this);
1965 BytecodeLabel end_label;
1966 bool hole_check_required =
Ben Murdochc5610432016-08-08 18:44:38 +01001967 (mode == LET && op != Token::INIT) ||
Ben Murdoch097c5b22016-05-18 11:27:45 +01001968 (mode == CONST && op != Token::INIT) ||
1969 (mode == CONST && op == Token::INIT && variable->is_this());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001970 switch (variable->location()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001971 case VariableLocation::PARAMETER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001972 case VariableLocation::LOCAL: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001973 Register destination;
1974 if (VariableLocation::PARAMETER == variable->location()) {
1975 destination = Register(builder()->Parameter(variable->index() + 1));
1976 } else {
1977 destination = Register(variable->index());
1978 }
1979
Ben Murdochc5610432016-08-08 18:44:38 +01001980 if (mode == CONST_LEGACY && op != Token::INIT) {
1981 if (is_strict(language_mode())) {
1982 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
1983 0);
1984 }
1985 // Non-initializing assignments to legacy constants are ignored
1986 // in sloppy mode. Break here to avoid storing into variable.
1987 break;
1988 }
1989
Ben Murdoch097c5b22016-05-18 11:27:45 +01001990 if (hole_check_required) {
1991 // Load destination to check for hole.
1992 Register value_temp = register_allocator()->NewRegister();
1993 builder()
1994 ->StoreAccumulatorInRegister(value_temp)
1995 .LoadAccumulatorWithRegister(destination);
1996
Ben Murdochc5610432016-08-08 18:44:38 +01001997 BuildHoleCheckForVariableAssignment(variable, op);
1998 builder()->LoadAccumulatorWithRegister(value_temp);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001999 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002000 builder()->StoreAccumulatorInRegister(destination);
2001 break;
2002 }
2003 case VariableLocation::GLOBAL:
2004 case VariableLocation::UNALLOCATED: {
2005 builder()->StoreGlobal(variable->name(), feedback_index(slot),
2006 language_mode());
2007 break;
2008 }
2009 case VariableLocation::CONTEXT: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002010 int depth = execution_context()->ContextChainDepth(variable->scope());
2011 ContextScope* context = execution_context()->Previous(depth);
2012 Register context_reg;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002013
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002014 if (context) {
2015 context_reg = context->reg();
2016 } else {
2017 Register value_temp = register_allocator()->NewRegister();
2018 context_reg = register_allocator()->NewRegister();
2019 // Walk the context chain to find the context at the given depth.
2020 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
2021 // a generic mechanism for performing jumps in interpreter.cc.
2022 // TODO(mythria): Also update bytecode graph builder with correct depth
2023 // when this changes.
2024 builder()
2025 ->StoreAccumulatorInRegister(value_temp)
2026 .LoadAccumulatorWithRegister(execution_context()->reg())
2027 .StoreAccumulatorInRegister(context_reg);
2028 for (int i = 0; i < depth; ++i) {
2029 builder()
2030 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
2031 .StoreAccumulatorInRegister(context_reg);
2032 }
2033 builder()->LoadAccumulatorWithRegister(value_temp);
2034 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002035
Ben Murdochc5610432016-08-08 18:44:38 +01002036 if (mode == CONST_LEGACY && op != Token::INIT) {
2037 if (is_strict(language_mode())) {
2038 builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
2039 0);
2040 }
2041 // Non-initializing assignments to legacy constants are ignored
2042 // in sloppy mode. Break here to avoid storing into variable.
2043 break;
2044 }
2045
Ben Murdoch097c5b22016-05-18 11:27:45 +01002046 if (hole_check_required) {
2047 // Load destination to check for hole.
2048 Register value_temp = register_allocator()->NewRegister();
2049 builder()
2050 ->StoreAccumulatorInRegister(value_temp)
2051 .LoadContextSlot(context_reg, variable->index());
2052
Ben Murdochc5610432016-08-08 18:44:38 +01002053 BuildHoleCheckForVariableAssignment(variable, op);
2054 builder()->LoadAccumulatorWithRegister(value_temp);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002055 }
2056
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002057 builder()->StoreContextSlot(context_reg, variable->index());
2058 break;
2059 }
2060 case VariableLocation::LOOKUP: {
Ben Murdochc5610432016-08-08 18:44:38 +01002061 DCHECK_NE(CONST_LEGACY, variable->mode());
2062 builder()->StoreLookupSlot(variable->name(), language_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002063 break;
2064 }
2065 }
2066}
2067
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002068void BytecodeGenerator::VisitAssignment(Assignment* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002069 DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
2070 Register object, key, home_object, value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002071 Handle<String> name;
2072
2073 // Left-hand side can only be a property, a global or a variable slot.
2074 Property* property = expr->target()->AsProperty();
2075 LhsKind assign_type = Property::GetAssignType(property);
2076
2077 // Evaluate LHS expression.
2078 switch (assign_type) {
2079 case VARIABLE:
2080 // Nothing to do to evaluate variable assignment LHS.
2081 break;
2082 case NAMED_PROPERTY: {
2083 object = VisitForRegisterValue(property->obj());
2084 name = property->key()->AsLiteral()->AsPropertyName();
2085 break;
2086 }
2087 case KEYED_PROPERTY: {
2088 object = VisitForRegisterValue(property->obj());
2089 if (expr->is_compound()) {
2090 // Use VisitForAccumulator and store to register so that the key is
2091 // still in the accumulator for loading the old value below.
2092 key = register_allocator()->NewRegister();
2093 VisitForAccumulatorValue(property->key());
2094 builder()->StoreAccumulatorInRegister(key);
2095 } else {
2096 key = VisitForRegisterValue(property->key());
2097 }
2098 break;
2099 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002100 case NAMED_SUPER_PROPERTY: {
2101 register_allocator()->PrepareForConsecutiveAllocations(4);
2102 object = register_allocator()->NextConsecutiveRegister();
2103 home_object = register_allocator()->NextConsecutiveRegister();
2104 key = register_allocator()->NextConsecutiveRegister();
2105 value = register_allocator()->NextConsecutiveRegister();
2106 SuperPropertyReference* super_property =
2107 property->obj()->AsSuperPropertyReference();
2108 VisitForRegisterValue(super_property->this_var(), object);
2109 VisitForRegisterValue(super_property->home_object(), home_object);
2110 builder()
2111 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2112 .StoreAccumulatorInRegister(key);
2113 break;
2114 }
2115 case KEYED_SUPER_PROPERTY: {
2116 register_allocator()->PrepareForConsecutiveAllocations(4);
2117 object = register_allocator()->NextConsecutiveRegister();
2118 home_object = register_allocator()->NextConsecutiveRegister();
2119 key = register_allocator()->NextConsecutiveRegister();
2120 value = register_allocator()->NextConsecutiveRegister();
2121 builder()->StoreAccumulatorInRegister(value);
2122 SuperPropertyReference* super_property =
2123 property->obj()->AsSuperPropertyReference();
2124 VisitForRegisterValue(super_property->this_var(), object);
2125 VisitForRegisterValue(super_property->home_object(), home_object);
2126 VisitForRegisterValue(property->key(), key);
2127 break;
2128 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002129 }
2130
2131 // Evaluate the value and potentially handle compound assignments by loading
2132 // the left-hand side value and performing a binary operation.
2133 if (expr->is_compound()) {
2134 Register old_value;
2135 switch (assign_type) {
2136 case VARIABLE: {
2137 VariableProxy* proxy = expr->target()->AsVariableProxy();
2138 old_value = VisitVariableLoadForRegisterValue(
2139 proxy->var(), proxy->VariableFeedbackSlot());
2140 break;
2141 }
2142 case NAMED_PROPERTY: {
2143 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2144 old_value = register_allocator()->NewRegister();
2145 builder()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002146 ->LoadNamedProperty(object, name, feedback_index(slot))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002147 .StoreAccumulatorInRegister(old_value);
2148 break;
2149 }
2150 case KEYED_PROPERTY: {
2151 // Key is already in accumulator at this point due to evaluating the
2152 // LHS above.
2153 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2154 old_value = register_allocator()->NewRegister();
2155 builder()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002156 ->LoadKeyedProperty(object, feedback_index(slot))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002157 .StoreAccumulatorInRegister(old_value);
2158 break;
2159 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002160 case NAMED_SUPER_PROPERTY: {
2161 old_value = register_allocator()->NewRegister();
2162 BuildNamedSuperPropertyLoad(object, home_object, key);
2163 builder()->StoreAccumulatorInRegister(old_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002164 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002165 }
2166 case KEYED_SUPER_PROPERTY: {
2167 old_value = register_allocator()->NewRegister();
2168 BuildKeyedSuperPropertyLoad(object, home_object, key);
2169 builder()->StoreAccumulatorInRegister(old_value);
2170 break;
2171 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002172 }
2173 VisitForAccumulatorValue(expr->value());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002174 builder()->BinaryOperation(expr->binary_op(), old_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002175 } else {
2176 VisitForAccumulatorValue(expr->value());
2177 }
2178
2179 // Store the value.
Ben Murdochda12d292016-06-02 14:46:10 +01002180 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002181 FeedbackVectorSlot slot = expr->AssignmentSlot();
2182 switch (assign_type) {
2183 case VARIABLE: {
2184 // TODO(oth): The VisitVariableAssignment() call is hard to reason about.
2185 // Is the value in the accumulator safe? Yes, but scary.
2186 Variable* variable = expr->target()->AsVariableProxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002187 VisitVariableAssignment(variable, expr->op(), slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002188 break;
2189 }
2190 case NAMED_PROPERTY:
2191 builder()->StoreNamedProperty(object, name, feedback_index(slot),
2192 language_mode());
2193 break;
2194 case KEYED_PROPERTY:
2195 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
2196 language_mode());
2197 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002198 case NAMED_SUPER_PROPERTY: {
2199 builder()->StoreAccumulatorInRegister(value);
2200 BuildNamedSuperPropertyStore(object, home_object, key, value);
2201 break;
2202 }
2203 case KEYED_SUPER_PROPERTY: {
2204 builder()->StoreAccumulatorInRegister(value);
2205 BuildKeyedSuperPropertyStore(object, home_object, key, value);
2206 break;
2207 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002208 }
2209 execution_result()->SetResultInAccumulator();
2210}
2211
Ben Murdochc5610432016-08-08 18:44:38 +01002212void BytecodeGenerator::VisitYield(Yield* expr) {
2213 builder()->SetExpressionPosition(expr);
2214 Register value = VisitForRegisterValue(expr->expression());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002215
Ben Murdochc5610432016-08-08 18:44:38 +01002216 Register generator = VisitForRegisterValue(expr->generator_object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002217
Ben Murdochc5610432016-08-08 18:44:38 +01002218 // Save context, registers, and state. Then return.
2219 builder()
2220 ->LoadLiteral(Smi::FromInt(expr->yield_id()))
2221 .SuspendGenerator(generator)
2222 .LoadAccumulatorWithRegister(value)
2223 .Return(); // Hard return (ignore any finally blocks).
2224
2225 builder()->Bind(&(generator_resume_points_[expr->yield_id()]));
2226 // Upon resume, we continue here.
2227
2228 {
2229 RegisterAllocationScope register_scope(this);
2230
2231 // Update state to indicate that we have finished resuming. Loop headers
2232 // rely on this.
2233 builder()
2234 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
2235 .StoreAccumulatorInRegister(generator_state_);
2236
2237 Register input = register_allocator()->NewRegister();
2238 builder()
Ben Murdoch61f157c2016-09-16 13:49:30 +01002239 ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator, 1)
Ben Murdochc5610432016-08-08 18:44:38 +01002240 .StoreAccumulatorInRegister(input);
2241
2242 Register resume_mode = register_allocator()->NewRegister();
2243 builder()
Ben Murdoch61f157c2016-09-16 13:49:30 +01002244 ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator, 1)
Ben Murdochc5610432016-08-08 18:44:38 +01002245 .StoreAccumulatorInRegister(resume_mode);
2246
2247 // Now dispatch on resume mode.
2248
2249 BytecodeLabel resume_with_next;
2250 BytecodeLabel resume_with_return;
2251 BytecodeLabel resume_with_throw;
2252
2253 builder()
2254 ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
2255 .CompareOperation(Token::EQ_STRICT, resume_mode)
2256 .JumpIfTrue(&resume_with_next)
2257 .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow))
2258 .CompareOperation(Token::EQ_STRICT, resume_mode)
2259 .JumpIfTrue(&resume_with_throw)
2260 .Jump(&resume_with_return);
2261
2262 builder()->Bind(&resume_with_return);
2263 {
2264 register_allocator()->PrepareForConsecutiveAllocations(2);
2265 Register value = register_allocator()->NextConsecutiveRegister();
2266 Register done = register_allocator()->NextConsecutiveRegister();
2267 builder()
2268 ->MoveRegister(input, value)
2269 .LoadTrue()
2270 .StoreAccumulatorInRegister(done)
Ben Murdoch61f157c2016-09-16 13:49:30 +01002271 .CallRuntime(Runtime::kInlineCreateIterResultObject, value, 2);
Ben Murdochc5610432016-08-08 18:44:38 +01002272 execution_control()->ReturnAccumulator();
2273 }
2274
2275 builder()->Bind(&resume_with_throw);
Ben Murdoch61f157c2016-09-16 13:49:30 +01002276 builder()->SetExpressionPosition(expr);
2277 builder()->LoadAccumulatorWithRegister(input).Throw();
Ben Murdochc5610432016-08-08 18:44:38 +01002278
2279 builder()->Bind(&resume_with_next);
2280 builder()->LoadAccumulatorWithRegister(input);
2281 }
2282 execution_result()->SetResultInAccumulator();
2283}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002284
2285void BytecodeGenerator::VisitThrow(Throw* expr) {
2286 VisitForAccumulatorValue(expr->exception());
Ben Murdochda12d292016-06-02 14:46:10 +01002287 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002288 builder()->Throw();
Ben Murdochc5610432016-08-08 18:44:38 +01002289 // Throw statements are modeled as expressions instead of statements. These
2290 // are converted from assignment statements in Rewriter::ReWrite pass. An
Ben Murdoch097c5b22016-05-18 11:27:45 +01002291 // assignment statement expects a value in the accumulator. This is a hack to
2292 // avoid DCHECK fails assert accumulator has been set.
2293 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002294}
2295
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002296void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
2297 LhsKind property_kind = Property::GetAssignType(expr);
2298 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
Ben Murdochda12d292016-06-02 14:46:10 +01002299 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002300 switch (property_kind) {
2301 case VARIABLE:
2302 UNREACHABLE();
2303 case NAMED_PROPERTY: {
2304 builder()->LoadNamedProperty(obj,
2305 expr->key()->AsLiteral()->AsPropertyName(),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002306 feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002307 break;
2308 }
2309 case KEYED_PROPERTY: {
2310 VisitForAccumulatorValue(expr->key());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002311 builder()->LoadKeyedProperty(obj, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002312 break;
2313 }
2314 case NAMED_SUPER_PROPERTY:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002315 VisitNamedSuperPropertyLoad(expr, Register::invalid_value());
2316 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002317 case KEYED_SUPER_PROPERTY:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002318 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value());
2319 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002320 }
2321 execution_result()->SetResultInAccumulator();
2322}
2323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002324void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj,
2325 Property* expr) {
2326 AccumulatorResultScope result_scope(this);
2327 VisitPropertyLoad(obj, expr);
2328}
2329
Ben Murdoch097c5b22016-05-18 11:27:45 +01002330void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
2331 Register opt_receiver_out) {
2332 RegisterAllocationScope register_scope(this);
2333 register_allocator()->PrepareForConsecutiveAllocations(3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002334
Ben Murdoch097c5b22016-05-18 11:27:45 +01002335 Register receiver, home_object, name;
2336 receiver = register_allocator()->NextConsecutiveRegister();
2337 home_object = register_allocator()->NextConsecutiveRegister();
2338 name = register_allocator()->NextConsecutiveRegister();
2339 SuperPropertyReference* super_property =
2340 property->obj()->AsSuperPropertyReference();
2341 VisitForRegisterValue(super_property->this_var(), receiver);
2342 VisitForRegisterValue(super_property->home_object(), home_object);
2343 builder()
2344 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2345 .StoreAccumulatorInRegister(name);
2346 BuildNamedSuperPropertyLoad(receiver, home_object, name);
2347
2348 if (opt_receiver_out.is_valid()) {
2349 builder()->MoveRegister(receiver, opt_receiver_out);
2350 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002351}
2352
Ben Murdoch097c5b22016-05-18 11:27:45 +01002353void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
2354 Register opt_receiver_out) {
2355 RegisterAllocationScope register_scope(this);
2356 register_allocator()->PrepareForConsecutiveAllocations(3);
2357
2358 Register receiver, home_object, key;
2359 receiver = register_allocator()->NextConsecutiveRegister();
2360 home_object = register_allocator()->NextConsecutiveRegister();
2361 key = register_allocator()->NextConsecutiveRegister();
2362 SuperPropertyReference* super_property =
2363 property->obj()->AsSuperPropertyReference();
2364 VisitForRegisterValue(super_property->this_var(), receiver);
2365 VisitForRegisterValue(super_property->home_object(), home_object);
2366 VisitForRegisterValue(property->key(), key);
2367 BuildKeyedSuperPropertyLoad(receiver, home_object, key);
2368
2369 if (opt_receiver_out.is_valid()) {
2370 builder()->MoveRegister(receiver, opt_receiver_out);
2371 }
2372}
2373
2374void BytecodeGenerator::VisitProperty(Property* expr) {
2375 LhsKind property_kind = Property::GetAssignType(expr);
2376 if (property_kind != NAMED_SUPER_PROPERTY &&
2377 property_kind != KEYED_SUPER_PROPERTY) {
2378 Register obj = VisitForRegisterValue(expr->obj());
2379 VisitPropertyLoad(obj, expr);
2380 } else {
2381 VisitPropertyLoad(Register::invalid_value(), expr);
2382 }
2383}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002384
2385Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
2386 if (args->length() == 0) {
2387 return Register();
2388 }
2389
2390 // Visit arguments and place in a contiguous block of temporary
2391 // registers. Return the first temporary register corresponding to
2392 // the first argument.
2393 //
2394 // NB the caller may have already called
2395 // PrepareForConsecutiveAllocations() with args->length() + N. The
2396 // second call here will be a no-op provided there have been N or
2397 // less calls to NextConsecutiveRegister(). Otherwise, the arguments
2398 // here will be consecutive, but they will not be consecutive with
2399 // earlier consecutive allocations made by the caller.
2400 register_allocator()->PrepareForConsecutiveAllocations(args->length());
2401
2402 // Visit for first argument that goes into returned register
2403 Register first_arg = register_allocator()->NextConsecutiveRegister();
2404 VisitForAccumulatorValue(args->at(0));
2405 builder()->StoreAccumulatorInRegister(first_arg);
2406
2407 // Visit remaining arguments
2408 for (int i = 1; i < static_cast<int>(args->length()); i++) {
2409 Register ith_arg = register_allocator()->NextConsecutiveRegister();
2410 VisitForAccumulatorValue(args->at(i));
2411 builder()->StoreAccumulatorInRegister(ith_arg);
2412 DCHECK(ith_arg.index() - i == first_arg.index());
2413 }
2414 return first_arg;
2415}
2416
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002417void BytecodeGenerator::VisitCall(Call* expr) {
2418 Expression* callee_expr = expr->expression();
2419 Call::CallType call_type = expr->GetCallType(isolate());
2420
Ben Murdoch097c5b22016-05-18 11:27:45 +01002421 if (call_type == Call::SUPER_CALL) {
2422 return VisitCallSuper(expr);
2423 }
2424
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002425 // Prepare the callee and the receiver to the function call. This depends on
2426 // the semantics of the underlying call type.
2427
2428 // The receiver and arguments need to be allocated consecutively for
2429 // Call(). We allocate the callee and receiver consecutively for calls to
Ben Murdoch097c5b22016-05-18 11:27:45 +01002430 // %LoadLookupSlotForCall. Future optimizations could avoid this there are
2431 // no arguments or the receiver and arguments are already consecutive.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002432 ZoneList<Expression*>* args = expr->arguments();
2433 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2);
2434 Register callee = register_allocator()->NextConsecutiveRegister();
2435 Register receiver = register_allocator()->NextConsecutiveRegister();
2436
2437 switch (call_type) {
2438 case Call::NAMED_PROPERTY_CALL:
2439 case Call::KEYED_PROPERTY_CALL: {
2440 Property* property = callee_expr->AsProperty();
2441 VisitForAccumulatorValue(property->obj());
2442 builder()->StoreAccumulatorInRegister(receiver);
2443 VisitPropertyLoadForAccumulator(receiver, property);
2444 builder()->StoreAccumulatorInRegister(callee);
2445 break;
2446 }
2447 case Call::GLOBAL_CALL: {
2448 // Receiver is undefined for global calls.
2449 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2450 // Load callee as a global variable.
2451 VariableProxy* proxy = callee_expr->AsVariableProxy();
2452 VisitVariableLoadForAccumulatorValue(proxy->var(),
2453 proxy->VariableFeedbackSlot());
2454 builder()->StoreAccumulatorInRegister(callee);
2455 break;
2456 }
2457 case Call::LOOKUP_SLOT_CALL:
2458 case Call::POSSIBLY_EVAL_CALL: {
2459 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) {
2460 RegisterAllocationScope inner_register_scope(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002461 Register name = register_allocator()->NewRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002462
Ben Murdoch097c5b22016-05-18 11:27:45 +01002463 // Call %LoadLookupSlotForCall to get the callee and receiver.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002464 DCHECK(Register::AreContiguous(callee, receiver));
2465 Variable* variable = callee_expr->AsVariableProxy()->var();
2466 builder()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002467 ->LoadLiteral(variable->name())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002468 .StoreAccumulatorInRegister(name)
Ben Murdoch097c5b22016-05-18 11:27:45 +01002469 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 1,
2470 callee);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002471 break;
2472 }
2473 // Fall through.
2474 DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL);
2475 }
2476 case Call::OTHER_CALL: {
2477 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2478 VisitForAccumulatorValue(callee_expr);
2479 builder()->StoreAccumulatorInRegister(callee);
2480 break;
2481 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002482 case Call::NAMED_SUPER_PROPERTY_CALL: {
2483 Property* property = callee_expr->AsProperty();
2484 VisitNamedSuperPropertyLoad(property, receiver);
2485 builder()->StoreAccumulatorInRegister(callee);
2486 break;
2487 }
2488 case Call::KEYED_SUPER_PROPERTY_CALL: {
2489 Property* property = callee_expr->AsProperty();
2490 VisitKeyedSuperPropertyLoad(property, receiver);
2491 builder()->StoreAccumulatorInRegister(callee);
2492 break;
2493 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002494 case Call::SUPER_CALL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002495 UNREACHABLE();
2496 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002497 }
2498
2499 // Evaluate all arguments to the function call and store in sequential
2500 // registers.
2501 Register arg = VisitArguments(args);
2502 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1);
2503
2504 // Resolve callee for a potential direct eval call. This block will mutate the
2505 // callee value.
2506 if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) {
2507 RegisterAllocationScope inner_register_scope(this);
Ben Murdochc5610432016-08-08 18:44:38 +01002508 register_allocator()->PrepareForConsecutiveAllocations(6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002509 Register callee_for_eval = register_allocator()->NextConsecutiveRegister();
2510 Register source = register_allocator()->NextConsecutiveRegister();
2511 Register function = register_allocator()->NextConsecutiveRegister();
2512 Register language = register_allocator()->NextConsecutiveRegister();
Ben Murdochc5610432016-08-08 18:44:38 +01002513 Register eval_scope_position =
2514 register_allocator()->NextConsecutiveRegister();
2515 Register eval_position = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002516
2517 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
2518 // strings and function closure, and loading language and
2519 // position.
2520 builder()
2521 ->MoveRegister(callee, callee_for_eval)
2522 .MoveRegister(arg, source)
2523 .MoveRegister(Register::function_closure(), function)
2524 .LoadLiteral(Smi::FromInt(language_mode()))
2525 .StoreAccumulatorInRegister(language)
2526 .LoadLiteral(
2527 Smi::FromInt(execution_context()->scope()->start_position()))
Ben Murdochc5610432016-08-08 18:44:38 +01002528 .StoreAccumulatorInRegister(eval_scope_position)
2529 .LoadLiteral(Smi::FromInt(expr->position()))
2530 .StoreAccumulatorInRegister(eval_position);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002531
2532 // Call ResolvePossiblyDirectEval and modify the callee.
2533 builder()
Ben Murdochc5610432016-08-08 18:44:38 +01002534 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 6)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002535 .StoreAccumulatorInRegister(callee);
2536 }
2537
Ben Murdoch097c5b22016-05-18 11:27:45 +01002538 builder()->SetExpressionPosition(expr);
2539 builder()->Call(callee, receiver, 1 + args->length(),
2540 feedback_index(expr->CallFeedbackICSlot()),
2541 expr->tail_call_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002542 execution_result()->SetResultInAccumulator();
2543}
2544
Ben Murdoch097c5b22016-05-18 11:27:45 +01002545void BytecodeGenerator::VisitCallSuper(Call* expr) {
2546 RegisterAllocationScope register_scope(this);
2547 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2548
2549 // Prepare the constructor to the super call.
2550 Register this_function = register_allocator()->NewRegister();
2551 VisitForAccumulatorValue(super->this_function_var());
2552 builder()
2553 ->StoreAccumulatorInRegister(this_function)
2554 .CallRuntime(Runtime::kInlineGetSuperConstructor, this_function, 1);
2555
2556 Register constructor = this_function; // Re-use dead this_function register.
2557 builder()->StoreAccumulatorInRegister(constructor);
2558
2559 ZoneList<Expression*>* args = expr->arguments();
2560 Register first_arg = VisitArguments(args);
2561
2562 // The new target is loaded into the accumulator from the
2563 // {new.target} variable.
2564 VisitForAccumulatorValue(super->new_target_var());
2565
2566 // Call construct.
2567 builder()->SetExpressionPosition(expr);
2568 builder()->New(constructor, first_arg, args->length());
2569 execution_result()->SetResultInAccumulator();
2570}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002571
2572void BytecodeGenerator::VisitCallNew(CallNew* expr) {
2573 Register constructor = register_allocator()->NewRegister();
2574 VisitForAccumulatorValue(expr->expression());
2575 builder()->StoreAccumulatorInRegister(constructor);
2576
2577 ZoneList<Expression*>* args = expr->arguments();
2578 Register first_arg = VisitArguments(args);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002579
2580 builder()->SetExpressionPosition(expr);
2581 // The accumulator holds new target which is the same as the
2582 // constructor for CallNew.
2583 builder()
2584 ->LoadAccumulatorWithRegister(constructor)
2585 .New(constructor, first_arg, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002586 execution_result()->SetResultInAccumulator();
2587}
2588
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002589void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2590 ZoneList<Expression*>* args = expr->arguments();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002591 if (expr->is_jsruntime()) {
2592 // Allocate a register for the receiver and load it with undefined.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002593 register_allocator()->PrepareForConsecutiveAllocations(1 + args->length());
2594 Register receiver = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002595 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002596 Register first_arg = VisitArguments(args);
2597 CHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1);
2598 builder()->CallJSRuntime(expr->context_index(), receiver,
2599 1 + args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002600 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002601 // Evaluate all arguments to the runtime call.
2602 Register first_arg = VisitArguments(args);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002603 Runtime::FunctionId function_id = expr->function()->function_id;
2604 builder()->CallRuntime(function_id, first_arg, args->length());
2605 }
2606 execution_result()->SetResultInAccumulator();
2607}
2608
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002609void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
2610 VisitForEffect(expr->expression());
2611 builder()->LoadUndefined();
2612 execution_result()->SetResultInAccumulator();
2613}
2614
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002615void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
2616 if (expr->expression()->IsVariableProxy()) {
2617 // Typeof does not throw a reference error on global variables, hence we
2618 // perform a non-contextual load in case the operand is a variable proxy.
2619 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2620 VisitVariableLoadForAccumulatorValue(
2621 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF);
2622 } else {
2623 VisitForAccumulatorValue(expr->expression());
2624 }
2625 builder()->TypeOf();
2626 execution_result()->SetResultInAccumulator();
2627}
2628
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002629void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
2630 VisitForAccumulatorValue(expr->expression());
2631 builder()->LogicalNot();
2632 execution_result()->SetResultInAccumulator();
2633}
2634
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002635void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2636 switch (expr->op()) {
2637 case Token::Value::NOT:
2638 VisitNot(expr);
2639 break;
2640 case Token::Value::TYPEOF:
2641 VisitTypeOf(expr);
2642 break;
2643 case Token::Value::VOID:
2644 VisitVoid(expr);
2645 break;
2646 case Token::Value::DELETE:
2647 VisitDelete(expr);
2648 break;
2649 case Token::Value::BIT_NOT:
2650 case Token::Value::ADD:
2651 case Token::Value::SUB:
2652 // These operators are converted to an equivalent binary operators in
2653 // the parser. These operators are not expected to be visited here.
2654 UNREACHABLE();
2655 default:
2656 UNREACHABLE();
2657 }
2658}
2659
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002660void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
2661 if (expr->expression()->IsProperty()) {
2662 // Delete of an object property is allowed both in sloppy
2663 // and strict modes.
2664 Property* property = expr->expression()->AsProperty();
2665 Register object = VisitForRegisterValue(property->obj());
2666 VisitForAccumulatorValue(property->key());
2667 builder()->Delete(object, language_mode());
2668 } else if (expr->expression()->IsVariableProxy()) {
2669 // Delete of an unqualified identifier is allowed in sloppy mode but is
2670 // not allowed in strict mode. Deleting 'this' is allowed in both modes.
2671 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2672 Variable* variable = proxy->var();
2673 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
2674 switch (variable->location()) {
2675 case VariableLocation::GLOBAL:
2676 case VariableLocation::UNALLOCATED: {
2677 // Global var, let, const or variables not explicitly declared.
2678 Register native_context = register_allocator()->NewRegister();
2679 Register global_object = register_allocator()->NewRegister();
2680 builder()
2681 ->LoadContextSlot(execution_context()->reg(),
2682 Context::NATIVE_CONTEXT_INDEX)
2683 .StoreAccumulatorInRegister(native_context)
2684 .LoadContextSlot(native_context, Context::EXTENSION_INDEX)
2685 .StoreAccumulatorInRegister(global_object)
2686 .LoadLiteral(variable->name())
2687 .Delete(global_object, language_mode());
2688 break;
2689 }
2690 case VariableLocation::PARAMETER:
2691 case VariableLocation::LOCAL:
2692 case VariableLocation::CONTEXT: {
2693 // Deleting local var/let/const, context variables, and arguments
2694 // does not have any effect.
2695 if (variable->HasThisName(isolate())) {
2696 builder()->LoadTrue();
2697 } else {
2698 builder()->LoadFalse();
2699 }
2700 break;
2701 }
2702 case VariableLocation::LOOKUP: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002703 Register name_reg = register_allocator()->NewRegister();
2704 builder()
2705 ->LoadLiteral(variable->name())
2706 .StoreAccumulatorInRegister(name_reg)
2707 .CallRuntime(Runtime::kDeleteLookupSlot, name_reg, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002708 break;
2709 }
2710 default:
2711 UNREACHABLE();
2712 }
2713 } else {
2714 // Delete of an unresolvable reference returns true.
2715 VisitForEffect(expr->expression());
2716 builder()->LoadTrue();
2717 }
2718 execution_result()->SetResultInAccumulator();
2719}
2720
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002721void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
2722 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2723
2724 // Left-hand side can only be a property, a global or a variable slot.
2725 Property* property = expr->expression()->AsProperty();
2726 LhsKind assign_type = Property::GetAssignType(property);
2727
2728 // TODO(rmcilroy): Set is_postfix to false if visiting for effect.
2729 bool is_postfix = expr->is_postfix();
2730
2731 // Evaluate LHS expression and get old value.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002732 Register object, home_object, key, old_value, value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002733 Handle<String> name;
2734 switch (assign_type) {
2735 case VARIABLE: {
2736 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2737 VisitVariableLoadForAccumulatorValue(proxy->var(),
2738 proxy->VariableFeedbackSlot());
2739 break;
2740 }
2741 case NAMED_PROPERTY: {
2742 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002743 object = VisitForRegisterValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002744 name = property->key()->AsLiteral()->AsPropertyName();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002745 builder()->LoadNamedProperty(object, name, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002746 break;
2747 }
2748 case KEYED_PROPERTY: {
2749 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002750 object = VisitForRegisterValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002751 // Use visit for accumulator here since we need the key in the accumulator
2752 // for the LoadKeyedProperty.
2753 key = register_allocator()->NewRegister();
2754 VisitForAccumulatorValue(property->key());
2755 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002756 object, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002757 break;
2758 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002759 case NAMED_SUPER_PROPERTY: {
2760 register_allocator()->PrepareForConsecutiveAllocations(4);
2761 object = register_allocator()->NextConsecutiveRegister();
2762 home_object = register_allocator()->NextConsecutiveRegister();
2763 key = register_allocator()->NextConsecutiveRegister();
2764 value = register_allocator()->NextConsecutiveRegister();
2765 SuperPropertyReference* super_property =
2766 property->obj()->AsSuperPropertyReference();
2767 VisitForRegisterValue(super_property->this_var(), object);
2768 VisitForRegisterValue(super_property->home_object(), home_object);
2769 builder()
2770 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2771 .StoreAccumulatorInRegister(key);
2772 BuildNamedSuperPropertyLoad(object, home_object, key);
2773 break;
2774 }
2775 case KEYED_SUPER_PROPERTY: {
2776 register_allocator()->PrepareForConsecutiveAllocations(4);
2777 object = register_allocator()->NextConsecutiveRegister();
2778 home_object = register_allocator()->NextConsecutiveRegister();
2779 key = register_allocator()->NextConsecutiveRegister();
2780 value = register_allocator()->NextConsecutiveRegister();
2781 builder()->StoreAccumulatorInRegister(value);
2782 SuperPropertyReference* super_property =
2783 property->obj()->AsSuperPropertyReference();
2784 VisitForRegisterValue(super_property->this_var(), object);
2785 VisitForRegisterValue(super_property->home_object(), home_object);
2786 VisitForRegisterValue(property->key(), key);
2787 BuildKeyedSuperPropertyLoad(object, home_object, key);
2788 break;
2789 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002790 }
2791
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002792 // Save result for postfix expressions.
2793 if (is_postfix) {
2794 old_value = register_allocator()->outer()->NewRegister();
Ben Murdochc5610432016-08-08 18:44:38 +01002795
2796 // Convert old value into a number before saving it.
2797 builder()->CastAccumulatorToNumber().StoreAccumulatorInRegister(old_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002798 }
2799
2800 // Perform +1/-1 operation.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002801 builder()->CountOperation(expr->binary_op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002802
2803 // Store the value.
Ben Murdochda12d292016-06-02 14:46:10 +01002804 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002805 FeedbackVectorSlot feedback_slot = expr->CountSlot();
2806 switch (assign_type) {
2807 case VARIABLE: {
2808 Variable* variable = expr->expression()->AsVariableProxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002809 VisitVariableAssignment(variable, expr->op(), feedback_slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002810 break;
2811 }
2812 case NAMED_PROPERTY: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002813 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002814 language_mode());
2815 break;
2816 }
2817 case KEYED_PROPERTY: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002818 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002819 language_mode());
2820 break;
2821 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002822 case NAMED_SUPER_PROPERTY: {
2823 builder()->StoreAccumulatorInRegister(value);
2824 BuildNamedSuperPropertyStore(object, home_object, key, value);
2825 break;
2826 }
2827 case KEYED_SUPER_PROPERTY: {
2828 builder()->StoreAccumulatorInRegister(value);
2829 BuildKeyedSuperPropertyStore(object, home_object, key, value);
2830 break;
2831 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002832 }
2833
2834 // Restore old value for postfix expressions.
2835 if (is_postfix) {
2836 execution_result()->SetResultInRegister(old_value);
2837 } else {
2838 execution_result()->SetResultInAccumulator();
2839 }
2840}
2841
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002842void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
2843 switch (binop->op()) {
2844 case Token::COMMA:
2845 VisitCommaExpression(binop);
2846 break;
2847 case Token::OR:
2848 VisitLogicalOrExpression(binop);
2849 break;
2850 case Token::AND:
2851 VisitLogicalAndExpression(binop);
2852 break;
2853 default:
2854 VisitArithmeticExpression(binop);
2855 break;
2856 }
2857}
2858
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002859void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2860 Register lhs = VisitForRegisterValue(expr->left());
2861 VisitForAccumulatorValue(expr->right());
Ben Murdochda12d292016-06-02 14:46:10 +01002862 builder()->SetExpressionPosition(expr);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002863 builder()->CompareOperation(expr->op(), lhs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002864 execution_result()->SetResultInAccumulator();
2865}
2866
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002867void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
2868 Register lhs = VisitForRegisterValue(expr->left());
2869 VisitForAccumulatorValue(expr->right());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002870 builder()->BinaryOperation(expr->op(), lhs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002871 execution_result()->SetResultInAccumulator();
2872}
2873
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002874void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
2875
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002876void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
2877 UNREACHABLE();
2878}
2879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002880void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
2881 execution_result()->SetResultInRegister(Register::function_closure());
2882}
2883
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002884void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002885 // Handled by VisitCall().
2886 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002887}
2888
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002889void BytecodeGenerator::VisitSuperPropertyReference(
2890 SuperPropertyReference* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002891 builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0);
2892 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002893}
2894
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002895void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
2896 VisitForEffect(binop->left());
2897 Visit(binop->right());
2898}
2899
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002900void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
2901 Expression* left = binop->left();
2902 Expression* right = binop->right();
2903
2904 // Short-circuit evaluation- If it is known that left is always true,
2905 // no need to visit right
2906 if (left->ToBooleanIsTrue()) {
2907 VisitForAccumulatorValue(left);
2908 } else {
2909 BytecodeLabel end_label;
2910 VisitForAccumulatorValue(left);
2911 builder()->JumpIfTrue(&end_label);
2912 VisitForAccumulatorValue(right);
2913 builder()->Bind(&end_label);
2914 }
2915 execution_result()->SetResultInAccumulator();
2916}
2917
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002918void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
2919 Expression* left = binop->left();
2920 Expression* right = binop->right();
2921
2922 // Short-circuit evaluation- If it is known that left is always false,
2923 // no need to visit right
2924 if (left->ToBooleanIsFalse()) {
2925 VisitForAccumulatorValue(left);
2926 } else {
2927 BytecodeLabel end_label;
2928 VisitForAccumulatorValue(left);
2929 builder()->JumpIfFalse(&end_label);
2930 VisitForAccumulatorValue(right);
2931 builder()->Bind(&end_label);
2932 }
2933 execution_result()->SetResultInAccumulator();
2934}
2935
Ben Murdoch097c5b22016-05-18 11:27:45 +01002936void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002937 Visit(expr->expression());
2938}
2939
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002940void BytecodeGenerator::VisitNewLocalFunctionContext() {
2941 AccumulatorResultScope accumulator_execution_result(this);
2942 Scope* scope = this->scope();
2943
2944 // Allocate a new local context.
2945 if (scope->is_script_scope()) {
2946 RegisterAllocationScope register_scope(this);
2947 Register closure = register_allocator()->NewRegister();
2948 Register scope_info = register_allocator()->NewRegister();
2949 DCHECK(Register::AreContiguous(closure, scope_info));
2950 builder()
2951 ->LoadAccumulatorWithRegister(Register::function_closure())
2952 .StoreAccumulatorInRegister(closure)
2953 .LoadLiteral(scope->GetScopeInfo(isolate()))
2954 .StoreAccumulatorInRegister(scope_info)
2955 .CallRuntime(Runtime::kNewScriptContext, closure, 2);
2956 } else {
2957 builder()->CallRuntime(Runtime::kNewFunctionContext,
2958 Register::function_closure(), 1);
2959 }
2960 execution_result()->SetResultInAccumulator();
2961}
2962
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002963void BytecodeGenerator::VisitBuildLocalActivationContext() {
2964 Scope* scope = this->scope();
2965
2966 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
2967 Variable* variable = scope->receiver();
2968 Register receiver(builder()->Parameter(0));
2969 // Context variable (at bottom of the context chain).
2970 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
2971 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
2972 execution_context()->reg(), variable->index());
2973 }
2974
2975 // Copy parameters into context if necessary.
2976 int num_parameters = scope->num_parameters();
2977 for (int i = 0; i < num_parameters; i++) {
2978 Variable* variable = scope->parameter(i);
2979 if (!variable->IsContextSlot()) continue;
2980
2981 // The parameter indices are shifted by 1 (receiver is variable
2982 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
2983 Register parameter(builder()->Parameter(i + 1));
2984 // Context variable (at bottom of the context chain).
2985 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
2986 builder()->LoadAccumulatorWithRegister(parameter)
2987 .StoreContextSlot(execution_context()->reg(), variable->index());
2988 }
2989}
2990
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002991void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
2992 AccumulatorResultScope accumulator_execution_result(this);
2993 DCHECK(scope->is_block_scope());
2994
2995 // Allocate a new local block context.
2996 register_allocator()->PrepareForConsecutiveAllocations(2);
2997 Register scope_info = register_allocator()->NextConsecutiveRegister();
2998 Register closure = register_allocator()->NextConsecutiveRegister();
2999
3000 builder()
3001 ->LoadLiteral(scope->GetScopeInfo(isolate()))
3002 .StoreAccumulatorInRegister(scope_info);
3003 VisitFunctionClosureForContext();
3004 builder()
3005 ->StoreAccumulatorInRegister(closure)
3006 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2);
3007 execution_result()->SetResultInAccumulator();
3008}
3009
Ben Murdoch097c5b22016-05-18 11:27:45 +01003010void BytecodeGenerator::VisitNewLocalWithContext() {
3011 AccumulatorResultScope accumulator_execution_result(this);
3012
3013 register_allocator()->PrepareForConsecutiveAllocations(2);
3014 Register extension_object = register_allocator()->NextConsecutiveRegister();
3015 Register closure = register_allocator()->NextConsecutiveRegister();
3016
3017 builder()->StoreAccumulatorInRegister(extension_object);
3018 VisitFunctionClosureForContext();
3019 builder()->StoreAccumulatorInRegister(closure).CallRuntime(
3020 Runtime::kPushWithContext, extension_object, 2);
3021 execution_result()->SetResultInAccumulator();
3022}
3023
3024void BytecodeGenerator::VisitNewLocalCatchContext(Variable* variable) {
3025 AccumulatorResultScope accumulator_execution_result(this);
3026 DCHECK(variable->IsContextSlot());
3027
3028 // Allocate a new local block context.
3029 register_allocator()->PrepareForConsecutiveAllocations(3);
3030 Register name = register_allocator()->NextConsecutiveRegister();
3031 Register exception = register_allocator()->NextConsecutiveRegister();
3032 Register closure = register_allocator()->NextConsecutiveRegister();
3033
3034 builder()
3035 ->StoreAccumulatorInRegister(exception)
3036 .LoadLiteral(variable->name())
3037 .StoreAccumulatorInRegister(name);
3038 VisitFunctionClosureForContext();
3039 builder()->StoreAccumulatorInRegister(closure).CallRuntime(
3040 Runtime::kPushCatchContext, name, 3);
3041 execution_result()->SetResultInAccumulator();
3042}
3043
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003044void BytecodeGenerator::VisitObjectLiteralAccessor(
3045 Register home_object, ObjectLiteralProperty* property, Register value_out) {
3046 // TODO(rmcilroy): Replace value_out with VisitForRegister();
3047 if (property == nullptr) {
3048 builder()->LoadNull().StoreAccumulatorInRegister(value_out);
3049 } else {
3050 VisitForAccumulatorValue(property->value());
3051 builder()->StoreAccumulatorInRegister(value_out);
3052 VisitSetHomeObject(value_out, home_object, property);
3053 }
3054}
3055
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003056void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
3057 ObjectLiteralProperty* property,
3058 int slot_number) {
3059 Expression* expr = property->value();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003060 if (FunctionLiteral::NeedsHomeObject(expr)) {
3061 Handle<Name> name = isolate()->factory()->home_object_symbol();
3062 FeedbackVectorSlot slot = property->GetSlot(slot_number);
3063 builder()
3064 ->LoadAccumulatorWithRegister(home_object)
3065 .StoreNamedProperty(value, name, feedback_index(slot), language_mode());
3066 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003067}
3068
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003069void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
3070 if (variable == nullptr) return;
3071
3072 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
3073
3074 // Allocate and initialize a new arguments object and assign to the
3075 // {arguments} variable.
3076 CreateArgumentsType type =
3077 is_strict(language_mode()) || !info()->has_simple_parameters()
3078 ? CreateArgumentsType::kUnmappedArguments
3079 : CreateArgumentsType::kMappedArguments;
3080 builder()->CreateArguments(type);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003081 VisitVariableAssignment(variable, Token::ASSIGN,
3082 FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003083}
3084
Ben Murdoch097c5b22016-05-18 11:27:45 +01003085void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
3086 if (rest == nullptr) return;
3087
3088 // Allocate and initialize a new rest parameter and assign to the {rest}
3089 // variable.
3090 builder()->CreateArguments(CreateArgumentsType::kRestParameter);
3091 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3092 VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid());
3093}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003094
3095void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
3096 if (variable == nullptr) return;
3097
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003098 // Store the closure we were called with in the given variable.
3099 builder()->LoadAccumulatorWithRegister(Register::function_closure());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003100 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003101}
3102
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003103void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
3104 if (variable == nullptr) return;
3105
3106 // Store the new target we were called with in the given variable.
3107 builder()->LoadAccumulatorWithRegister(Register::new_target());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003108 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003109}
3110
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003111void BytecodeGenerator::VisitFunctionClosureForContext() {
3112 AccumulatorResultScope accumulator_execution_result(this);
3113 Scope* closure_scope = execution_context()->scope()->ClosureScope();
3114 if (closure_scope->is_script_scope() ||
3115 closure_scope->is_module_scope()) {
3116 // Contexts nested in the native context have a canonical empty function as
3117 // their closure, not the anonymous closure containing the global code.
3118 Register native_context = register_allocator()->NewRegister();
3119 builder()
3120 ->LoadContextSlot(execution_context()->reg(),
3121 Context::NATIVE_CONTEXT_INDEX)
3122 .StoreAccumulatorInRegister(native_context)
3123 .LoadContextSlot(native_context, Context::CLOSURE_INDEX);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003124 } else if (closure_scope->is_eval_scope()) {
3125 // Contexts created by a call to eval have the same closure as the
3126 // context calling eval, not the anonymous closure containing the eval
3127 // code. Fetch it from the context.
3128 builder()->LoadContextSlot(execution_context()->reg(),
3129 Context::CLOSURE_INDEX);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003130 } else {
3131 DCHECK(closure_scope->is_function_scope());
3132 builder()->LoadAccumulatorWithRegister(Register::function_closure());
3133 }
3134 execution_result()->SetResultInAccumulator();
3135}
3136
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003137// Visits the expression |expr| and places the result in the accumulator.
3138void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
3139 AccumulatorResultScope accumulator_scope(this);
3140 Visit(expr);
3141}
3142
Ben Murdoch097c5b22016-05-18 11:27:45 +01003143void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
3144 if (expr == nullptr) {
3145 builder()->LoadTheHole();
3146 } else {
3147 VisitForAccumulatorValue(expr);
3148 }
3149}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003150
3151// Visits the expression |expr| and discards the result.
3152void BytecodeGenerator::VisitForEffect(Expression* expr) {
3153 EffectResultScope effect_scope(this);
3154 Visit(expr);
3155}
3156
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003157// Visits the expression |expr| and returns the register containing
3158// the expression result.
3159Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
3160 RegisterResultScope register_scope(this);
3161 Visit(expr);
3162 return register_scope.ResultRegister();
3163}
3164
Ben Murdoch097c5b22016-05-18 11:27:45 +01003165// Visits the expression |expr| and stores the expression result in
3166// |destination|.
3167void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
3168 Register destination) {
3169 AccumulatorResultScope register_scope(this);
3170 Visit(expr);
3171 builder()->StoreAccumulatorInRegister(destination);
3172}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003173
Ben Murdoch097c5b22016-05-18 11:27:45 +01003174void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
3175 ContextScope context_scope(this, scope);
3176 DCHECK(scope->declarations()->is_empty());
3177 Visit(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003178}
3179
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003180LanguageMode BytecodeGenerator::language_mode() const {
Ben Murdochda12d292016-06-02 14:46:10 +01003181 return execution_context()->scope()->language_mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003182}
3183
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003184int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
Ben Murdoch61f157c2016-09-16 13:49:30 +01003185 return TypeFeedbackVector::GetIndex(slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003186}
3187
3188} // namespace interpreter
3189} // namespace internal
3190} // namespace v8