 Chromium Code Reviews
 Chromium Code Reviews Issue 1403943004:
  [Interpreter] Add support for local context loads and stores.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@int_contextchain
    
  
    Issue 1403943004:
  [Interpreter] Add support for local context loads and stores.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@int_contextchain| OLD | NEW | 
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" | 
| 6 | 6 | 
| 7 #include <stack> | 7 #include <stack> | 
| 8 | 8 | 
| 9 #include "src/compiler.h" | 9 #include "src/compiler.h" | 
| 10 #include "src/interpreter/control-flow-builders.h" | 10 #include "src/interpreter/control-flow-builders.h" | 
| 11 #include "src/objects.h" | 11 #include "src/objects.h" | 
| 12 #include "src/parser.h" | 12 #include "src/parser.h" | 
| 13 #include "src/scopes.h" | 13 #include "src/scopes.h" | 
| 14 #include "src/token.h" | 14 #include "src/token.h" | 
| 15 | 15 | 
| 16 namespace v8 { | 16 namespace v8 { | 
| 17 namespace internal { | 17 namespace internal { | 
| 18 namespace interpreter { | 18 namespace interpreter { | 
| 19 | 19 | 
| 20 | 20 | 
| 21 // Scoped class tracking context objects created by the visitor. Represents | 21 // Scoped class tracking context objects created by the visitor. Represents | 
| 22 // mutations of the context chain within the function body, allowing pushing and | 22 // mutations of the context chain within the function body, allowing pushing and | 
| 23 // popping of the current {context_register} during visitation. | 23 // popping of the current {context_register} during visitation. | 
| 24 class BytecodeGenerator::ContextScope BASE_EMBEDDED { | 24 class BytecodeGenerator::ContextScope BASE_EMBEDDED { | 
| 25 public: | 25 public: | 
| 26 explicit ContextScope(BytecodeGenerator* generator, | 26 ContextScope(BytecodeGenerator* generator, Scope* scope, | 
| 27 bool is_function_context = false) | 27 bool should_pop_context = true) | 
| 28 : generator_(generator), | 28 : generator_(generator), | 
| 29 outer_(generator_->current_context()), | 29 scope_(scope), | 
| 30 is_function_context_(is_function_context) { | 30 outer_(generator_->execution_context()), | 
| 31 DCHECK(!is_function_context || | 31 register_(generator_->NextContextRegister()), | 
| 32 outer_.index() == Register::function_context().index()); | 32 depth_(0), | 
| 33 Register new_context_reg = NewContextRegister(); | 33 should_pop_context_(should_pop_context) { | 
| 34 generator_->builder()->PushContext(new_context_reg); | 34 if (outer_) { | 
| 35 generator_->set_current_context(new_context_reg); | 35 depth_ = outer_->depth_ + 1; | 
| 36 generator_->builder()->PushContext(register_); | |
| 37 } | |
| 38 generator_->set_execution_context(this); | |
| 36 } | 39 } | 
| 37 | 40 | 
| 38 ~ContextScope() { | 41 ~ContextScope() { | 
| 39 if (!is_function_context_) { | 42 if (should_pop_context_) { | 
| 
Michael Starzinger
2015/10/16 13:29:06
nit: Let's be defensive and keep checking "outer_
 
rmcilroy
2015/10/16 14:11:35
Ok, done.
 | |
| 40 generator_->builder()->PopContext(outer_); | 43 generator_->builder()->PopContext(outer_->reg()); | 
| 41 } | 44 } | 
| 42 generator_->set_current_context(outer_); | 45 generator_->set_execution_context(outer_); | 
| 43 } | 46 } | 
| 44 | 47 | 
| 45 private: | 48 // Returns the execution context for the given |scope| if it is a function | 
| 46 Register NewContextRegister() const { | 49 // local execution context, otherwise returns nullptr. | 
| 47 if (outer_.index() == Register::function_context().index()) { | 50 ContextScope* Previous(Scope* scope) { | 
| 48 return generator_->builder()->first_context_register(); | 51 int depth = scope_->ContextChainLength(scope); | 
| 49 } else { | 52 if (depth > depth_) { | 
| 50 DCHECK_LT(outer_.index(), | 53 return nullptr; | 
| 51 generator_->builder()->last_context_register().index()); | |
| 52 return Register(outer_.index() + 1); | |
| 53 } | 54 } | 
| 55 | |
| 56 ContextScope* previous = this; | |
| 57 for (int i = depth; i > 0; --i) { | |
| 58 previous = previous->outer_; | |
| 59 } | |
| 60 DCHECK_EQ(previous->scope_, scope); | |
| 61 return previous; | |
| 54 } | 62 } | 
| 55 | 63 | 
| 64 Scope* scope() const { return scope_; } | |
| 65 Register reg() const { return register_; } | |
| 66 | |
| 67 private: | |
| 56 BytecodeGenerator* generator_; | 68 BytecodeGenerator* generator_; | 
| 57 Register outer_; | 69 Scope* scope_; | 
| 58 bool is_function_context_; | 70 ContextScope* outer_; | 
| 71 Register register_; | |
| 72 int depth_; | |
| 73 bool should_pop_context_; | |
| 59 }; | 74 }; | 
| 60 | 75 | 
| 61 | 76 | 
| 62 // Scoped class for tracking control statements entered by the | 77 // Scoped class for tracking control statements entered by the | 
| 63 // visitor. The pattern derives AstGraphBuilder::ControlScope. | 78 // visitor. The pattern derives AstGraphBuilder::ControlScope. | 
| 64 class BytecodeGenerator::ControlScope BASE_EMBEDDED { | 79 class BytecodeGenerator::ControlScope BASE_EMBEDDED { | 
| 65 public: | 80 public: | 
| 66 explicit ControlScope(BytecodeGenerator* generator) | 81 explicit ControlScope(BytecodeGenerator* generator) | 
| 67 : generator_(generator), outer_(generator->control_scope()) { | 82 : generator_(generator), outer_(generator->execution_control()) { | 
| 68 generator_->set_control_scope(this); | 83 generator_->set_execution_control(this); | 
| 69 } | 84 } | 
| 70 virtual ~ControlScope() { generator_->set_control_scope(outer()); } | 85 virtual ~ControlScope() { generator_->set_execution_control(outer()); } | 
| 71 | 86 | 
| 72 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } | 87 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); } | 
| 73 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } | 88 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); } | 
| 74 | 89 | 
| 75 protected: | 90 protected: | 
| 76 enum Command { CMD_BREAK, CMD_CONTINUE }; | 91 enum Command { CMD_BREAK, CMD_CONTINUE }; | 
| 77 void PerformCommand(Command command, Statement* statement); | 92 void PerformCommand(Command command, Statement* statement); | 
| 78 virtual bool Execute(Command command, Statement* statement) = 0; | 93 virtual bool Execute(Command command, Statement* statement) = 0; | 
| 79 | 94 | 
| 80 BytecodeGenerator* generator() const { return generator_; } | 95 BytecodeGenerator* generator() const { return generator_; } | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 } | 146 } | 
| 132 | 147 | 
| 133 | 148 | 
| 134 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) | 149 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) | 
| 135 : isolate_(isolate), | 150 : isolate_(isolate), | 
| 136 zone_(zone), | 151 zone_(zone), | 
| 137 builder_(isolate, zone), | 152 builder_(isolate, zone), | 
| 138 info_(nullptr), | 153 info_(nullptr), | 
| 139 scope_(nullptr), | 154 scope_(nullptr), | 
| 140 globals_(0, zone), | 155 globals_(0, zone), | 
| 141 control_scope_(nullptr), | 156 execution_control_(nullptr), | 
| 142 current_context_(Register::function_context()) { | 157 execution_context_(nullptr) { | 
| 143 InitializeAstVisitor(isolate); | 158 InitializeAstVisitor(isolate); | 
| 144 } | 159 } | 
| 145 | 160 | 
| 146 | 161 | 
| 147 BytecodeGenerator::~BytecodeGenerator() {} | 162 BytecodeGenerator::~BytecodeGenerator() {} | 
| 148 | 163 | 
| 149 | 164 | 
| 150 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 165 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { | 
| 151 set_info(info); | 166 set_info(info); | 
| 152 set_scope(info->scope()); | 167 set_scope(info->scope()); | 
| 153 | 168 | 
| 169 // Initialize the incoming context. | |
| 170 ContextScope incoming_context(this, scope(), false); | |
| 171 | |
| 154 builder()->set_parameter_count(info->num_parameters_including_this()); | 172 builder()->set_parameter_count(info->num_parameters_including_this()); | 
| 155 builder()->set_locals_count(scope()->num_stack_slots()); | 173 builder()->set_locals_count(scope()->num_stack_slots()); | 
| 156 builder()->set_context_count(scope()->MaxNestedContextChainLength()); | 174 builder()->set_context_count(scope()->MaxNestedContextChainLength()); | 
| 157 | 175 | 
| 158 // Build function context only if there are context allocated variables. | 176 // Build function context only if there are context allocated variables. | 
| 159 if (scope()->NeedsContext()) { | 177 if (scope()->NeedsContext()) { | 
| 160 // Push a new inner context scope for the function. | 178 // Push a new inner context scope for the function. | 
| 161 VisitNewLocalFunctionContext(); | 179 VisitNewLocalFunctionContext(); | 
| 162 ContextScope top_context(this, true); | 180 ContextScope local_function_context(this, scope(), false); | 
| 181 VisitBuildLocalActivationContext(); | |
| 163 MakeBytecodeBody(); | 182 MakeBytecodeBody(); | 
| 164 } else { | 183 } else { | 
| 165 MakeBytecodeBody(); | 184 MakeBytecodeBody(); | 
| 166 } | 185 } | 
| 167 | 186 | 
| 168 set_scope(nullptr); | 187 set_scope(nullptr); | 
| 169 set_info(nullptr); | 188 set_info(nullptr); | 
| 170 return builder_.ToBytecodeArray(); | 189 return builder_.ToBytecodeArray(); | 
| 171 } | 190 } | 
| 172 | 191 | 
| 173 | 192 | 
| 174 void BytecodeGenerator::MakeBytecodeBody() { | 193 void BytecodeGenerator::MakeBytecodeBody() { | 
| 175 // Visit declarations within the function scope. | 194 // Visit declarations within the function scope. | 
| 176 VisitDeclarations(scope()->declarations()); | 195 VisitDeclarations(scope()->declarations()); | 
| 177 | 196 | 
| 178 // Visit statements in the function body. | 197 // Visit statements in the function body. | 
| 179 VisitStatements(info()->literal()->body()); | 198 VisitStatements(info()->literal()->body()); | 
| 180 } | 199 } | 
| 181 | 200 | 
| 182 | 201 | 
| 183 void BytecodeGenerator::VisitBlock(Block* node) { | 202 void BytecodeGenerator::VisitBlock(Block* stmt) { | 
| 184 builder()->EnterBlock(); | 203 builder()->EnterBlock(); | 
| 185 if (node->scope() == NULL) { | 204 if (stmt->scope() == NULL) { | 
| 186 // Visit statements in the same scope, no declarations. | 205 // Visit statements in the same scope, no declarations. | 
| 187 VisitStatements(node->statements()); | 206 VisitStatements(stmt->statements()); | 
| 188 } else { | 207 } else { | 
| 189 // Visit declarations and statements in a block scope. | 208 // Visit declarations and statements in a block scope. | 
| 190 if (node->scope()->ContextLocalCount() > 0) { | 209 if (stmt->scope()->NeedsContext()) { | 
| 191 UNIMPLEMENTED(); | 210 VisitNewLocalBlockContext(stmt->scope()); | 
| 211 ContextScope scope(this, stmt->scope()); | |
| 212 VisitDeclarations(stmt->scope()->declarations()); | |
| 213 VisitStatements(stmt->statements()); | |
| 192 } else { | 214 } else { | 
| 193 VisitDeclarations(node->scope()->declarations()); | 215 VisitDeclarations(stmt->scope()->declarations()); | 
| 194 VisitStatements(node->statements()); | 216 VisitStatements(stmt->statements()); | 
| 195 } | 217 } | 
| 196 } | 218 } | 
| 197 builder()->LeaveBlock(); | 219 builder()->LeaveBlock(); | 
| 198 } | 220 } | 
| 199 | 221 | 
| 200 | 222 | 
| 201 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { | 223 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) { | 
| 202 Variable* variable = decl->proxy()->var(); | 224 Variable* variable = decl->proxy()->var(); | 
| 203 VariableMode mode = decl->mode(); | 225 VariableMode mode = decl->mode(); | 
| 226 // Const and let variables are initialized with the hole so that we can | |
| 227 // check that they are only assigned once. | |
| 204 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; | 228 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET; | 
| 205 if (hole_init) { | |
| 206 UNIMPLEMENTED(); | |
| 207 } | |
| 208 switch (variable->location()) { | 229 switch (variable->location()) { | 
| 209 case VariableLocation::GLOBAL: | 230 case VariableLocation::GLOBAL: | 
| 210 case VariableLocation::UNALLOCATED: { | 231 case VariableLocation::UNALLOCATED: { | 
| 211 Handle<Oddball> value = variable->binding_needs_init() | 232 Handle<Oddball> value = variable->binding_needs_init() | 
| 212 ? isolate()->factory()->the_hole_value() | 233 ? isolate()->factory()->the_hole_value() | 
| 213 : isolate()->factory()->undefined_value(); | 234 : isolate()->factory()->undefined_value(); | 
| 214 globals()->push_back(variable->name()); | 235 globals()->push_back(variable->name()); | 
| 215 globals()->push_back(value); | 236 globals()->push_back(value); | 
| 216 break; | 237 break; | 
| 217 } | 238 } | 
| 239 case VariableLocation::LOCAL: | |
| 240 if (hole_init) { | |
| 241 Register destination(variable->index()); | |
| 242 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); | |
| 243 } | |
| 244 break; | |
| 218 case VariableLocation::PARAMETER: | 245 case VariableLocation::PARAMETER: | 
| 219 case VariableLocation::LOCAL: | 246 if (hole_init) { | 
| 220 // Details stored in scope, i.e. variable index. | 247 // The parameter indices are shifted by 1 (receiver is variable | 
| 248 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | |
| 249 Register destination(builder()->Parameter(variable->index() + 1)); | |
| 250 builder()->LoadTheHole().StoreAccumulatorInRegister(destination); | |
| 251 } | |
| 221 break; | 252 break; | 
| 222 case VariableLocation::CONTEXT: | 253 case VariableLocation::CONTEXT: | 
| 254 if (hole_init) { | |
| 255 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(), | |
| 256 variable->index()); | |
| 257 } | |
| 258 break; | |
| 223 case VariableLocation::LOOKUP: | 259 case VariableLocation::LOOKUP: | 
| 224 UNIMPLEMENTED(); | 260 UNIMPLEMENTED(); | 
| 225 break; | 261 break; | 
| 226 } | 262 } | 
| 227 } | 263 } | 
| 228 | 264 | 
| 229 | 265 | 
| 230 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 266 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) { | 
| 231 Variable* variable = decl->proxy()->var(); | 267 Variable* variable = decl->proxy()->var(); | 
| 232 switch (variable->location()) { | 268 switch (variable->location()) { | 
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 319 } | 355 } | 
| 320 | 356 | 
| 321 | 357 | 
| 322 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( | 358 void BytecodeGenerator::VisitSloppyBlockFunctionStatement( | 
| 323 SloppyBlockFunctionStatement* stmt) { | 359 SloppyBlockFunctionStatement* stmt) { | 
| 324 Visit(stmt->statement()); | 360 Visit(stmt->statement()); | 
| 325 } | 361 } | 
| 326 | 362 | 
| 327 | 363 | 
| 328 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 364 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) { | 
| 329 control_scope()->Continue(stmt->target()); | 365 execution_control()->Continue(stmt->target()); | 
| 330 } | 366 } | 
| 331 | 367 | 
| 332 | 368 | 
| 333 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 369 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { | 
| 334 control_scope()->Break(stmt->target()); | 370 execution_control()->Break(stmt->target()); | 
| 335 } | 371 } | 
| 336 | 372 | 
| 337 | 373 | 
| 338 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 374 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { | 
| 339 Visit(stmt->expression()); | 375 Visit(stmt->expression()); | 
| 340 builder()->Return(); | 376 builder()->Return(); | 
| 341 } | 377 } | 
| 342 | 378 | 
| 343 | 379 | 
| 344 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 380 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { | 
| 345 UNIMPLEMENTED(); | 381 UNIMPLEMENTED(); | 
| 346 } | 382 } | 
| 347 | 383 | 
| 348 | 384 | 
| 349 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 385 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { | 
| 350 UNIMPLEMENTED(); | 386 UNIMPLEMENTED(); | 
| 351 } | 387 } | 
| 352 | 388 | 
| 353 | 389 | 
| 354 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } | 390 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { UNIMPLEMENTED(); } | 
| 355 | 391 | 
| 356 | 392 | 
| 357 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 393 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { | 
| 358 LoopBuilder loop_builder(builder()); | 394 LoopBuilder loop_builder(builder()); | 
| 359 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 395 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 
| 360 | 396 | 
| 361 BytecodeLabel body_label, condition_label, done_label; | 397 BytecodeLabel body_label, condition_label, done_label; | 
| 362 builder()->Bind(&body_label); | 398 builder()->Bind(&body_label); | 
| 363 Visit(stmt->body()); | 399 Visit(stmt->body()); | 
| 364 builder()->Bind(&condition_label); | 400 builder()->Bind(&condition_label); | 
| 365 Visit(stmt->cond()); | 401 Visit(stmt->cond()); | 
| 366 builder()->JumpIfTrue(&body_label); | 402 builder()->JumpIfTrue(&body_label); | 
| 367 builder()->Bind(&done_label); | 403 builder()->Bind(&done_label); | 
| 368 | 404 | 
| 369 loop_builder.SetBreakTarget(done_label); | 405 loop_builder.SetBreakTarget(done_label); | 
| 370 loop_builder.SetContinueTarget(condition_label); | 406 loop_builder.SetContinueTarget(condition_label); | 
| 371 } | 407 } | 
| 372 | 408 | 
| 373 | 409 | 
| 374 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 410 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { | 
| 375 LoopBuilder loop_builder(builder()); | 411 LoopBuilder loop_builder(builder()); | 
| 376 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 412 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 
| 377 | 413 | 
| 378 BytecodeLabel body_label, condition_label, done_label; | 414 BytecodeLabel body_label, condition_label, done_label; | 
| 379 builder()->Jump(&condition_label); | 415 builder()->Jump(&condition_label); | 
| 380 builder()->Bind(&body_label); | 416 builder()->Bind(&body_label); | 
| 381 Visit(stmt->body()); | 417 Visit(stmt->body()); | 
| 382 builder()->Bind(&condition_label); | 418 builder()->Bind(&condition_label); | 
| 383 Visit(stmt->cond()); | 419 Visit(stmt->cond()); | 
| 384 builder()->JumpIfTrue(&body_label); | 420 builder()->JumpIfTrue(&body_label); | 
| 385 builder()->Bind(&done_label); | 421 builder()->Bind(&done_label); | 
| 386 | 422 | 
| 387 loop_builder.SetBreakTarget(done_label); | 423 loop_builder.SetBreakTarget(done_label); | 
| 388 loop_builder.SetContinueTarget(condition_label); | 424 loop_builder.SetContinueTarget(condition_label); | 
| 389 } | 425 } | 
| 390 | 426 | 
| 391 | 427 | 
| 392 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 428 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { | 
| 393 LoopBuilder loop_builder(builder()); | 429 LoopBuilder loop_builder(builder()); | 
| 394 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | 430 ControlScopeForIteration execution_control(this, stmt, &loop_builder); | 
| 395 | 431 | 
| 396 if (stmt->init() != nullptr) { | 432 if (stmt->init() != nullptr) { | 
| 397 Visit(stmt->init()); | 433 Visit(stmt->init()); | 
| 398 } | 434 } | 
| 399 | 435 | 
| 400 BytecodeLabel body_label, condition_label, next_label, done_label; | 436 BytecodeLabel body_label, condition_label, next_label, done_label; | 
| 401 if (stmt->cond() != nullptr) { | 437 if (stmt->cond() != nullptr) { | 
| 402 builder()->Jump(&condition_label); | 438 builder()->Jump(&condition_label); | 
| 403 } | 439 } | 
| 404 builder()->Bind(&body_label); | 440 builder()->Bind(&body_label); | 
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 588 } | 624 } | 
| 589 break; | 625 break; | 
| 590 case ObjectLiteral::Property::SETTER: | 626 case ObjectLiteral::Property::SETTER: | 
| 591 if (property->emit_store()) { | 627 if (property->emit_store()) { | 
| 592 accessor_table.lookup(literal_key)->second->setter = property; | 628 accessor_table.lookup(literal_key)->second->setter = property; | 
| 593 } | 629 } | 
| 594 break; | 630 break; | 
| 595 } | 631 } | 
| 596 } | 632 } | 
| 597 | 633 | 
| 598 // Create nodes to define accessors, using only a single call to the runtime | 634 // Define accessors, using only a single call to the runtime for each pair of | 
| 599 // for each pair of corresponding getters and setters. | 635 // corresponding getters and setters. | 
| 600 for (AccessorTable::Iterator it = accessor_table.begin(); | 636 for (AccessorTable::Iterator it = accessor_table.begin(); | 
| 601 it != accessor_table.end(); ++it) { | 637 it != accessor_table.end(); ++it) { | 
| 602 TemporaryRegisterScope inner_temporary_register_scope(builder()); | 638 TemporaryRegisterScope inner_temporary_register_scope(builder()); | 
| 603 Register name = inner_temporary_register_scope.NewRegister(); | 639 Register name = inner_temporary_register_scope.NewRegister(); | 
| 604 Register getter = inner_temporary_register_scope.NewRegister(); | 640 Register getter = inner_temporary_register_scope.NewRegister(); | 
| 605 Register setter = inner_temporary_register_scope.NewRegister(); | 641 Register setter = inner_temporary_register_scope.NewRegister(); | 
| 606 Register attr = inner_temporary_register_scope.NewRegister(); | 642 Register attr = inner_temporary_register_scope.NewRegister(); | 
| 607 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); | 643 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr)); | 
| 608 Visit(it->first); | 644 Visit(it->first); | 
| 609 builder()->StoreAccumulatorInRegister(name); | 645 builder()->StoreAccumulatorInRegister(name); | 
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 691 | 727 | 
| 692 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 728 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { | 
| 693 // Deep-copy the literal boilerplate. | 729 // Deep-copy the literal boilerplate. | 
| 694 builder() | 730 builder() | 
| 695 ->LoadLiteral(expr->constant_elements()) | 731 ->LoadLiteral(expr->constant_elements()) | 
| 696 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true)); | 732 .CreateArrayLiteral(expr->literal_index(), expr->ComputeFlags(true)); | 
| 697 | 733 | 
| 698 TemporaryRegisterScope temporary_register_scope(builder()); | 734 TemporaryRegisterScope temporary_register_scope(builder()); | 
| 699 Register index, literal; | 735 Register index, literal; | 
| 700 | 736 | 
| 701 // Create nodes to evaluate all the non-constant subexpressions and to store | 737 // Evaluate all the non-constant subexpressions and store them into the | 
| 702 // them into the newly cloned array. | 738 // newly cloned array. | 
| 703 bool literal_in_accumulator = true; | 739 bool literal_in_accumulator = true; | 
| 704 for (int array_index = 0; array_index < expr->values()->length(); | 740 for (int array_index = 0; array_index < expr->values()->length(); | 
| 705 array_index++) { | 741 array_index++) { | 
| 706 Expression* subexpr = expr->values()->at(array_index); | 742 Expression* subexpr = expr->values()->at(array_index); | 
| 707 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 743 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 
| 708 if (subexpr->IsSpread()) { | 744 if (subexpr->IsSpread()) { | 
| 709 // TODO(rmcilroy): Deal with spread expressions. | 745 // TODO(rmcilroy): Deal with spread expressions. | 
| 710 UNIMPLEMENTED(); | 746 UNIMPLEMENTED(); | 
| 711 } | 747 } | 
| 712 | 748 | 
| (...skipping 24 matching lines...) Expand all Loading... | |
| 737 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 773 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); | 
| 738 } | 774 } | 
| 739 | 775 | 
| 740 | 776 | 
| 741 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 777 void BytecodeGenerator::VisitVariableLoad(Variable* variable, | 
| 742 FeedbackVectorSlot slot) { | 778 FeedbackVectorSlot slot) { | 
| 743 switch (variable->location()) { | 779 switch (variable->location()) { | 
| 744 case VariableLocation::LOCAL: { | 780 case VariableLocation::LOCAL: { | 
| 745 Register source(variable->index()); | 781 Register source(variable->index()); | 
| 746 builder()->LoadAccumulatorWithRegister(source); | 782 builder()->LoadAccumulatorWithRegister(source); | 
| 783 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and | |
| 784 // let variables. | |
| 747 break; | 785 break; | 
| 748 } | 786 } | 
| 749 case VariableLocation::PARAMETER: { | 787 case VariableLocation::PARAMETER: { | 
| 750 // The parameter indices are shifted by 1 (receiver is variable | 788 // The parameter indices are shifted by 1 (receiver is variable | 
| 751 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 789 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | 
| 752 Register source(builder()->Parameter(variable->index() + 1)); | 790 Register source(builder()->Parameter(variable->index() + 1)); | 
| 753 builder()->LoadAccumulatorWithRegister(source); | 791 builder()->LoadAccumulatorWithRegister(source); | 
| 754 break; | 792 break; | 
| 755 } | 793 } | 
| 756 case VariableLocation::GLOBAL: { | 794 case VariableLocation::GLOBAL: { | 
| 757 // Global var, const, or let variable. | 795 // Global var, const, or let variable. | 
| 758 // TODO(rmcilroy): If context chain depth is short enough, do this using | 796 // TODO(rmcilroy): If context chain depth is short enough, do this using | 
| 759 // a generic version of LoadGlobalViaContextStub rather than calling the | 797 // a generic version of LoadGlobalViaContextStub rather than calling the | 
| 760 // runtime. | 798 // runtime. | 
| 761 DCHECK(variable->IsStaticGlobalObjectProperty()); | 799 DCHECK(variable->IsStaticGlobalObjectProperty()); | 
| 762 builder()->LoadGlobal(variable->index()); | 800 builder()->LoadGlobal(variable->index()); | 
| 763 break; | 801 break; | 
| 764 } | 802 } | 
| 765 case VariableLocation::UNALLOCATED: { | 803 case VariableLocation::UNALLOCATED: { | 
| 766 TemporaryRegisterScope temporary_register_scope(builder()); | 804 TemporaryRegisterScope temporary_register_scope(builder()); | 
| 767 Register obj = temporary_register_scope.NewRegister(); | 805 Register obj = temporary_register_scope.NewRegister(); | 
| 768 builder()->LoadContextSlot(current_context(), | 806 builder()->LoadContextSlot(execution_context()->reg(), | 
| 769 Context::GLOBAL_OBJECT_INDEX); | 807 Context::GLOBAL_OBJECT_INDEX); | 
| 770 builder()->StoreAccumulatorInRegister(obj); | 808 builder()->StoreAccumulatorInRegister(obj); | 
| 771 builder()->LoadLiteral(variable->name()); | 809 builder()->LoadLiteral(variable->name()); | 
| 772 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 810 builder()->LoadNamedProperty(obj, feedback_index(slot), language_mode()); | 
| 773 break; | 811 break; | 
| 774 } | 812 } | 
| 775 case VariableLocation::CONTEXT: | 813 case VariableLocation::CONTEXT: { | 
| 814 ContextScope* context = execution_context()->Previous(variable->scope()); | |
| 815 if (context) { | |
| 816 builder()->LoadContextSlot(context->reg(), variable->index()); | |
| 817 } else { | |
| 818 UNIMPLEMENTED(); | |
| 819 } | |
| 820 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and | |
| 821 // let variables. | |
| 822 break; | |
| 823 } | |
| 776 case VariableLocation::LOOKUP: | 824 case VariableLocation::LOOKUP: | 
| 777 UNIMPLEMENTED(); | 825 UNIMPLEMENTED(); | 
| 778 } | 826 } | 
| 779 } | 827 } | 
| 780 | 828 | 
| 781 | 829 | 
| 782 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 830 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, | 
| 783 FeedbackVectorSlot slot) { | 831 FeedbackVectorSlot slot) { | 
| 784 switch (variable->location()) { | 832 switch (variable->location()) { | 
| 785 case VariableLocation::LOCAL: { | 833 case VariableLocation::LOCAL: { | 
| (...skipping 19 matching lines...) Expand all Loading... | |
| 805 break; | 853 break; | 
| 806 } | 854 } | 
| 807 case VariableLocation::UNALLOCATED: { | 855 case VariableLocation::UNALLOCATED: { | 
| 808 TemporaryRegisterScope temporary_register_scope(builder()); | 856 TemporaryRegisterScope temporary_register_scope(builder()); | 
| 809 Register value = temporary_register_scope.NewRegister(); | 857 Register value = temporary_register_scope.NewRegister(); | 
| 810 Register obj = temporary_register_scope.NewRegister(); | 858 Register obj = temporary_register_scope.NewRegister(); | 
| 811 Register name = temporary_register_scope.NewRegister(); | 859 Register name = temporary_register_scope.NewRegister(); | 
| 812 // TODO(rmcilroy): Investigate whether we can avoid having to stash the | 860 // TODO(rmcilroy): Investigate whether we can avoid having to stash the | 
| 813 // value in a register. | 861 // value in a register. | 
| 814 builder()->StoreAccumulatorInRegister(value); | 862 builder()->StoreAccumulatorInRegister(value); | 
| 815 builder()->LoadContextSlot(current_context(), | 863 builder()->LoadContextSlot(execution_context()->reg(), | 
| 816 Context::GLOBAL_OBJECT_INDEX); | 864 Context::GLOBAL_OBJECT_INDEX); | 
| 817 builder()->StoreAccumulatorInRegister(obj); | 865 builder()->StoreAccumulatorInRegister(obj); | 
| 818 builder()->LoadLiteral(variable->name()); | 866 builder()->LoadLiteral(variable->name()); | 
| 819 builder()->StoreAccumulatorInRegister(name); | 867 builder()->StoreAccumulatorInRegister(name); | 
| 820 builder()->LoadAccumulatorWithRegister(value); | 868 builder()->LoadAccumulatorWithRegister(value); | 
| 821 builder()->StoreNamedProperty(obj, name, feedback_index(slot), | 869 builder()->StoreNamedProperty(obj, name, feedback_index(slot), | 
| 822 language_mode()); | 870 language_mode()); | 
| 823 break; | 871 break; | 
| 824 } | 872 } | 
| 825 case VariableLocation::CONTEXT: | 873 case VariableLocation::CONTEXT: { | 
| 874 // TODO(rmcilroy): support const mode initialization. | |
| 875 ContextScope* context = execution_context()->Previous(variable->scope()); | |
| 876 if (context) { | |
| 877 builder()->StoreContextSlot(context->reg(), variable->index()); | |
| 878 } else { | |
| 879 UNIMPLEMENTED(); | |
| 880 } | |
| 881 break; | |
| 882 } | |
| 826 case VariableLocation::LOOKUP: | 883 case VariableLocation::LOOKUP: | 
| 827 UNIMPLEMENTED(); | 884 UNIMPLEMENTED(); | 
| 828 } | 885 } | 
| 829 } | 886 } | 
| 830 | 887 | 
| 831 | 888 | 
| 832 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 889 void BytecodeGenerator::VisitAssignment(Assignment* expr) { | 
| 833 DCHECK(expr->target()->IsValidReferenceExpression()); | 890 DCHECK(expr->target()->IsValidReferenceExpression()); | 
| 834 TemporaryRegisterScope temporary_register_scope(builder()); | 891 TemporaryRegisterScope temporary_register_scope(builder()); | 
| 835 Register object, key; | 892 Register object, key; | 
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1134 builder() | 1191 builder() | 
| 1135 ->LoadAccumulatorWithRegister(Register::function_closure()) | 1192 ->LoadAccumulatorWithRegister(Register::function_closure()) | 
| 1136 .StoreAccumulatorInRegister(closure) | 1193 .StoreAccumulatorInRegister(closure) | 
| 1137 .LoadLiteral(scope->GetScopeInfo(isolate())) | 1194 .LoadLiteral(scope->GetScopeInfo(isolate())) | 
| 1138 .StoreAccumulatorInRegister(scope_info) | 1195 .StoreAccumulatorInRegister(scope_info) | 
| 1139 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 1196 .CallRuntime(Runtime::kNewScriptContext, closure, 2); | 
| 1140 } else { | 1197 } else { | 
| 1141 builder()->CallRuntime(Runtime::kNewFunctionContext, | 1198 builder()->CallRuntime(Runtime::kNewFunctionContext, | 
| 1142 Register::function_closure(), 1); | 1199 Register::function_closure(), 1); | 
| 1143 } | 1200 } | 
| 1201 } | |
| 1202 | |
| 1203 | |
| 1204 void BytecodeGenerator::VisitBuildLocalActivationContext() { | |
| 1205 Scope* scope = this->scope(); | |
| 1144 | 1206 | 
| 1145 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 1207 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) { | 
| 1146 UNIMPLEMENTED(); | 1208 UNIMPLEMENTED(); | 
| 1147 } | 1209 } | 
| 1148 | 1210 | 
| 1149 // Copy parameters into context if necessary. | 1211 // Copy parameters into context if necessary. | 
| 1150 int num_parameters = scope->num_parameters(); | 1212 int num_parameters = scope->num_parameters(); | 
| 1151 for (int i = 0; i < num_parameters; i++) { | 1213 for (int i = 0; i < num_parameters; i++) { | 
| 1152 Variable* variable = scope->parameter(i); | 1214 Variable* variable = scope->parameter(i); | 
| 1153 if (variable->IsContextSlot()) { | 1215 if (!variable->IsContextSlot()) continue; | 
| 1154 UNIMPLEMENTED(); | 1216 | 
| 1155 } | 1217 // The parameter indices are shifted by 1 (receiver is variable | 
| 1218 // index -1 but is parameter index 0 in BytecodeArrayBuilder). | |
| 1219 Register parameter(builder()->Parameter(i + 1)); | |
| 1220 // Context variable (at bottom of the context chain). | |
| 1221 DCHECK_EQ(0, scope->ContextChainLength(variable->scope())); | |
| 1222 builder()->LoadAccumulatorWithRegister(parameter) | |
| 1223 .StoreContextSlot(execution_context()->reg(), variable->index()); | |
| 1156 } | 1224 } | 
| 1157 } | 1225 } | 
| 1158 | 1226 | 
| 1159 | 1227 | 
| 1228 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) { | |
| 1229 DCHECK(scope->is_block_scope()); | |
| 1230 | |
| 1231 // Allocate a new local block context. | |
| 1232 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 1233 Register scope_info = temporary_register_scope.NewRegister(); | |
| 1234 Register closure = temporary_register_scope.NewRegister(); | |
| 1235 DCHECK(Register::AreContiguous(scope_info, closure)); | |
| 1236 builder() | |
| 1237 ->LoadLiteral(scope->GetScopeInfo(isolate())) | |
| 1238 .StoreAccumulatorInRegister(scope_info); | |
| 1239 VisitFunctionClosureForContext(); | |
| 1240 builder() | |
| 1241 ->StoreAccumulatorInRegister(closure) | |
| 1242 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2); | |
| 1243 } | |
| 1244 | |
| 1245 | |
| 1160 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { | 1246 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* binop) { | 
| 1161 Token::Value op = binop->op(); | 1247 Token::Value op = binop->op(); | 
| 1162 Expression* left = binop->left(); | 1248 Expression* left = binop->left(); | 
| 1163 Expression* right = binop->right(); | 1249 Expression* right = binop->right(); | 
| 1164 | 1250 | 
| 1165 TemporaryRegisterScope temporary_register_scope(builder()); | 1251 TemporaryRegisterScope temporary_register_scope(builder()); | 
| 1166 Register temporary = temporary_register_scope.NewRegister(); | 1252 Register temporary = temporary_register_scope.NewRegister(); | 
| 1167 | 1253 | 
| 1168 Visit(left); | 1254 Visit(left); | 
| 1169 builder()->StoreAccumulatorInRegister(temporary); | 1255 builder()->StoreAccumulatorInRegister(temporary); | 
| 1170 Visit(right); | 1256 Visit(right); | 
| 1171 builder()->BinaryOperation(op, temporary, language_mode_strength()); | 1257 builder()->BinaryOperation(op, temporary, language_mode_strength()); | 
| 1172 } | 1258 } | 
| 1173 | 1259 | 
| 1174 | 1260 | 
| 1175 void BytecodeGenerator::VisitObjectLiteralAccessor( | |
| 1176 Register home_object, ObjectLiteralProperty* property, Register value_out) { | |
| 1177 // TODO(rmcilroy): Replace value_out with VisitForRegister(); | |
| 1178 if (property == nullptr) { | |
| 1179 builder()->LoadNull().StoreAccumulatorInRegister(value_out); | |
| 1180 } else { | |
| 1181 Visit(property->value()); | |
| 1182 builder()->StoreAccumulatorInRegister(value_out); | |
| 1183 VisitSetHomeObject(value_out, home_object, property); | |
| 1184 } | |
| 1185 } | |
| 1186 | |
| 1187 | |
| 1188 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, | |
| 1189 ObjectLiteralProperty* property, | |
| 1190 int slot_number) { | |
| 1191 Expression* expr = property->value(); | |
| 1192 if (!FunctionLiteral::NeedsHomeObject(expr)) return; | |
| 1193 | |
| 1194 // TODO(rmcilroy): Remove UNIMPLEMENTED once we have tests for setting the | |
| 1195 // home object. | |
| 1196 UNIMPLEMENTED(); | |
| 1197 | |
| 1198 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 1199 Register name = temporary_register_scope.NewRegister(); | |
| 1200 isolate()->factory()->home_object_symbol(); | |
| 1201 builder() | |
| 1202 ->LoadLiteral(isolate()->factory()->home_object_symbol()) | |
| 1203 .StoreAccumulatorInRegister(name) | |
| 1204 .StoreNamedProperty(home_object, name, | |
| 1205 feedback_index(property->GetSlot(slot_number)), | |
| 1206 language_mode()); | |
| 1207 } | |
| 1208 | |
| 1209 | |
| 1210 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { | 1261 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) { | 
| 1211 Expression* left = binop->left(); | 1262 Expression* left = binop->left(); | 
| 1212 Expression* right = binop->right(); | 1263 Expression* right = binop->right(); | 
| 1213 | 1264 | 
| 1214 Visit(left); | 1265 Visit(left); | 
| 1215 Visit(right); | 1266 Visit(right); | 
| 1216 } | 1267 } | 
| 1217 | 1268 | 
| 1218 | 1269 | 
| 1219 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { | 1270 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) { | 
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1247 BytecodeLabel end_label; | 1298 BytecodeLabel end_label; | 
| 1248 | 1299 | 
| 1249 Visit(left); | 1300 Visit(left); | 
| 1250 builder()->JumpIfToBooleanFalse(&end_label); | 1301 builder()->JumpIfToBooleanFalse(&end_label); | 
| 1251 Visit(right); | 1302 Visit(right); | 
| 1252 builder()->Bind(&end_label); | 1303 builder()->Bind(&end_label); | 
| 1253 } | 1304 } | 
| 1254 } | 1305 } | 
| 1255 | 1306 | 
| 1256 | 1307 | 
| 1308 void BytecodeGenerator::VisitObjectLiteralAccessor( | |
| 1309 Register home_object, ObjectLiteralProperty* property, Register value_out) { | |
| 1310 // TODO(rmcilroy): Replace value_out with VisitForRegister(); | |
| 1311 if (property == nullptr) { | |
| 1312 builder()->LoadNull().StoreAccumulatorInRegister(value_out); | |
| 1313 } else { | |
| 1314 Visit(property->value()); | |
| 1315 builder()->StoreAccumulatorInRegister(value_out); | |
| 1316 VisitSetHomeObject(value_out, home_object, property); | |
| 1317 } | |
| 1318 } | |
| 1319 | |
| 1320 | |
| 1321 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object, | |
| 1322 ObjectLiteralProperty* property, | |
| 1323 int slot_number) { | |
| 1324 Expression* expr = property->value(); | |
| 1325 if (!FunctionLiteral::NeedsHomeObject(expr)) return; | |
| 1326 | |
| 1327 // TODO(rmcilroy): Remove UNIMPLEMENTED once we have tests for setting the | |
| 1328 // home object. | |
| 1329 UNIMPLEMENTED(); | |
| 1330 | |
| 1331 TemporaryRegisterScope temporary_register_scope(builder()); | |
| 1332 Register name = temporary_register_scope.NewRegister(); | |
| 1333 isolate()->factory()->home_object_symbol(); | |
| 1334 builder() | |
| 1335 ->LoadLiteral(isolate()->factory()->home_object_symbol()) | |
| 1336 .StoreAccumulatorInRegister(name) | |
| 1337 .StoreNamedProperty(home_object, name, | |
| 1338 feedback_index(property->GetSlot(slot_number)), | |
| 1339 language_mode()); | |
| 1340 } | |
| 1341 | |
| 1342 | |
| 1343 void BytecodeGenerator::VisitFunctionClosureForContext() { | |
| 1344 Scope* closure_scope = execution_context()->scope()->ClosureScope(); | |
| 1345 if (closure_scope->is_script_scope() || | |
| 1346 closure_scope->is_module_scope()) { | |
| 1347 // Contexts nested in the native context have a canonical empty function as | |
| 1348 // their closure, not the anonymous closure containing the global code. | |
| 1349 // Pass a SMI sentinel and let the runtime look up the empty function. | |
| 1350 builder()->LoadLiteral(Smi::FromInt(0)); | |
| 1351 } else { | |
| 1352 DCHECK(closure_scope->is_function_scope()); | |
| 1353 builder()->LoadAccumulatorWithRegister(Register::function_closure()); | |
| 1354 } | |
| 1355 } | |
| 1356 | |
| 1357 | |
| 1358 Register BytecodeGenerator::NextContextRegister() const { | |
| 1359 if (execution_context() == nullptr) { | |
| 1360 // Return the incoming function context for the outermost execution context. | |
| 1361 return Register::function_context(); | |
| 1362 } | |
| 1363 Register previous = execution_context()->reg(); | |
| 1364 if (previous == Register::function_context()) { | |
| 1365 // If the previous context was the incoming function context, then the next | |
| 1366 // context register is the first local context register. | |
| 1367 return builder_.first_context_register(); | |
| 1368 } else { | |
| 1369 // Otherwise use the next local context register. | |
| 1370 DCHECK_LT(previous.index(), builder_.last_context_register().index()); | |
| 1371 return Register(previous.index() + 1); | |
| 1372 } | |
| 1373 } | |
| 1374 | |
| 1375 | |
| 1257 LanguageMode BytecodeGenerator::language_mode() const { | 1376 LanguageMode BytecodeGenerator::language_mode() const { | 
| 1258 return info()->language_mode(); | 1377 return info()->language_mode(); | 
| 1259 } | 1378 } | 
| 1260 | 1379 | 
| 1261 | 1380 | 
| 1262 Strength BytecodeGenerator::language_mode_strength() const { | 1381 Strength BytecodeGenerator::language_mode_strength() const { | 
| 1263 return strength(language_mode()); | 1382 return strength(language_mode()); | 
| 1264 } | 1383 } | 
| 1265 | 1384 | 
| 1266 | 1385 | 
| 1267 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 1386 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 
| 1268 return info()->feedback_vector()->GetIndex(slot); | 1387 return info()->feedback_vector()->GetIndex(slot); | 
| 1269 } | 1388 } | 
| 1270 | 1389 | 
| 1271 } // namespace interpreter | 1390 } // namespace interpreter | 
| 1272 } // namespace internal | 1391 } // namespace internal | 
| 1273 } // namespace v8 | 1392 } // namespace v8 | 
| OLD | NEW |