Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(521)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 1576403004: [Interpreter] Removes assignment hazard scope. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: rebased the patch Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "src/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/compiler.h" 8 #include "src/compiler.h"
9 #include "src/interpreter/control-flow-builders.h" 9 #include "src/interpreter/control-flow-builders.h"
10 #include "src/objects.h" 10 #include "src/objects.h"
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 207
208 Register NewRegister() { 208 Register NewRegister() {
209 ExpressionResultScope* current_scope = generator()->execution_result(); 209 ExpressionResultScope* current_scope = generator()->execution_result();
210 if ((current_scope == this) || 210 if ((current_scope == this) ||
211 (current_scope->outer() == this && 211 (current_scope->outer() == this &&
212 !current_scope->allocator_.hasConsecutiveAllocations())) { 212 !current_scope->allocator_.hasConsecutiveAllocations())) {
213 // Regular case - Allocating registers in current or outer context. 213 // Regular case - Allocating registers in current or outer context.
214 // VisitForRegisterValue allocates register in outer context. 214 // VisitForRegisterValue allocates register in outer context.
215 return allocator_.NewRegister(); 215 return allocator_.NewRegister();
216 } else { 216 } else {
217 // We need this when allocating registers due to an Assignment hazard. 217 // If it is required to allocate a register other than current or outer
218 // It might be expensive to walk the full context chain and compute the 218 // scopes, allocate a new temporary register. It might be expensive to
219 // list of consecutive reservations in the innerscopes. So allocates a 219 // walk the full context chain and compute the list of consecutive
220 // new unallocated temporary register. 220 // reservations in the innerscopes.
221 return allocator_.AllocateNewRegister(); 221 UNIMPLEMENTED();
222 return Register(-1);
222 } 223 }
223 } 224 }
224 225
225 void PrepareForConsecutiveAllocations(size_t count) { 226 void PrepareForConsecutiveAllocations(size_t count) {
226 allocator_.PrepareForConsecutiveAllocations(count); 227 allocator_.PrepareForConsecutiveAllocations(count);
227 } 228 }
228 229
229 Register NextConsecutiveRegister() { 230 Register NextConsecutiveRegister() {
230 return allocator_.NextConsecutiveRegister(); 231 return allocator_.NextConsecutiveRegister();
231 } 232 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 set_result_identified(); 306 set_result_identified();
306 } 307 }
307 308
308 Register ResultRegister() const { return result_register_; } 309 Register ResultRegister() const { return result_register_; }
309 310
310 private: 311 private:
311 Register result_register_; 312 Register result_register_;
312 }; 313 };
313 314
314 315
315 BytecodeGenerator::AssignmentHazardHelper::AssignmentHazardHelper(
316 BytecodeGenerator* generator)
317 : generator_(generator),
318 alias_mappings_(generator->zone()),
319 aliased_locals_and_parameters_(generator->zone()),
320 execution_result_(nullptr),
321 scope_depth_(0) {}
322
323
324 void BytecodeGenerator::AssignmentHazardHelper::EnterScope() {
325 DCHECK_GE(scope_depth_, 0);
326 if (scope_depth_++ == 0) {
327 execution_result_ = generator_->execution_result();
328 }
329 }
330
331
332 void BytecodeGenerator::AssignmentHazardHelper::LeaveScope() {
333 DCHECK_GT(scope_depth_, 0);
334 if (--scope_depth_ == 0) {
335 DCHECK_EQ(execution_result_, generator_->execution_result());
336 RestoreAliasedLocalsAndParameters();
337 }
338 }
339
340
341 // Returns a register that a load instruction should use when
342 // loading from |reg|. This allows an alias for a modified version
343 // of |reg| to be used within a hazard regions.
344 MUST_USE_RESULT Register
345 BytecodeGenerator::AssignmentHazardHelper::GetRegisterForLoad(Register reg) {
346 if (scope_depth_ == 0) {
347 return reg;
348 } else {
349 // A load from |reg| is to be issued. The register is placed in
350 // the mappings table initially mapping to itself. Future stores
351 // will update the mapping with temporaries thus preserving the
352 // original register's value.
353 //
354 // NB This insert only updates the table if no mapping exists
355 // already (std::map::insert semantics).
356 auto insert_result =
357 alias_mappings_.insert(std::make_pair(reg.index(), reg.index()));
358 auto mapping = insert_result.first;
359 // Return the current alias for reg.
360 return Register(mapping->second);
361 }
362 }
363
364
365 // Returns a register that a store instruction should use when
366 // loading from |reg|. This allows an alias for a modified version
367 // of |reg| to be used within hazard regions.
368 MUST_USE_RESULT Register
369 BytecodeGenerator::AssignmentHazardHelper::GetRegisterForStore(Register reg) {
370 if (scope_depth_ == 0 ||
371 alias_mappings_.find(reg.index()) == alias_mappings_.end()) {
372 // If not in a hazard region or a load for this register has not
373 // occurred no mapping is necessary.
374 return reg;
375 } else {
376 // Storing to a register with 1 or more loads issued. The
377 // register is mapped to a temporary alias so we don't overwrite
378 // the lhs value, e.g. y = x + (x = 1); has a register for x on
379 // the lhs and needs a new register x' for the upcoming store on
380 // the rhs as the original x is an input to the add operation.
381 Register alias = execution_result_->NewRegister();
382 alias_mappings_[reg.index()] = alias.index();
383 if (generator_->builder()->RegisterIsParameterOrLocal(reg)) {
384 // Keep track of registers that need to be restored on exit
385 // from the assignment hazard region.
386 aliased_locals_and_parameters_.insert(reg.index());
387 }
388 return alias;
389 }
390 }
391
392
393 void BytecodeGenerator::AssignmentHazardHelper::
394 RestoreAliasedLocalsAndParameters() {
395 DCHECK(scope_depth_ == 0);
396 // Move temporary registers holding values for locals and
397 // parameters back into their local and parameter registers.
398 for (auto reg = aliased_locals_and_parameters_.begin();
399 reg != aliased_locals_and_parameters_.end(); reg++) {
400 auto mapping = alias_mappings_.find(*reg);
401 if (mapping != alias_mappings_.end()) {
402 generator_->builder()->MoveRegister(Register(mapping->second),
403 Register(*reg));
404 }
405 }
406 alias_mappings_.clear();
407 aliased_locals_and_parameters_.clear();
408 }
409
410
411 class BytecodeGenerator::AssignmentHazardScope final {
412 public:
413 explicit AssignmentHazardScope(BytecodeGenerator* generator)
414 : generator_(generator) {
415 generator_->assignment_hazard_helper()->EnterScope();
416 }
417
418 ~AssignmentHazardScope() {
419 generator_->assignment_hazard_helper()->LeaveScope();
420 }
421
422 private:
423 BytecodeGenerator* generator_;
424
425 DISALLOW_COPY_AND_ASSIGN(AssignmentHazardScope);
426 };
427
428
429 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) 316 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
430 : isolate_(isolate), 317 : isolate_(isolate),
431 zone_(zone), 318 zone_(zone),
432 builder_(isolate, zone), 319 builder_(isolate, zone),
433 info_(nullptr), 320 info_(nullptr),
434 scope_(nullptr), 321 scope_(nullptr),
435 globals_(0, zone), 322 globals_(0, zone),
436 execution_control_(nullptr), 323 execution_control_(nullptr),
437 execution_context_(nullptr), 324 execution_context_(nullptr),
438 execution_result_(nullptr), 325 execution_result_(nullptr) {
439 assignment_hazard_helper_(this) {
440 InitializeAstVisitor(isolate); 326 InitializeAstVisitor(isolate);
441 } 327 }
442 328
443 329
444 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 330 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
445 set_info(info); 331 set_info(info);
446 set_scope(info->scope()); 332 set_scope(info->scope());
447 333
448 // Initialize the incoming context. 334 // Initialize the incoming context.
449 ContextScope incoming_context(this, scope(), false); 335 ContextScope incoming_context(this, scope(), false);
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 builder()->Return(); 587 builder()->Return();
702 } 588 }
703 589
704 590
705 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 591 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
706 UNIMPLEMENTED(); 592 UNIMPLEMENTED();
707 } 593 }
708 594
709 595
710 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 596 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
597 // We need this scope because we visit for register values. We have to
598 // maintain a execution result scope where registers can be allocated.
599 EffectResultScope effect_results_scope(this);
711 ZoneList<CaseClause*>* clauses = stmt->cases(); 600 ZoneList<CaseClause*>* clauses = stmt->cases();
712 SwitchBuilder switch_builder(builder(), clauses->length()); 601 SwitchBuilder switch_builder(builder(), clauses->length());
713 ControlScopeForBreakable scope(this, stmt, &switch_builder); 602 ControlScopeForBreakable scope(this, stmt, &switch_builder);
714 int default_index = -1; 603 int default_index = -1;
715 604
716 // Keep the switch value in a register until a case matches. 605 // Keep the switch value in a register until a case matches.
717 Register tag = VisitForRegisterValue(stmt->tag()); 606 Register tag = VisitForRegisterValue(stmt->tag());
718 607
719 // Iterate over all cases and create nodes for label comparison. 608 // Iterate over all cases and create nodes for label comparison.
720 BytecodeLabel done_label; 609 BytecodeLabel done_label;
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 1163 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1275 } 1164 }
1276 1165
1277 1166
1278 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 1167 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1279 FeedbackVectorSlot slot, 1168 FeedbackVectorSlot slot,
1280 TypeofMode typeof_mode) { 1169 TypeofMode typeof_mode) {
1281 switch (variable->location()) { 1170 switch (variable->location()) {
1282 case VariableLocation::LOCAL: { 1171 case VariableLocation::LOCAL: {
1283 Register source(Register(variable->index())); 1172 Register source(Register(variable->index()));
1284 source = assignment_hazard_helper()->GetRegisterForLoad(source); 1173 builder()->LoadAccumulatorWithRegister(source);
1285 execution_result()->SetResultInRegister(source); 1174 execution_result()->SetResultInAccumulator();
1286 break; 1175 break;
1287 } 1176 }
1288 case VariableLocation::PARAMETER: { 1177 case VariableLocation::PARAMETER: {
1289 // The parameter indices are shifted by 1 (receiver is variable 1178 // The parameter indices are shifted by 1 (receiver is variable
1290 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1179 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1291 Register source = builder()->Parameter(variable->index() + 1); 1180 Register source = builder()->Parameter(variable->index() + 1);
1292 source = assignment_hazard_helper()->GetRegisterForLoad(source); 1181 builder()->LoadAccumulatorWithRegister(source);
1293 execution_result()->SetResultInRegister(source); 1182 execution_result()->SetResultInAccumulator();
1294 break; 1183 break;
1295 } 1184 }
1296 case VariableLocation::GLOBAL: 1185 case VariableLocation::GLOBAL:
1297 case VariableLocation::UNALLOCATED: { 1186 case VariableLocation::UNALLOCATED: {
1298 builder()->LoadGlobal(variable->name(), feedback_index(slot), 1187 builder()->LoadGlobal(variable->name(), feedback_index(slot),
1299 language_mode(), typeof_mode); 1188 language_mode(), typeof_mode);
1300 execution_result()->SetResultInAccumulator(); 1189 execution_result()->SetResultInAccumulator();
1301 break; 1190 break;
1302 } 1191 }
1303 case VariableLocation::CONTEXT: { 1192 case VariableLocation::CONTEXT: {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 return register_scope.ResultRegister(); 1240 return register_scope.ResultRegister();
1352 } 1241 }
1353 1242
1354 1243
1355 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 1244 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
1356 FeedbackVectorSlot slot) { 1245 FeedbackVectorSlot slot) {
1357 switch (variable->location()) { 1246 switch (variable->location()) {
1358 case VariableLocation::LOCAL: { 1247 case VariableLocation::LOCAL: {
1359 // TODO(rmcilroy): support const mode initialization. 1248 // TODO(rmcilroy): support const mode initialization.
1360 Register destination(variable->index()); 1249 Register destination(variable->index());
1361 destination =
1362 assignment_hazard_helper()->GetRegisterForStore(destination);
1363 builder()->StoreAccumulatorInRegister(destination); 1250 builder()->StoreAccumulatorInRegister(destination);
1364 break; 1251 break;
1365 } 1252 }
1366 case VariableLocation::PARAMETER: { 1253 case VariableLocation::PARAMETER: {
1367 // The parameter indices are shifted by 1 (receiver is variable 1254 // The parameter indices are shifted by 1 (receiver is variable
1368 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1255 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1369 Register destination(builder()->Parameter(variable->index() + 1)); 1256 Register destination(builder()->Parameter(variable->index() + 1));
1370 destination =
1371 assignment_hazard_helper()->GetRegisterForStore(destination);
1372
1373 builder()->StoreAccumulatorInRegister(destination); 1257 builder()->StoreAccumulatorInRegister(destination);
1374 break; 1258 break;
1375 } 1259 }
1376 case VariableLocation::GLOBAL: 1260 case VariableLocation::GLOBAL:
1377 case VariableLocation::UNALLOCATED: { 1261 case VariableLocation::UNALLOCATED: {
1378 builder()->StoreGlobal(variable->name(), feedback_index(slot), 1262 builder()->StoreGlobal(variable->name(), feedback_index(slot),
1379 language_mode()); 1263 language_mode());
1380 break; 1264 break;
1381 } 1265 }
1382 case VariableLocation::CONTEXT: { 1266 case VariableLocation::CONTEXT: {
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after
1963 VisitLogicalAndExpression(binop); 1847 VisitLogicalAndExpression(binop);
1964 break; 1848 break;
1965 default: 1849 default:
1966 VisitArithmeticExpression(binop); 1850 VisitArithmeticExpression(binop);
1967 break; 1851 break;
1968 } 1852 }
1969 } 1853 }
1970 1854
1971 1855
1972 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1856 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1973 // The evaluation of binary comparison expressions has an assignment
1974 // hazard because the lhs may be a variable that evaluates to a
1975 // local or parameter and the rhs may modify that, e.g. y = x + (x = 1)
1976 // To get a correct result the generator treats the inner assigment
1977 // as being made to a temporary x' that is spilled on exit of the
1978 // assignment hazard.
1979 AssignmentHazardScope assignment_hazard_scope(this);
1980
1981 Register lhs = VisitForRegisterValue(expr->left()); 1857 Register lhs = VisitForRegisterValue(expr->left());
1982 VisitForAccumulatorValue(expr->right()); 1858 VisitForAccumulatorValue(expr->right());
1983 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); 1859 builder()->CompareOperation(expr->op(), lhs, language_mode_strength());
1984 execution_result()->SetResultInAccumulator(); 1860 execution_result()->SetResultInAccumulator();
1985 } 1861 }
1986 1862
1987 1863
1988 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { 1864 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
1989 // The evaluation of binary arithmetic expressions has an assignment
1990 // hazard because the lhs may be a variable that evaluates to a
1991 // local or parameter and the rhs may modify that, e.g. y = x + (x = 1)
1992 // To get a correct result the generator treats the inner assigment
1993 // as being made to a temporary x' that is spilled on exit of the
1994 // assignment hazard.
1995 AssignmentHazardScope assignment_hazard_scope(this);
1996
1997 Register lhs = VisitForRegisterValue(expr->left()); 1865 Register lhs = VisitForRegisterValue(expr->left());
1998 VisitForAccumulatorValue(expr->right()); 1866 VisitForAccumulatorValue(expr->right());
1999 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength()); 1867 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength());
2000 execution_result()->SetResultInAccumulator(); 1868 execution_result()->SetResultInAccumulator();
2001 } 1869 }
2002 1870
2003 1871
2004 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } 1872 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
2005 1873
2006 1874
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
2281 } 2149 }
2282 2150
2283 2151
2284 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2152 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2285 return info()->feedback_vector()->GetIndex(slot); 2153 return info()->feedback_vector()->GetIndex(slot);
2286 } 2154 }
2287 2155
2288 } // namespace interpreter 2156 } // namespace interpreter
2289 } // namespace internal 2157 } // namespace internal
2290 } // namespace v8 2158 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | test/cctest/interpreter/test-bytecode-generator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698