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

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: Skips failing mjsunit tests. 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 // Allocating a register other than the current or outer scope:
218 // It might be expensive to walk the full context chain and compute the 218 // It might be expensive to walk the full context chain and compute the
219 // list of consecutive reservations in the innerscopes. So allocates a 219 // list of consecutive reservations in the innerscopes. So allocates a
220 // new unallocated temporary register. 220 // new unallocated temporary register. We needed this in an implementation
221 // of Assignment hazard.
222 // TODO(mythria): Reevaluate this after we have the new assignment hazard
223 // implementation. Remove this if not required.
rmcilroy 2016/01/12 14:43:17 I'd rather just remove this now if it is no longer
mythria 2016/01/12 16:53:21 Done.
221 return allocator_.AllocateNewRegister(); 224 return allocator_.AllocateNewRegister();
222 } 225 }
223 } 226 }
224 227
225 void PrepareForConsecutiveAllocations(size_t count) { 228 void PrepareForConsecutiveAllocations(size_t count) {
226 allocator_.PrepareForConsecutiveAllocations(count); 229 allocator_.PrepareForConsecutiveAllocations(count);
227 } 230 }
228 231
229 Register NextConsecutiveRegister() { 232 Register NextConsecutiveRegister() {
230 return allocator_.NextConsecutiveRegister(); 233 return allocator_.NextConsecutiveRegister();
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 set_result_identified(); 308 set_result_identified();
306 } 309 }
307 310
308 Register ResultRegister() const { return result_register_; } 311 Register ResultRegister() const { return result_register_; }
309 312
310 private: 313 private:
311 Register result_register_; 314 Register result_register_;
312 }; 315 };
313 316
314 317
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) 318 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
430 : isolate_(isolate), 319 : isolate_(isolate),
431 zone_(zone), 320 zone_(zone),
432 builder_(isolate, zone), 321 builder_(isolate, zone),
433 info_(nullptr), 322 info_(nullptr),
434 scope_(nullptr), 323 scope_(nullptr),
435 globals_(0, zone), 324 globals_(0, zone),
436 execution_control_(nullptr), 325 execution_control_(nullptr),
437 execution_context_(nullptr), 326 execution_context_(nullptr),
438 execution_result_(nullptr), 327 execution_result_(nullptr) {
439 assignment_hazard_helper_(this) {
440 InitializeAstVisitor(isolate); 328 InitializeAstVisitor(isolate);
441 } 329 }
442 330
443 331
444 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 332 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
445 set_info(info); 333 set_info(info);
446 set_scope(info->scope()); 334 set_scope(info->scope());
447 335
448 // Initialize the incoming context. 336 // Initialize the incoming context.
449 ContextScope incoming_context(this, scope(), false); 337 ContextScope incoming_context(this, scope(), false);
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 builder()->Return(); 589 builder()->Return();
702 } 590 }
703 591
704 592
705 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 593 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
706 UNIMPLEMENTED(); 594 UNIMPLEMENTED();
707 } 595 }
708 596
709 597
710 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 598 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
599 // We need this scope because we visit for register values. We have to
600 // maintain a execution result scope where registers can be allocated.
601 EffectResultScope switch_result_scope(this);
rmcilroy 2016/01/12 14:43:17 nit - effect_results_scope
mythria 2016/01/12 16:53:21 Done.
711 ZoneList<CaseClause*>* clauses = stmt->cases(); 602 ZoneList<CaseClause*>* clauses = stmt->cases();
712 SwitchBuilder switch_builder(builder(), clauses->length()); 603 SwitchBuilder switch_builder(builder(), clauses->length());
713 ControlScopeForBreakable scope(this, stmt, &switch_builder); 604 ControlScopeForBreakable scope(this, stmt, &switch_builder);
714 int default_index = -1; 605 int default_index = -1;
715 606
716 // Keep the switch value in a register until a case matches. 607 // Keep the switch value in a register until a case matches.
717 Register tag = VisitForRegisterValue(stmt->tag()); 608 Register tag = VisitForRegisterValue(stmt->tag());
718 609
719 // Iterate over all cases and create nodes for label comparison. 610 // Iterate over all cases and create nodes for label comparison.
720 BytecodeLabel done_label; 611 BytecodeLabel done_label;
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 1165 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1275 } 1166 }
1276 1167
1277 1168
1278 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 1169 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1279 FeedbackVectorSlot slot, 1170 FeedbackVectorSlot slot,
1280 TypeofMode typeof_mode) { 1171 TypeofMode typeof_mode) {
1281 switch (variable->location()) { 1172 switch (variable->location()) {
1282 case VariableLocation::LOCAL: { 1173 case VariableLocation::LOCAL: {
1283 Register source(Register(variable->index())); 1174 Register source(Register(variable->index()));
1284 source = assignment_hazard_helper()->GetRegisterForLoad(source); 1175 builder()->LoadAccumulatorWithRegister(source);
1285 execution_result()->SetResultInRegister(source); 1176 execution_result()->SetResultInAccumulator();
1286 break; 1177 break;
1287 } 1178 }
1288 case VariableLocation::PARAMETER: { 1179 case VariableLocation::PARAMETER: {
1289 // The parameter indices are shifted by 1 (receiver is variable 1180 // The parameter indices are shifted by 1 (receiver is variable
1290 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1181 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1291 Register source = builder()->Parameter(variable->index() + 1); 1182 Register source = builder()->Parameter(variable->index() + 1);
1292 source = assignment_hazard_helper()->GetRegisterForLoad(source); 1183 builder()->LoadAccumulatorWithRegister(source);
1293 execution_result()->SetResultInRegister(source); 1184 execution_result()->SetResultInAccumulator();
1294 break; 1185 break;
1295 } 1186 }
1296 case VariableLocation::GLOBAL: 1187 case VariableLocation::GLOBAL:
1297 case VariableLocation::UNALLOCATED: { 1188 case VariableLocation::UNALLOCATED: {
1298 builder()->LoadGlobal(variable->name(), feedback_index(slot), 1189 builder()->LoadGlobal(variable->name(), feedback_index(slot),
1299 language_mode(), typeof_mode); 1190 language_mode(), typeof_mode);
1300 execution_result()->SetResultInAccumulator(); 1191 execution_result()->SetResultInAccumulator();
1301 break; 1192 break;
1302 } 1193 }
1303 case VariableLocation::CONTEXT: { 1194 case VariableLocation::CONTEXT: {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 return register_scope.ResultRegister(); 1242 return register_scope.ResultRegister();
1352 } 1243 }
1353 1244
1354 1245
1355 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 1246 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
1356 FeedbackVectorSlot slot) { 1247 FeedbackVectorSlot slot) {
1357 switch (variable->location()) { 1248 switch (variable->location()) {
1358 case VariableLocation::LOCAL: { 1249 case VariableLocation::LOCAL: {
1359 // TODO(rmcilroy): support const mode initialization. 1250 // TODO(rmcilroy): support const mode initialization.
1360 Register destination(variable->index()); 1251 Register destination(variable->index());
1361 destination =
1362 assignment_hazard_helper()->GetRegisterForStore(destination);
1363 builder()->StoreAccumulatorInRegister(destination); 1252 builder()->StoreAccumulatorInRegister(destination);
1364 break; 1253 break;
1365 } 1254 }
1366 case VariableLocation::PARAMETER: { 1255 case VariableLocation::PARAMETER: {
1367 // The parameter indices are shifted by 1 (receiver is variable 1256 // The parameter indices are shifted by 1 (receiver is variable
1368 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1257 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1369 Register destination(builder()->Parameter(variable->index() + 1)); 1258 Register destination(builder()->Parameter(variable->index() + 1));
1370 destination =
1371 assignment_hazard_helper()->GetRegisterForStore(destination);
1372
1373 builder()->StoreAccumulatorInRegister(destination); 1259 builder()->StoreAccumulatorInRegister(destination);
1374 break; 1260 break;
1375 } 1261 }
1376 case VariableLocation::GLOBAL: 1262 case VariableLocation::GLOBAL:
1377 case VariableLocation::UNALLOCATED: { 1263 case VariableLocation::UNALLOCATED: {
1378 builder()->StoreGlobal(variable->name(), feedback_index(slot), 1264 builder()->StoreGlobal(variable->name(), feedback_index(slot),
1379 language_mode()); 1265 language_mode());
1380 break; 1266 break;
1381 } 1267 }
1382 case VariableLocation::CONTEXT: { 1268 case VariableLocation::CONTEXT: {
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after
1963 VisitLogicalAndExpression(binop); 1849 VisitLogicalAndExpression(binop);
1964 break; 1850 break;
1965 default: 1851 default:
1966 VisitArithmeticExpression(binop); 1852 VisitArithmeticExpression(binop);
1967 break; 1853 break;
1968 } 1854 }
1969 } 1855 }
1970 1856
1971 1857
1972 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1858 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()); 1859 Register lhs = VisitForRegisterValue(expr->left());
1982 VisitForAccumulatorValue(expr->right()); 1860 VisitForAccumulatorValue(expr->right());
1983 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); 1861 builder()->CompareOperation(expr->op(), lhs, language_mode_strength());
1984 execution_result()->SetResultInAccumulator(); 1862 execution_result()->SetResultInAccumulator();
1985 } 1863 }
1986 1864
1987 1865
1988 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { 1866 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()); 1867 Register lhs = VisitForRegisterValue(expr->left());
1998 VisitForAccumulatorValue(expr->right()); 1868 VisitForAccumulatorValue(expr->right());
1999 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength()); 1869 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength());
2000 execution_result()->SetResultInAccumulator(); 1870 execution_result()->SetResultInAccumulator();
2001 } 1871 }
2002 1872
2003 1873
2004 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } 1874 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
2005 1875
2006 1876
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
2281 } 2151 }
2282 2152
2283 2153
2284 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2154 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2285 return info()->feedback_vector()->GetIndex(slot); 2155 return info()->feedback_vector()->GetIndex(slot);
2286 } 2156 }
2287 2157
2288 } // namespace interpreter 2158 } // namespace interpreter
2289 } // namespace internal 2159 } // namespace internal
2290 } // namespace v8 2160 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698