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

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

Issue 1412683011: [Interpreter] Enable assignments in expressions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase. Created 5 years, 1 month 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/compiler.h" 7 #include "src/compiler.h"
8 #include "src/interpreter/control-flow-builders.h" 8 #include "src/interpreter/control-flow-builders.h"
9 #include "src/objects.h" 9 #include "src/objects.h"
10 #include "src/parser.h" 10 #include "src/parser.h"
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 ExpressionResultScope* outer_; 231 ExpressionResultScope* outer_;
232 TemporaryRegisterScope allocator_; 232 TemporaryRegisterScope allocator_;
233 bool result_identified_; 233 bool result_identified_;
234 234
235 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope); 235 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
236 }; 236 };
237 237
238 238
239 // Scoped class used when the result of the current expression is not 239 // Scoped class used when the result of the current expression is not
240 // expected to produce a result. 240 // expected to produce a result.
241 class BytecodeGenerator::EffectResultScope final 241 class BytecodeGenerator::EffectResultScope : public ExpressionResultScope {
rmcilroy 2015/11/05 16:34:51 Make final again
oth 2015/11/12 11:32:15 Done.
242 : public ExpressionResultScope {
243 public: 242 public:
244 explicit EffectResultScope(BytecodeGenerator* generator) 243 explicit EffectResultScope(BytecodeGenerator* generator)
245 : ExpressionResultScope(generator, Expression::kEffect) { 244 : ExpressionResultScope(generator, Expression::kEffect) {
246 set_result_identified(); 245 set_result_identified();
247 } 246 }
248 247
249 virtual void SetResultInAccumulator() {} 248 virtual void SetResultInAccumulator() {}
250 virtual void SetResultInRegister(Register reg) {} 249 virtual void SetResultInRegister(Register reg) {}
251 }; 250 };
252 251
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 set_result_identified(); 289 set_result_identified();
291 } 290 }
292 291
293 Register ResultRegister() const { return result_register_; } 292 Register ResultRegister() const { return result_register_; }
294 293
295 private: 294 private:
296 Register result_register_; 295 Register result_register_;
297 }; 296 };
298 297
299 298
299 // Scope providing protection against potentially conflicting patterns
300 // of variable loads and stores in binary expressions.
301 class BytecodeGenerator::AssignmentHazardScope final BASE_EMBEDDED {
302 public:
303 explicit AssignmentHazardScope(BytecodeGenerator* generator)
304 : alias_mappings_(generator->zone()),
305 aliased_locals_and_parameters_(generator->zone()),
306 register_scope_(generator->builder()) {
307 if (generator->assignment_hazard_scope() == nullptr) {
308 // Set self as the assignment_hazard_scope if one doesn't
309 // exist. Only the outermost participates in register remapping.
310 generator_ = generator;
311 generator->set_assignment_hazard_scope(this);
rmcilroy 2015/11/05 16:34:51 Rather than creating a map and set for each Assign
oth 2015/11/12 11:32:15 Okay, the helper class an inner class of BytecodeG
312 } else {
313 generator_ = nullptr;
314 }
315 }
316
317 ~AssignmentHazardScope() {
318 if (is_outermost_scope()) {
319 RestoreAliasedLocalsAndParameters();
320 generator()->set_assignment_hazard_scope(nullptr);
321 }
322 }
323
324 // Returns a register that a load instruction should use when
325 // loading from |reg|. This allows an alias for a modified version
326 // of |reg| to be used within a hazard regions.
327 MUST_USE_RESULT Register GetRegisterForLoad(Register reg) {
328 DCHECK(is_outermost_scope());
329 // A load from |reg| is to be issued. The register is placed in
330 // the mappings table initially mapping to itself. Future stores
331 // will update the mapping with temporaries thus preserving the
332 // original register's value.
333 //
334 // NB This insert only updates the table if no mapping exists
335 // already (std::map::insert semantics).
336 auto insert_result =
337 alias_mappings_.insert(std::make_pair(reg.index(), reg.index()));
338 auto mapping = insert_result.first;
339 // Return the current alias for reg.
340 return Register(mapping->second);
341 }
342
343 // Returns a register that a store instruction should use when
344 // loading from |reg|. This allows an alias for a modified version
345 // of |reg| to be used within hazard regions.
346 MUST_USE_RESULT Register GetRegisterForStore(Register reg) {
347 DCHECK(is_outermost_scope());
348 if (alias_mappings_.find(reg.index()) == alias_mappings_.end()) {
349 // If not in a hazard region or a load for this register has not
350 // occurred no mapping is necessary.
351 return reg;
352 } else {
353 // Storing to a register with 1 or more loads issued. The
354 // register is mapped to a temporary alias so we don't overwrite
355 // the lhs value, e.g. y = x + (x = 1); has a register for x on
356 // the lhs and needs a new register x' for the upcoming store on
357 // the rhs as the original x is an input to the add operation.
358 Register alias = register_scope_.NewRegister();
359 alias_mappings_[reg.index()] = alias.index();
360 if (generator()->builder()->RegisterIsParameterOrLocal(reg)) {
361 // Keep track of registers that need to be restored on exit
362 // from the assignment hazard region.
363 aliased_locals_and_parameters_.insert(reg.index());
364 }
365 return alias;
366 }
367 }
368
369 private:
370 void RestoreAliasedLocalsAndParameters() {
371 // Move temporary registers holding values for locals and
372 // parameters back into their local and parameter registers.
373 for (auto reg = aliased_locals_and_parameters_.begin();
374 reg != aliased_locals_and_parameters_.end(); reg++) {
375 auto mapping = alias_mappings_.find(*reg);
376 if (mapping != alias_mappings_.end()) {
377 builder()->MoveRegister(Register(mapping->second), Register(*reg));
378 }
379 }
380 alias_mappings_.clear();
381 aliased_locals_and_parameters_.clear();
382 }
383
384 BytecodeArrayBuilder* builder() const { return generator()->builder(); }
385 BytecodeGenerator* generator() const { return generator_; }
386 bool is_outermost_scope() const { return generator_ != nullptr; }
387
388 BytecodeGenerator* generator_;
389 ZoneMap<int, int> alias_mappings_;
390 ZoneSet<int> aliased_locals_and_parameters_;
391 TemporaryRegisterScope register_scope_;
392
393 DISALLOW_COPY_AND_ASSIGN(AssignmentHazardScope);
394 };
395
396
300 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone) 397 BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
301 : isolate_(isolate), 398 : isolate_(isolate),
302 zone_(zone), 399 zone_(zone),
303 builder_(isolate, zone), 400 builder_(isolate, zone),
304 info_(nullptr), 401 info_(nullptr),
305 scope_(nullptr), 402 scope_(nullptr),
306 globals_(0, zone), 403 globals_(0, zone),
307 execution_control_(nullptr), 404 execution_control_(nullptr),
308 execution_context_(nullptr), 405 execution_context_(nullptr),
309 execution_result_(nullptr), 406 execution_result_(nullptr),
310 binary_expression_depth_(0), 407 assignment_hazard_scope_(nullptr) {
311 binary_expression_hazard_set_(zone) {
312 InitializeAstVisitor(isolate); 408 InitializeAstVisitor(isolate);
313 } 409 }
314 410
315 411
316 BytecodeGenerator::~BytecodeGenerator() {} 412 BytecodeGenerator::~BytecodeGenerator() {}
317 413
318 414
319 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) { 415 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
320 set_info(info); 416 set_info(info);
321 set_scope(info->scope()); 417 set_scope(info->scope());
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 builder()->LoadLiteral(Smi::FromInt(encoded_flags)); 595 builder()->LoadLiteral(Smi::FromInt(encoded_flags));
500 builder()->StoreAccumulatorInRegister(flags); 596 builder()->StoreAccumulatorInRegister(flags);
501 DCHECK(flags.index() == pairs.index() + 1); 597 DCHECK(flags.index() == pairs.index() + 1);
502 598
503 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2); 599 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
504 globals()->clear(); 600 globals()->clear();
505 } 601 }
506 602
507 603
508 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) { 604 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
509 // TODO(rmcilroy): Replace this with a StatementResultScope when it exists. 605 EffectResultScope statement_result_scope(this);
510 EffectResultScope effect_scope(this);
511 VisitForEffect(stmt->expression()); 606 VisitForEffect(stmt->expression());
512 } 607 }
513 608
514 609
515 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) { 610 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
516 } 611 }
517 612
518 613
519 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) { 614 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
520 BytecodeLabel else_label, end_label; 615 BytecodeLabel else_label, end_label;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 execution_control()->Continue(stmt->target()); 647 execution_control()->Continue(stmt->target());
553 } 648 }
554 649
555 650
556 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) { 651 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
557 execution_control()->Break(stmt->target()); 652 execution_control()->Break(stmt->target());
558 } 653 }
559 654
560 655
561 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) { 656 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
562 EffectResultScope effect_scope(this); 657 EffectResultScope statement_result_scope(this);
563 VisitForAccumulatorValue(stmt->expression()); 658 VisitForAccumulatorValue(stmt->expression());
564 builder()->Return(); 659 builder()->Return();
565 } 660 }
566 661
567 662
568 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) { 663 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
569 UNIMPLEMENTED(); 664 UNIMPLEMENTED();
570 } 665 }
571 666
572 667
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) { 716 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
622 // Handled entirely in VisitSwitchStatement. 717 // Handled entirely in VisitSwitchStatement.
623 UNREACHABLE(); 718 UNREACHABLE();
624 } 719 }
625 720
626 721
627 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { 722 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
628 LoopBuilder loop_builder(builder()); 723 LoopBuilder loop_builder(builder());
629 ControlScopeForIteration execution_control(this, stmt, &loop_builder); 724 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
630 BytecodeLabel body_label, condition_label, done_label; 725 BytecodeLabel body_label, condition_label, done_label;
631
632 if (stmt->cond()->ToBooleanIsFalse()) { 726 if (stmt->cond()->ToBooleanIsFalse()) {
633 Visit(stmt->body()); 727 Visit(stmt->body());
634 // Bind condition_label and done_label for processing continue and break. 728 // Bind condition_label and done_label for processing continue and break.
635 builder()->Bind(&condition_label); 729 builder()->Bind(&condition_label);
636 builder()->Bind(&done_label); 730 builder()->Bind(&done_label);
637 } else { 731 } else {
638 builder()->Bind(&body_label); 732 builder()->Bind(&body_label);
639 Visit(stmt->body()); 733 Visit(stmt->body());
640 734
641 builder()->Bind(&condition_label); 735 builder()->Bind(&condition_label);
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 break; 851 break;
758 } 852 }
759 case NAMED_SUPER_PROPERTY: 853 case NAMED_SUPER_PROPERTY:
760 case KEYED_SUPER_PROPERTY: 854 case KEYED_SUPER_PROPERTY:
761 UNIMPLEMENTED(); 855 UNIMPLEMENTED();
762 } 856 }
763 } 857 }
764 858
765 859
766 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { 860 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
767 // TODO(oth): For now we need a parent scope for paths that end up 861 EffectResultScope statement_result_scope(this);
768 // in VisitLiteral which can allocate in the parent scope. A future
769 // CL in preparation will add a StatementResultScope that will
770 // remove the need for this EffectResultScope.
771 EffectResultScope result_scope(this);
772 862
773 if (stmt->subject()->IsNullLiteral() || 863 if (stmt->subject()->IsNullLiteral() ||
774 stmt->subject()->IsUndefinedLiteral(isolate())) { 864 stmt->subject()->IsUndefinedLiteral(isolate())) {
775 // ForIn generates lots of code, skip if it wouldn't produce any effects. 865 // ForIn generates lots of code, skip if it wouldn't produce any effects.
776 return; 866 return;
777 } 867 }
778 868
779 LoopBuilder loop_builder(builder()); 869 LoopBuilder loop_builder(builder());
780 ControlScopeForIteration control_scope(this, stmt, &loop_builder); 870 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
781 871
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
1191 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot()); 1281 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1192 } 1282 }
1193 1283
1194 1284
1195 void BytecodeGenerator::VisitVariableLoad(Variable* variable, 1285 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1196 FeedbackVectorSlot slot, 1286 FeedbackVectorSlot slot,
1197 TypeofMode typeof_mode) { 1287 TypeofMode typeof_mode) {
1198 switch (variable->location()) { 1288 switch (variable->location()) {
1199 case VariableLocation::LOCAL: { 1289 case VariableLocation::LOCAL: {
1200 Register source(Register(variable->index())); 1290 Register source(Register(variable->index()));
1291 if (assignment_hazard_scope()) {
1292 source = assignment_hazard_scope()->GetRegisterForLoad(source);
1293 }
1201 execution_result()->SetResultInRegister(source); 1294 execution_result()->SetResultInRegister(source);
1202 break; 1295 break;
1203 } 1296 }
1204 case VariableLocation::PARAMETER: { 1297 case VariableLocation::PARAMETER: {
1205 // The parameter indices are shifted by 1 (receiver is variable 1298 // The parameter indices are shifted by 1 (receiver is variable
1206 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1299 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1207 Register source = builder()->Parameter(variable->index() + 1); 1300 Register source = builder()->Parameter(variable->index() + 1);
1301 if (assignment_hazard_scope()) {
1302 source = assignment_hazard_scope()->GetRegisterForLoad(source);
1303 }
1208 execution_result()->SetResultInRegister(source); 1304 execution_result()->SetResultInRegister(source);
1209 break; 1305 break;
1210 } 1306 }
1211 case VariableLocation::GLOBAL: 1307 case VariableLocation::GLOBAL:
1212 case VariableLocation::UNALLOCATED: { 1308 case VariableLocation::UNALLOCATED: {
1213 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); 1309 size_t name_index = builder()->GetConstantPoolEntry(variable->name());
1214 builder()->LoadGlobal(name_index, feedback_index(slot), language_mode(), 1310 builder()->LoadGlobal(name_index, feedback_index(slot), language_mode(),
1215 typeof_mode); 1311 typeof_mode);
1216 execution_result()->SetResultInAccumulator(); 1312 execution_result()->SetResultInAccumulator();
1217 break; 1313 break;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 return register_scope.ResultRegister(); 1358 return register_scope.ResultRegister();
1263 } 1359 }
1264 1360
1265 1361
1266 void BytecodeGenerator::VisitVariableAssignment(Variable* variable, 1362 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
1267 FeedbackVectorSlot slot) { 1363 FeedbackVectorSlot slot) {
1268 switch (variable->location()) { 1364 switch (variable->location()) {
1269 case VariableLocation::LOCAL: { 1365 case VariableLocation::LOCAL: {
1270 // TODO(rmcilroy): support const mode initialization. 1366 // TODO(rmcilroy): support const mode initialization.
1271 Register destination(variable->index()); 1367 Register destination(variable->index());
1368 if (assignment_hazard_scope()) {
1369 destination =
1370 assignment_hazard_scope()->GetRegisterForStore(destination);
1371 }
1272 builder()->StoreAccumulatorInRegister(destination); 1372 builder()->StoreAccumulatorInRegister(destination);
1273 RecordStoreToRegister(destination);
1274 break; 1373 break;
1275 } 1374 }
1276 case VariableLocation::PARAMETER: { 1375 case VariableLocation::PARAMETER: {
1277 // The parameter indices are shifted by 1 (receiver is variable 1376 // The parameter indices are shifted by 1 (receiver is variable
1278 // index -1 but is parameter index 0 in BytecodeArrayBuilder). 1377 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1279 Register destination(builder()->Parameter(variable->index() + 1)); 1378 Register destination(builder()->Parameter(variable->index() + 1));
1379 if (assignment_hazard_scope()) {
1380 destination =
1381 assignment_hazard_scope()->GetRegisterForStore(destination);
1382 }
1280 builder()->StoreAccumulatorInRegister(destination); 1383 builder()->StoreAccumulatorInRegister(destination);
1281 RecordStoreToRegister(destination);
1282 break; 1384 break;
1283 } 1385 }
1284 case VariableLocation::GLOBAL: 1386 case VariableLocation::GLOBAL:
1285 case VariableLocation::UNALLOCATED: { 1387 case VariableLocation::UNALLOCATED: {
1286 size_t name_index = builder()->GetConstantPoolEntry(variable->name()); 1388 size_t name_index = builder()->GetConstantPoolEntry(variable->name());
1287 builder()->StoreGlobal(name_index, feedback_index(slot), language_mode()); 1389 builder()->StoreGlobal(name_index, feedback_index(slot), language_mode());
1288 break; 1390 break;
1289 } 1391 }
1290 case VariableLocation::CONTEXT: { 1392 case VariableLocation::CONTEXT: {
1291 // TODO(rmcilroy): support const mode initialization. 1393 // TODO(rmcilroy): support const mode initialization.
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
1818 VisitLogicalAndExpression(binop); 1920 VisitLogicalAndExpression(binop);
1819 break; 1921 break;
1820 default: 1922 default:
1821 VisitArithmeticExpression(binop); 1923 VisitArithmeticExpression(binop);
1822 break; 1924 break;
1823 } 1925 }
1824 } 1926 }
1825 1927
1826 1928
1827 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) { 1929 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1828 // TODO(oth): Remove PrepareForBinaryExpression/CompleteBinaryExpression 1930 // The evaluation of binary comparison expressions has an assignment
1829 // once we have StatementScope that tracks hazardous loads/stores. 1931 // hazard because the lhs may be a variable that evaluates to a
1830 PrepareForBinaryExpression(); 1932 // local or parameter and the rhs may modify that, e.g. y = x + (x = 1)
1933 // To get a correct result the generator treats the inner assigment
1934 // as being made to a temporary x' that is spilled on exit of the
1935 // assignment hazard.
1936 AssignmentHazardScope assignment_hazard_scope(this);
1937
1831 Register lhs = VisitForRegisterValue(expr->left()); 1938 Register lhs = VisitForRegisterValue(expr->left());
1832 if (builder()->RegisterIsParameterOrLocal(lhs)) {
1833 // Result was returned in an existing local or parameter. See if
1834 // it needs to be moved to a temporary.
1835 // TODO(oth) LoadFromAliasedRegister call into VisitVariableLoad().
1836 lhs = LoadFromAliasedRegister(lhs);
1837 }
1838 VisitForAccumulatorValue(expr->right()); 1939 VisitForAccumulatorValue(expr->right());
1839 builder()->CompareOperation(expr->op(), lhs, language_mode_strength()); 1940 builder()->CompareOperation(expr->op(), lhs, language_mode_strength());
1840 CompleteBinaryExpression();
1841 execution_result()->SetResultInAccumulator(); 1941 execution_result()->SetResultInAccumulator();
1842 } 1942 }
1843 1943
1844 1944
1845 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) { 1945 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
1846 // TODO(oth): Remove PrepareForBinaryExpression/CompleteBinaryExpression 1946 // The evaluation of binary arithmetic expressions has an assignment
1847 // once we have StatementScope that tracks hazardous loads/stores. 1947 // hazard because the lhs may be a variable that evaluates to a
1848 PrepareForBinaryExpression(); 1948 // local or parameter and the rhs may modify that, e.g. y = x + (x = 1)
1949 // To get a correct result the generator treats the inner assigment
1950 // as being made to a temporary x' that is spilled on exit of the
1951 // assignment hazard.
1952 AssignmentHazardScope assignment_hazard_scope(this);
1953
1849 Register lhs = VisitForRegisterValue(expr->left()); 1954 Register lhs = VisitForRegisterValue(expr->left());
1850 if (builder()->RegisterIsParameterOrLocal(lhs)) {
1851 // Result was returned in an existing local or parameter. See if
1852 // it needs to be moved to a temporary.
1853 // TODO(oth) LoadFromAliasedRegister call into VisitVariableLoad().
1854 lhs = LoadFromAliasedRegister(lhs);
1855 }
1856 VisitForAccumulatorValue(expr->right()); 1955 VisitForAccumulatorValue(expr->right());
1857 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength()); 1956 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength());
1858 CompleteBinaryExpression();
1859 execution_result()->SetResultInAccumulator(); 1957 execution_result()->SetResultInAccumulator();
1860 } 1958 }
1861 1959
1862 1960
1863 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); } 1961 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
1864 1962
1865 1963
1866 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) { 1964 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
1867 UNREACHABLE(); 1965 UNREACHABLE();
1868 } 1966 }
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
2069 // Pass a SMI sentinel and let the runtime look up the empty function. 2167 // Pass a SMI sentinel and let the runtime look up the empty function.
2070 builder()->LoadLiteral(Smi::FromInt(0)); 2168 builder()->LoadLiteral(Smi::FromInt(0));
2071 } else { 2169 } else {
2072 DCHECK(closure_scope->is_function_scope()); 2170 DCHECK(closure_scope->is_function_scope());
2073 builder()->LoadAccumulatorWithRegister(Register::function_closure()); 2171 builder()->LoadAccumulatorWithRegister(Register::function_closure());
2074 } 2172 }
2075 execution_result()->SetResultInAccumulator(); 2173 execution_result()->SetResultInAccumulator();
2076 } 2174 }
2077 2175
2078 2176
2079 void BytecodeGenerator::PrepareForBinaryExpression() {
2080 if (binary_expression_depth_++ == 0) {
2081 binary_expression_hazard_set_.clear();
2082 }
2083 }
2084
2085
2086 // Visits the expression |expr| and places the result in the accumulator. 2177 // Visits the expression |expr| and places the result in the accumulator.
2087 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) { 2178 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
2088 AccumulatorResultScope accumulator_scope(this); 2179 AccumulatorResultScope accumulator_scope(this);
2089 Visit(expr); 2180 Visit(expr);
2090 } 2181 }
2091 2182
2092 2183
2093 // Visits the expression |expr| and discards the result. 2184 // Visits the expression |expr| and discards the result.
2094 void BytecodeGenerator::VisitForEffect(Expression* expr) { 2185 void BytecodeGenerator::VisitForEffect(Expression* expr) {
2095 EffectResultScope effect_scope(this); 2186 EffectResultScope effect_scope(this);
2096 Visit(expr); 2187 Visit(expr);
2097 } 2188 }
2098 2189
2099 2190
2100 // Visits the expression |expr| and returns the register containing 2191 // Visits the expression |expr| and returns the register containing
2101 // the expression result. 2192 // the expression result.
2102 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) { 2193 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
2103 RegisterResultScope register_scope(this); 2194 RegisterResultScope register_scope(this);
2104 Visit(expr); 2195 Visit(expr);
2105 return register_scope.ResultRegister(); 2196 return register_scope.ResultRegister();
2106 } 2197 }
2107 2198
2108 2199
2109 Register BytecodeGenerator::LoadFromAliasedRegister(Register reg) {
2110 // TODO(oth): Follow on CL to load from re-map here.
2111 DCHECK(builder()->RegisterIsParameterOrLocal(reg));
2112 if (binary_expression_depth_ > 0) {
2113 binary_expression_hazard_set_.insert(reg.index());
2114 }
2115 return reg;
2116 }
2117
2118
2119 void BytecodeGenerator::RecordStoreToRegister(Register reg) {
2120 DCHECK(builder()->RegisterIsParameterOrLocal(reg));
2121 if (binary_expression_depth_ > 0) {
2122 // TODO(oth): a store to a register that's be loaded needs to be
2123 // remapped.
2124 DCHECK(binary_expression_hazard_set_.find(reg.index()) ==
2125 binary_expression_hazard_set_.end());
2126 }
2127 }
2128
2129
2130 void BytecodeGenerator::CompleteBinaryExpression() {
2131 DCHECK(binary_expression_depth_ > 0);
2132 binary_expression_depth_ -= 1;
2133 // TODO(oth): spill remapped registers into origins.
2134 // TODO(oth): make statement/top-level.
2135 }
2136
2137
2138 Register BytecodeGenerator::NextContextRegister() const { 2200 Register BytecodeGenerator::NextContextRegister() const {
2139 if (execution_context() == nullptr) { 2201 if (execution_context() == nullptr) {
2140 // Return the incoming function context for the outermost execution context. 2202 // Return the incoming function context for the outermost execution context.
2141 return Register::function_context(); 2203 return Register::function_context();
2142 } 2204 }
2143 Register previous = execution_context()->reg(); 2205 Register previous = execution_context()->reg();
2144 if (previous == Register::function_context()) { 2206 if (previous == Register::function_context()) {
2145 // If the previous context was the incoming function context, then the next 2207 // If the previous context was the incoming function context, then the next
2146 // context register is the first local context register. 2208 // context register is the first local context register.
2147 return builder_.first_context_register(); 2209 return builder_.first_context_register();
(...skipping 15 matching lines...) Expand all
2163 } 2225 }
2164 2226
2165 2227
2166 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { 2228 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2167 return info()->feedback_vector()->GetIndex(slot); 2229 return info()->feedback_vector()->GetIndex(slot);
2168 } 2230 }
2169 2231
2170 } // namespace interpreter 2232 } // namespace interpreter
2171 } // namespace internal 2233 } // namespace internal
2172 } // namespace v8 2234 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698