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

Side by Side Diff: src/x64/full-codegen-x64.cc

Issue 6113004: Version 3.0.7 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 9 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 | Annotate | Revision Log
« no previous file with comments | « src/x64/codegen-x64.cc ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 } 203 }
204 204
205 205
206 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) { 206 void FullCodeGenerator::EmitStackCheck(IterationStatement* stmt) {
207 Comment cmnt(masm_, "[ Stack check"); 207 Comment cmnt(masm_, "[ Stack check");
208 NearLabel ok; 208 NearLabel ok;
209 __ CompareRoot(rsp, Heap::kStackLimitRootIndex); 209 __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
210 __ j(above_equal, &ok); 210 __ j(above_equal, &ok);
211 StackCheckStub stub; 211 StackCheckStub stub;
212 __ CallStub(&stub); 212 __ CallStub(&stub);
213 // Record a mapping of this PC offset to the OSR id. This is used to find
214 // the AST id from the unoptimized code in order to use it as a key into
215 // the deoptimization input data found in the optimized code.
216 RecordStackCheck(stmt->OsrEntryId());
217
213 __ bind(&ok); 218 __ bind(&ok);
214 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS); 219 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
220 // Record a mapping of the OSR id to this PC. This is used if the OSR
221 // entry becomes the target of a bailout. We don't expect it to be, but
222 // we want it to work if it is.
215 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS); 223 PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
216 RecordStackCheck(stmt->OsrEntryId());
217 } 224 }
218 225
219 226
220 void FullCodeGenerator::EmitReturnSequence() { 227 void FullCodeGenerator::EmitReturnSequence() {
221 Comment cmnt(masm_, "[ Return sequence"); 228 Comment cmnt(masm_, "[ Return sequence");
222 if (return_label_.is_bound()) { 229 if (return_label_.is_bound()) {
223 __ jmp(&return_label_); 230 __ jmp(&return_label_);
224 } else { 231 } else {
225 __ bind(&return_label_); 232 __ bind(&return_label_);
226 if (FLAG_trace) { 233 if (FLAG_trace) {
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 459
453 460
454 void FullCodeGenerator::StackValueContext::Plug(bool flag) const { 461 void FullCodeGenerator::StackValueContext::Plug(bool flag) const {
455 Heap::RootListIndex value_root_index = 462 Heap::RootListIndex value_root_index =
456 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex; 463 flag ? Heap::kTrueValueRootIndex : Heap::kFalseValueRootIndex;
457 __ PushRoot(value_root_index); 464 __ PushRoot(value_root_index);
458 } 465 }
459 466
460 467
461 void FullCodeGenerator::TestContext::Plug(bool flag) const { 468 void FullCodeGenerator::TestContext::Plug(bool flag) const {
462 codegen()->PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL); 469 codegen()->PrepareForBailoutBeforeSplit(TOS_REG,
470 true,
471 true_label_,
472 false_label_);
463 if (flag) { 473 if (flag) {
464 if (true_label_ != fall_through_) __ jmp(true_label_); 474 if (true_label_ != fall_through_) __ jmp(true_label_);
465 } else { 475 } else {
466 if (false_label_ != fall_through_) __ jmp(false_label_); 476 if (false_label_ != fall_through_) __ jmp(false_label_);
467 } 477 }
468 } 478 }
469 479
470 480
471 void FullCodeGenerator::DoTest(Label* if_true, 481 void FullCodeGenerator::DoTest(Label* if_true,
472 Label* if_false, 482 Label* if_false,
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize; 558 int offset = FixedArray::kHeaderSize + dst->index() * kPointerSize;
549 __ RecordWrite(scratch1, offset, src, scratch2); 559 __ RecordWrite(scratch1, offset, src, scratch2);
550 } 560 }
551 } 561 }
552 562
553 563
554 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 564 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
555 bool should_normalize, 565 bool should_normalize,
556 Label* if_true, 566 Label* if_true,
557 Label* if_false) { 567 Label* if_false) {
568 // Only prepare for bailouts before splits if we're in a test
569 // context. Otherwise, we let the Visit function deal with the
570 // preparation to avoid preparing with the same AST id twice.
571 if (!context()->IsTest() || !info_->IsOptimizable()) return;
572
573 NearLabel skip;
574 if (should_normalize) __ jmp(&skip);
575
576 ForwardBailoutStack* current = forward_bailout_stack_;
577 while (current != NULL) {
578 PrepareForBailout(current->expr(), state);
579 current = current->parent();
580 }
581
582 if (should_normalize) {
583 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
584 Split(equal, if_true, if_false, NULL);
585 __ bind(&skip);
586 }
558 } 587 }
559 588
560 589
561 void FullCodeGenerator::EmitDeclaration(Variable* variable, 590 void FullCodeGenerator::EmitDeclaration(Variable* variable,
562 Variable::Mode mode, 591 Variable::Mode mode,
563 FunctionLiteral* function) { 592 FunctionLiteral* function) {
564 Comment cmnt(masm_, "[ Declaration"); 593 Comment cmnt(masm_, "[ Declaration");
565 ASSERT(variable != NULL); // Must have been resolved. 594 ASSERT(variable != NULL); // Must have been resolved.
566 Slot* slot = variable->AsSlot(); 595 Slot* slot = variable->AsSlot();
567 Property* prop = variable->AsProperty(); 596 Property* prop = variable->AsProperty();
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 __ Push(Smi::FromInt(is_eval() ? 1 : 0)); 691 __ Push(Smi::FromInt(is_eval() ? 1 : 0));
663 __ CallRuntime(Runtime::kDeclareGlobals, 3); 692 __ CallRuntime(Runtime::kDeclareGlobals, 3);
664 // Return value is ignored. 693 // Return value is ignored.
665 } 694 }
666 695
667 696
668 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 697 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
669 Comment cmnt(masm_, "[ SwitchStatement"); 698 Comment cmnt(masm_, "[ SwitchStatement");
670 Breakable nested_statement(this, stmt); 699 Breakable nested_statement(this, stmt);
671 SetStatementPosition(stmt); 700 SetStatementPosition(stmt);
701
672 // Keep the switch value on the stack until a case matches. 702 // Keep the switch value on the stack until a case matches.
673 VisitForStackValue(stmt->tag()); 703 VisitForStackValue(stmt->tag());
704 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
674 705
675 ZoneList<CaseClause*>* clauses = stmt->cases(); 706 ZoneList<CaseClause*>* clauses = stmt->cases();
676 CaseClause* default_clause = NULL; // Can occur anywhere in the list. 707 CaseClause* default_clause = NULL; // Can occur anywhere in the list.
677 708
678 Label next_test; // Recycled for each test. 709 Label next_test; // Recycled for each test.
679 // Compile all the tests with branches to their bodies. 710 // Compile all the tests with branches to their bodies.
680 for (int i = 0; i < clauses->length(); i++) { 711 for (int i = 0; i < clauses->length(); i++) {
681 CaseClause* clause = clauses->at(i); 712 CaseClause* clause = clauses->at(i);
682 // The default is not a test, but remember it as final fall through. 713 // The default is not a test, but remember it as final fall through.
683 if (clause->is_default()) { 714 if (clause->is_default()) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
728 759
729 // Compile all the case bodies. 760 // Compile all the case bodies.
730 for (int i = 0; i < clauses->length(); i++) { 761 for (int i = 0; i < clauses->length(); i++) {
731 Comment cmnt(masm_, "[ Case body"); 762 Comment cmnt(masm_, "[ Case body");
732 CaseClause* clause = clauses->at(i); 763 CaseClause* clause = clauses->at(i);
733 __ bind(clause->body_target()->entry_label()); 764 __ bind(clause->body_target()->entry_label());
734 VisitStatements(clause->statements()); 765 VisitStatements(clause->statements());
735 } 766 }
736 767
737 __ bind(nested_statement.break_target()); 768 __ bind(nested_statement.break_target());
769 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
738 } 770 }
739 771
740 772
741 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 773 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
742 Comment cmnt(masm_, "[ ForInStatement"); 774 Comment cmnt(masm_, "[ ForInStatement");
743 SetStatementPosition(stmt); 775 SetStatementPosition(stmt);
744 776
745 Label loop, exit; 777 Label loop, exit;
746 ForIn loop_statement(this, stmt); 778 ForIn loop_statement(this, stmt);
747 increment_loop_depth(); 779 increment_loop_depth();
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1249 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1218 // Fall through. 1250 // Fall through.
1219 case ObjectLiteral::Property::COMPUTED: 1251 case ObjectLiteral::Property::COMPUTED:
1220 if (key->handle()->IsSymbol()) { 1252 if (key->handle()->IsSymbol()) {
1221 VisitForAccumulatorValue(value); 1253 VisitForAccumulatorValue(value);
1222 __ Move(rcx, key->handle()); 1254 __ Move(rcx, key->handle());
1223 __ movq(rdx, Operand(rsp, 0)); 1255 __ movq(rdx, Operand(rsp, 0));
1224 if (property->emit_store()) { 1256 if (property->emit_store()) {
1225 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1257 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
1226 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1258 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1259 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1227 } 1260 }
1228 break; 1261 break;
1229 } 1262 }
1230 // Fall through. 1263 // Fall through.
1231 case ObjectLiteral::Property::PROTOTYPE: 1264 case ObjectLiteral::Property::PROTOTYPE:
1232 __ push(Operand(rsp, 0)); // Duplicate receiver. 1265 __ push(Operand(rsp, 0)); // Duplicate receiver.
1233 VisitForStackValue(key); 1266 VisitForStackValue(key);
1234 VisitForStackValue(value); 1267 VisitForStackValue(value);
1235 if (property->emit_store()) { 1268 if (property->emit_store()) {
1236 __ CallRuntime(Runtime::kSetProperty, 3); 1269 __ CallRuntime(Runtime::kSetProperty, 3);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1304 VisitForAccumulatorValue(subexpr); 1337 VisitForAccumulatorValue(subexpr);
1305 1338
1306 // Store the subexpression value in the array's elements. 1339 // Store the subexpression value in the array's elements.
1307 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 1340 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal.
1308 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 1341 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
1309 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1342 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1310 __ movq(FieldOperand(rbx, offset), result_register()); 1343 __ movq(FieldOperand(rbx, offset), result_register());
1311 1344
1312 // Update the write barrier for the array store. 1345 // Update the write barrier for the array store.
1313 __ RecordWrite(rbx, offset, result_register(), rcx); 1346 __ RecordWrite(rbx, offset, result_register(), rcx);
1347
1348 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1314 } 1349 }
1315 1350
1316 if (result_saved) { 1351 if (result_saved) {
1317 context()->PlugTOS(); 1352 context()->PlugTOS();
1318 } else { 1353 } else {
1319 context()->Plug(rax); 1354 context()->Plug(rax);
1320 } 1355 }
1321 } 1356 }
1322 1357
1323 1358
(...skipping 24 matching lines...) Expand all
1348 break; 1383 break;
1349 case NAMED_PROPERTY: 1384 case NAMED_PROPERTY:
1350 if (expr->is_compound()) { 1385 if (expr->is_compound()) {
1351 // We need the receiver both on the stack and in the accumulator. 1386 // We need the receiver both on the stack and in the accumulator.
1352 VisitForAccumulatorValue(property->obj()); 1387 VisitForAccumulatorValue(property->obj());
1353 __ push(result_register()); 1388 __ push(result_register());
1354 } else { 1389 } else {
1355 VisitForStackValue(property->obj()); 1390 VisitForStackValue(property->obj());
1356 } 1391 }
1357 break; 1392 break;
1358 case KEYED_PROPERTY: 1393 case KEYED_PROPERTY: {
1359 if (expr->is_compound()) { 1394 if (expr->is_compound()) {
1360 VisitForStackValue(property->obj()); 1395 if (property->is_arguments_access()) {
1361 VisitForAccumulatorValue(property->key()); 1396 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1397 MemOperand slot_operand =
1398 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1399 __ push(slot_operand);
1400 __ Move(rax, property->key()->AsLiteral()->handle());
1401 } else {
1402 VisitForStackValue(property->obj());
1403 VisitForAccumulatorValue(property->key());
1404 }
1362 __ movq(rdx, Operand(rsp, 0)); 1405 __ movq(rdx, Operand(rsp, 0));
1363 __ push(rax); 1406 __ push(rax);
1364 } else { 1407 } else {
1365 VisitForStackValue(property->obj()); 1408 if (property->is_arguments_access()) {
1366 VisitForStackValue(property->key()); 1409 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1410 MemOperand slot_operand =
1411 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1412 __ push(slot_operand);
1413 __ Push(property->key()->AsLiteral()->handle());
1414 } else {
1415 VisitForStackValue(property->obj());
1416 VisitForStackValue(property->key());
1417 }
1367 } 1418 }
1368 break; 1419 break;
1420 }
1369 } 1421 }
1370 1422
1371 if (expr->is_compound()) { 1423 if (expr->is_compound()) {
1372 { AccumulatorValueContext context(this); 1424 { AccumulatorValueContext context(this);
1373 switch (assign_type) { 1425 switch (assign_type) {
1374 case VARIABLE: 1426 case VARIABLE:
1375 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); 1427 EmitVariableLoad(expr->target()->AsVariableProxy()->var());
1376 break; 1428 break;
1377 case NAMED_PROPERTY: 1429 case NAMED_PROPERTY:
1378 EmitNamedPropertyLoad(property); 1430 EmitNamedPropertyLoad(property);
1379 break; 1431 break;
1380 case KEYED_PROPERTY: 1432 case KEYED_PROPERTY:
1381 EmitKeyedPropertyLoad(property); 1433 EmitKeyedPropertyLoad(property);
1382 break; 1434 break;
1383 } 1435 }
1384 } 1436 }
1385 1437
1438 // For property compound assignments we need another deoptimization
1439 // point after the property load.
1440 if (property != NULL) {
1441 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
1442 }
1443
1386 Token::Value op = expr->binary_op(); 1444 Token::Value op = expr->binary_op();
1387 ConstantOperand constant = ShouldInlineSmiCase(op) 1445 ConstantOperand constant = ShouldInlineSmiCase(op)
1388 ? GetConstantOperand(op, expr->target(), expr->value()) 1446 ? GetConstantOperand(op, expr->target(), expr->value())
1389 : kNoConstants; 1447 : kNoConstants;
1390 ASSERT(constant == kRightConstant || constant == kNoConstants); 1448 ASSERT(constant == kRightConstant || constant == kNoConstants);
1391 if (constant == kNoConstants) { 1449 if (constant == kNoConstants) {
1392 __ push(rax); // Left operand goes on the stack. 1450 __ push(rax); // Left operand goes on the stack.
1393 VisitForAccumulatorValue(expr->value()); 1451 VisitForAccumulatorValue(expr->value());
1394 } 1452 }
1395 1453
1396 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1454 OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1397 ? OVERWRITE_RIGHT 1455 ? OVERWRITE_RIGHT
1398 : NO_OVERWRITE; 1456 : NO_OVERWRITE;
1399 SetSourcePosition(expr->position() + 1); 1457 SetSourcePosition(expr->position() + 1);
1400 AccumulatorValueContext context(this); 1458 AccumulatorValueContext context(this);
1401 if (ShouldInlineSmiCase(op)) { 1459 if (ShouldInlineSmiCase(op)) {
1402 EmitInlineSmiBinaryOp(expr, 1460 EmitInlineSmiBinaryOp(expr,
1403 op, 1461 op,
1404 mode, 1462 mode,
1405 expr->target(), 1463 expr->target(),
1406 expr->value(), 1464 expr->value(),
1407 constant); 1465 constant);
1408 } else { 1466 } else {
1409 EmitBinaryOp(op, mode); 1467 EmitBinaryOp(op, mode);
1410 } 1468 }
1469 // Deoptimization point in case the binary operation may have side effects.
1470 PrepareForBailout(expr->binary_operation(), TOS_REG);
1411 } else { 1471 } else {
1412 VisitForAccumulatorValue(expr->value()); 1472 VisitForAccumulatorValue(expr->value());
1413 } 1473 }
1414 1474
1415 // Record source position before possible IC call. 1475 // Record source position before possible IC call.
1416 SetSourcePosition(expr->position()); 1476 SetSourcePosition(expr->position());
1417 1477
1418 // Store the value. 1478 // Store the value.
1419 switch (assign_type) { 1479 switch (assign_type) {
1420 case VARIABLE: 1480 case VARIABLE:
1421 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1481 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1422 expr->op()); 1482 expr->op());
1483 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1423 context()->Plug(rax); 1484 context()->Plug(rax);
1424 break; 1485 break;
1425 case NAMED_PROPERTY: 1486 case NAMED_PROPERTY:
1426 EmitNamedPropertyAssignment(expr); 1487 EmitNamedPropertyAssignment(expr);
1427 break; 1488 break;
1428 case KEYED_PROPERTY: 1489 case KEYED_PROPERTY:
1429 EmitKeyedPropertyAssignment(expr); 1490 EmitKeyedPropertyAssignment(expr);
1430 break; 1491 break;
1431 } 1492 }
1432 } 1493 }
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1522 __ pop(rdx); 1583 __ pop(rdx);
1523 stub.GenerateCall(masm_, rdx, rax); 1584 stub.GenerateCall(masm_, rdx, rax);
1524 } else { 1585 } else {
1525 __ push(result_register()); 1586 __ push(result_register());
1526 __ CallStub(&stub); 1587 __ CallStub(&stub);
1527 } 1588 }
1528 context()->Plug(rax); 1589 context()->Plug(rax);
1529 } 1590 }
1530 1591
1531 1592
1532 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_id) { 1593 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1533 // Invalid left-hand sides are rewritten to have a 'throw 1594 // Invalid left-hand sides are rewritten to have a 'throw
1534 // ReferenceError' on the left-hand side. 1595 // ReferenceError' on the left-hand side.
1535 if (!expr->IsValidLeftHandSide()) { 1596 if (!expr->IsValidLeftHandSide()) {
1536 VisitForEffect(expr); 1597 VisitForEffect(expr);
1537 return; 1598 return;
1538 } 1599 }
1539 1600
1540 // Left-hand side can only be a property, a global or a (parameter or local) 1601 // Left-hand side can only be a property, a global or a (parameter or local)
1541 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1602 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1542 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1603 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
(...skipping 27 matching lines...) Expand all
1570 VisitForStackValue(prop->obj()); 1631 VisitForStackValue(prop->obj());
1571 VisitForAccumulatorValue(prop->key()); 1632 VisitForAccumulatorValue(prop->key());
1572 __ movq(rcx, rax); 1633 __ movq(rcx, rax);
1573 __ pop(rdx); 1634 __ pop(rdx);
1574 __ pop(rax); 1635 __ pop(rax);
1575 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1636 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
1576 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1637 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1577 break; 1638 break;
1578 } 1639 }
1579 } 1640 }
1641 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1580 context()->Plug(rax); 1642 context()->Plug(rax);
1581 } 1643 }
1582 1644
1583 1645
1584 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1646 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1585 Token::Value op) { 1647 Token::Value op) {
1586 // Left-hand sides that rewrite to explicit property accesses do not reach 1648 // Left-hand sides that rewrite to explicit property accesses do not reach
1587 // here. 1649 // here.
1588 ASSERT(var != NULL); 1650 ASSERT(var != NULL);
1589 ASSERT(var->is_global() || var->AsSlot() != NULL); 1651 ASSERT(var->is_global() || var->AsSlot() != NULL);
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1743 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1682 1744
1683 // If the assignment ends an initialization block, revert to fast case. 1745 // If the assignment ends an initialization block, revert to fast case.
1684 if (expr->ends_initialization_block()) { 1746 if (expr->ends_initialization_block()) {
1685 __ push(rax); // Result of assignment, saved even if not needed. 1747 __ push(rax); // Result of assignment, saved even if not needed.
1686 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1748 __ push(Operand(rsp, kPointerSize)); // Receiver is under value.
1687 __ CallRuntime(Runtime::kToFastProperties, 1); 1749 __ CallRuntime(Runtime::kToFastProperties, 1);
1688 __ pop(rax); 1750 __ pop(rax);
1689 __ Drop(1); 1751 __ Drop(1);
1690 } 1752 }
1753 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1691 context()->Plug(rax); 1754 context()->Plug(rax);
1692 } 1755 }
1693 1756
1694 1757
1695 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1758 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1696 // Assignment to a property, using a keyed store IC. 1759 // Assignment to a property, using a keyed store IC.
1697 1760
1698 // If the assignment starts a block of assignments to the same object, 1761 // If the assignment starts a block of assignments to the same object,
1699 // change to slow case to avoid the quadratic behavior of repeatedly 1762 // change to slow case to avoid the quadratic behavior of repeatedly
1700 // adding fast properties. 1763 // adding fast properties.
(...skipping 18 matching lines...) Expand all
1719 1782
1720 // If the assignment ends an initialization block, revert to fast case. 1783 // If the assignment ends an initialization block, revert to fast case.
1721 if (expr->ends_initialization_block()) { 1784 if (expr->ends_initialization_block()) {
1722 __ pop(rdx); 1785 __ pop(rdx);
1723 __ push(rax); // Result of assignment, saved even if not needed. 1786 __ push(rax); // Result of assignment, saved even if not needed.
1724 __ push(rdx); 1787 __ push(rdx);
1725 __ CallRuntime(Runtime::kToFastProperties, 1); 1788 __ CallRuntime(Runtime::kToFastProperties, 1);
1726 __ pop(rax); 1789 __ pop(rax);
1727 } 1790 }
1728 1791
1792 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1729 context()->Plug(rax); 1793 context()->Plug(rax);
1730 } 1794 }
1731 1795
1732 1796
1733 void FullCodeGenerator::VisitProperty(Property* expr) { 1797 void FullCodeGenerator::VisitProperty(Property* expr) {
1734 Comment cmnt(masm_, "[ Property"); 1798 Comment cmnt(masm_, "[ Property");
1735 Expression* key = expr->key(); 1799 Expression* key = expr->key();
1736 1800
1737 if (key->IsPropertyName()) { 1801 if (key->IsPropertyName()) {
1738 VisitForAccumulatorValue(expr->obj()); 1802 VisitForAccumulatorValue(expr->obj());
(...skipping 20 matching lines...) Expand all
1759 VisitForStackValue(args->at(i)); 1823 VisitForStackValue(args->at(i));
1760 } 1824 }
1761 __ Move(rcx, name); 1825 __ Move(rcx, name);
1762 } 1826 }
1763 // Record source position for debugger. 1827 // Record source position for debugger.
1764 SetSourcePosition(expr->position()); 1828 SetSourcePosition(expr->position());
1765 // Call the IC initialization code. 1829 // Call the IC initialization code.
1766 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1830 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1767 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); 1831 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop);
1768 EmitCallIC(ic, mode); 1832 EmitCallIC(ic, mode);
1833 RecordJSReturnSite(expr);
1769 // Restore context register. 1834 // Restore context register.
1770 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1835 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1771 context()->Plug(rax); 1836 context()->Plug(rax);
1772 } 1837 }
1773 1838
1774 1839
1775 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 1840 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
1776 Expression* key, 1841 Expression* key,
1777 RelocInfo::Mode mode) { 1842 RelocInfo::Mode mode) {
1778 // Load the key. 1843 // Load the key.
(...skipping 13 matching lines...) Expand all
1792 VisitForStackValue(args->at(i)); 1857 VisitForStackValue(args->at(i));
1793 } 1858 }
1794 } 1859 }
1795 // Record source position for debugger. 1860 // Record source position for debugger.
1796 SetSourcePosition(expr->position()); 1861 SetSourcePosition(expr->position());
1797 // Call the IC initialization code. 1862 // Call the IC initialization code.
1798 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1863 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1799 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); 1864 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop);
1800 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. 1865 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key.
1801 EmitCallIC(ic, mode); 1866 EmitCallIC(ic, mode);
1867 RecordJSReturnSite(expr);
1802 // Restore context register. 1868 // Restore context register.
1803 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1869 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1804 context()->DropAndPlug(1, rax); // Drop the key still on the stack. 1870 context()->DropAndPlug(1, rax); // Drop the key still on the stack.
1805 } 1871 }
1806 1872
1807 1873
1808 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 1874 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
1809 // Code common for calls using the call stub. 1875 // Code common for calls using the call stub.
1810 ZoneList<Expression*>* args = expr->arguments(); 1876 ZoneList<Expression*>* args = expr->arguments();
1811 int arg_count = args->length(); 1877 int arg_count = args->length();
1812 { PreservePositionScope scope(masm()->positions_recorder()); 1878 { PreservePositionScope scope(masm()->positions_recorder());
1813 for (int i = 0; i < arg_count; i++) { 1879 for (int i = 0; i < arg_count; i++) {
1814 VisitForStackValue(args->at(i)); 1880 VisitForStackValue(args->at(i));
1815 } 1881 }
1816 } 1882 }
1817 // Record source position for debugger. 1883 // Record source position for debugger.
1818 SetSourcePosition(expr->position()); 1884 SetSourcePosition(expr->position());
1819 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1885 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1820 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1886 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1821 __ CallStub(&stub); 1887 __ CallStub(&stub);
1888 RecordJSReturnSite(expr);
1822 // Restore context register. 1889 // Restore context register.
1823 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1890 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1824 // Discard the function left on TOS. 1891 // Discard the function left on TOS.
1825 context()->DropAndPlug(1, rax); 1892 context()->DropAndPlug(1, rax);
1826 } 1893 }
1827 1894
1828 1895
1829 void FullCodeGenerator::VisitCall(Call* expr) { 1896 void FullCodeGenerator::VisitCall(Call* expr) {
1897 #ifdef DEBUG
1898 // We want to verify that RecordJSReturnSite gets called on all paths
1899 // through this function. Avoid early returns.
1900 expr->return_is_recorded_ = false;
1901 #endif
1902
1830 Comment cmnt(masm_, "[ Call"); 1903 Comment cmnt(masm_, "[ Call");
1831 Expression* fun = expr->expression(); 1904 Expression* fun = expr->expression();
1832 Variable* var = fun->AsVariableProxy()->AsVariable(); 1905 Variable* var = fun->AsVariableProxy()->AsVariable();
1833 1906
1834 if (var != NULL && var->is_possibly_eval()) { 1907 if (var != NULL && var->is_possibly_eval()) {
1835 // In a call to eval, we first call %ResolvePossiblyDirectEval to 1908 // In a call to eval, we first call %ResolvePossiblyDirectEval to
1836 // resolve the function we need to call and the receiver of the 1909 // resolve the function we need to call and the receiver of the
1837 // call. The we call the resolved function using the given 1910 // call. Then we call the resolved function using the given
1838 // arguments. 1911 // arguments.
1839 ZoneList<Expression*>* args = expr->arguments(); 1912 ZoneList<Expression*>* args = expr->arguments();
1840 int arg_count = args->length(); 1913 int arg_count = args->length();
1841 { PreservePositionScope pos_scope(masm()->positions_recorder()); 1914 { PreservePositionScope pos_scope(masm()->positions_recorder());
1842 VisitForStackValue(fun); 1915 VisitForStackValue(fun);
1843 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. 1916 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
1844 1917
1845 // Push the arguments. 1918 // Push the arguments.
1846 for (int i = 0; i < arg_count; i++) { 1919 for (int i = 0; i < arg_count; i++) {
1847 VisitForStackValue(args->at(i)); 1920 VisitForStackValue(args->at(i));
(...skipping 16 matching lines...) Expand all
1864 // The runtime call returns a pair of values in rax (function) and 1937 // The runtime call returns a pair of values in rax (function) and
1865 // rdx (receiver). Touch up the stack with the right values. 1938 // rdx (receiver). Touch up the stack with the right values.
1866 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); 1939 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
1867 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); 1940 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
1868 } 1941 }
1869 // Record source position for debugger. 1942 // Record source position for debugger.
1870 SetSourcePosition(expr->position()); 1943 SetSourcePosition(expr->position());
1871 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1944 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1872 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1945 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1873 __ CallStub(&stub); 1946 __ CallStub(&stub);
1947 RecordJSReturnSite(expr);
1874 // Restore context register. 1948 // Restore context register.
1875 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1949 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1876 context()->DropAndPlug(1, rax); 1950 context()->DropAndPlug(1, rax);
1877 } else if (var != NULL && !var->is_this() && var->is_global()) { 1951 } else if (var != NULL && !var->is_this() && var->is_global()) {
1878 // Call to a global variable. 1952 // Call to a global variable.
1879 // Push global object as receiver for the call IC lookup. 1953 // Push global object as receiver for the call IC lookup.
1880 __ push(GlobalObjectOperand()); 1954 __ push(GlobalObjectOperand());
1881 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1955 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1882 } else if (var != NULL && var->AsSlot() != NULL && 1956 } else if (var != NULL && var->AsSlot() != NULL &&
1883 var->AsSlot()->type() == Slot::LOOKUP) { 1957 var->AsSlot()->type() == Slot::LOOKUP) {
1884 // Call to a lookup slot (dynamically introduced variable). 1958 // Call to a lookup slot (dynamically introduced variable).
1885 Label slow, done; 1959 Label slow, done;
1886 1960
1887 { PreservePositionScope scope(masm()->positions_recorder()); 1961 { PreservePositionScope scope(masm()->positions_recorder());
1888 // Generate code for loading from variables potentially shadowed 1962 // Generate code for loading from variables potentially shadowed
1889 // by eval-introduced variables. 1963 // by eval-introduced variables.
1890 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), 1964 EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
1891 NOT_INSIDE_TYPEOF, 1965 NOT_INSIDE_TYPEOF,
1892 &slow, 1966 &slow,
1893 &done); 1967 &done);
1894 1968
1895 __ bind(&slow); 1969 __ bind(&slow);
1896 // Call the runtime to find the function to call (returned in rax) 1970 }
1897 // and the object holding it (returned in rdx). 1971 // Call the runtime to find the function to call (returned in rax)
1898 __ push(context_register()); 1972 // and the object holding it (returned in rdx).
1899 __ Push(var->name()); 1973 __ push(context_register());
1900 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1974 __ Push(var->name());
1901 __ push(rax); // Function. 1975 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1902 __ push(rdx); // Receiver. 1976 __ push(rax); // Function.
1977 __ push(rdx); // Receiver.
1903 1978
1904 // If fast case code has been generated, emit code to push the 1979 // If fast case code has been generated, emit code to push the
1905 // function and receiver and have the slow path jump around this 1980 // function and receiver and have the slow path jump around this
1906 // code. 1981 // code.
1907 if (done.is_linked()) { 1982 if (done.is_linked()) {
1908 NearLabel call; 1983 NearLabel call;
1909 __ jmp(&call); 1984 __ jmp(&call);
1910 __ bind(&done); 1985 __ bind(&done);
1911 // Push function. 1986 // Push function.
1912 __ push(rax); 1987 __ push(rax);
1913 // Push global receiver. 1988 // Push global receiver.
1914 __ movq(rbx, GlobalObjectOperand()); 1989 __ movq(rbx, GlobalObjectOperand());
1915 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 1990 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1916 __ bind(&call); 1991 __ bind(&call);
1917 }
1918 } 1992 }
1919 1993
1920 EmitCallWithStub(expr); 1994 EmitCallWithStub(expr);
1921
1922 } else if (fun->AsProperty() != NULL) { 1995 } else if (fun->AsProperty() != NULL) {
1923 // Call to an object property. 1996 // Call to an object property.
1924 Property* prop = fun->AsProperty(); 1997 Property* prop = fun->AsProperty();
1925 Literal* key = prop->key()->AsLiteral(); 1998 Literal* key = prop->key()->AsLiteral();
1926 if (key != NULL && key->handle()->IsSymbol()) { 1999 if (key != NULL && key->handle()->IsSymbol()) {
1927 // Call to a named property, use call IC. 2000 // Call to a named property, use call IC.
1928 { PreservePositionScope scope(masm()->positions_recorder()); 2001 { PreservePositionScope scope(masm()->positions_recorder());
1929 VisitForStackValue(prop->obj()); 2002 VisitForStackValue(prop->obj());
1930 } 2003 }
1931 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2004 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1932 } else { 2005 } else {
1933 // Call to a keyed property. 2006 // Call to a keyed property.
1934 // For a synthetic property use keyed load IC followed by function call, 2007 // For a synthetic property use keyed load IC followed by function call,
1935 // for a regular property use KeyedCallIC. 2008 // for a regular property use keyed EmitCallIC.
1936 { PreservePositionScope scope(masm()->positions_recorder()); 2009 { PreservePositionScope scope(masm()->positions_recorder());
1937 VisitForStackValue(prop->obj()); 2010 VisitForStackValue(prop->obj());
1938 } 2011 }
1939 if (prop->is_synthetic()) { 2012 if (prop->is_synthetic()) {
1940 { PreservePositionScope scope(masm()->positions_recorder()); 2013 { PreservePositionScope scope(masm()->positions_recorder());
1941 VisitForAccumulatorValue(prop->key()); 2014 VisitForAccumulatorValue(prop->key());
1942 __ movq(rdx, Operand(rsp, 0));
1943 } 2015 }
1944 // Record source code position for IC call. 2016 // Record source code position for IC call.
1945 SetSourcePosition(prop->position()); 2017 SetSourcePosition(prop->position());
2018 __ pop(rdx); // We do not need to keep the receiver.
2019
1946 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 2020 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1947 EmitCallIC(ic, RelocInfo::CODE_TARGET); 2021 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1948 // Pop receiver.
1949 __ pop(rbx);
1950 // Push result (function). 2022 // Push result (function).
1951 __ push(rax); 2023 __ push(rax);
1952 // Push receiver object on stack. 2024 // Push Global receiver.
1953 __ movq(rcx, GlobalObjectOperand()); 2025 __ movq(rcx, GlobalObjectOperand());
1954 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 2026 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
1955 EmitCallWithStub(expr); 2027 EmitCallWithStub(expr);
1956 } else { 2028 } else {
1957 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 2029 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
1958 } 2030 }
1959 } 2031 }
1960 } else { 2032 } else {
1961 // Call to some other expression. If the expression is an anonymous 2033 // Call to some other expression. If the expression is an anonymous
1962 // function literal not called in a loop, mark it as one that should 2034 // function literal not called in a loop, mark it as one that should
1963 // also use the fast code generator. 2035 // also use the full code generator.
1964 FunctionLiteral* lit = fun->AsFunctionLiteral(); 2036 FunctionLiteral* lit = fun->AsFunctionLiteral();
1965 if (lit != NULL && 2037 if (lit != NULL &&
1966 lit->name()->Equals(Heap::empty_string()) && 2038 lit->name()->Equals(Heap::empty_string()) &&
1967 loop_depth() == 0) { 2039 loop_depth() == 0) {
1968 lit->set_try_full_codegen(true); 2040 lit->set_try_full_codegen(true);
1969 } 2041 }
1970 { PreservePositionScope scope(masm()->positions_recorder()); 2042 { PreservePositionScope scope(masm()->positions_recorder());
1971 VisitForStackValue(fun); 2043 VisitForStackValue(fun);
1972 } 2044 }
1973 // Load global receiver object. 2045 // Load global receiver object.
1974 __ movq(rbx, GlobalObjectOperand()); 2046 __ movq(rbx, GlobalObjectOperand());
1975 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 2047 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1976 // Emit function call. 2048 // Emit function call.
1977 EmitCallWithStub(expr); 2049 EmitCallWithStub(expr);
1978 } 2050 }
2051
2052 #ifdef DEBUG
2053 // RecordJSReturnSite should have been called.
2054 ASSERT(expr->return_is_recorded_);
2055 #endif
1979 } 2056 }
1980 2057
1981 2058
1982 void FullCodeGenerator::VisitCallNew(CallNew* expr) { 2059 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
1983 Comment cmnt(masm_, "[ CallNew"); 2060 Comment cmnt(masm_, "[ CallNew");
1984 // According to ECMA-262, section 11.2.2, page 44, the function 2061 // According to ECMA-262, section 11.2.2, page 44, the function
1985 // expression in new calls must be evaluated before the 2062 // expression in new calls must be evaluated before the
1986 // arguments. 2063 // arguments.
1987 2064
1988 // Push constructor on the stack. If it's not a function it's used as 2065 // Push constructor on the stack. If it's not a function it's used as
(...skipping 27 matching lines...) Expand all
2016 2093
2017 VisitForAccumulatorValue(args->at(0)); 2094 VisitForAccumulatorValue(args->at(0));
2018 2095
2019 Label materialize_true, materialize_false; 2096 Label materialize_true, materialize_false;
2020 Label* if_true = NULL; 2097 Label* if_true = NULL;
2021 Label* if_false = NULL; 2098 Label* if_false = NULL;
2022 Label* fall_through = NULL; 2099 Label* fall_through = NULL;
2023 context()->PrepareTest(&materialize_true, &materialize_false, 2100 context()->PrepareTest(&materialize_true, &materialize_false,
2024 &if_true, &if_false, &fall_through); 2101 &if_true, &if_false, &fall_through);
2025 2102
2103 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2026 __ JumpIfSmi(rax, if_true); 2104 __ JumpIfSmi(rax, if_true);
2027 __ jmp(if_false); 2105 __ jmp(if_false);
2028 2106
2029 context()->Plug(if_true, if_false); 2107 context()->Plug(if_true, if_false);
2030 } 2108 }
2031 2109
2032 2110
2033 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 2111 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
2034 ASSERT(args->length() == 1); 2112 ASSERT(args->length() == 1);
2035 2113
2036 VisitForAccumulatorValue(args->at(0)); 2114 VisitForAccumulatorValue(args->at(0));
2037 2115
2038 Label materialize_true, materialize_false; 2116 Label materialize_true, materialize_false;
2039 Label* if_true = NULL; 2117 Label* if_true = NULL;
2040 Label* if_false = NULL; 2118 Label* if_false = NULL;
2041 Label* fall_through = NULL; 2119 Label* fall_through = NULL;
2042 context()->PrepareTest(&materialize_true, &materialize_false, 2120 context()->PrepareTest(&materialize_true, &materialize_false,
2043 &if_true, &if_false, &fall_through); 2121 &if_true, &if_false, &fall_through);
2044 2122
2123 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2045 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); 2124 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
2046 Split(non_negative_smi, if_true, if_false, fall_through); 2125 Split(non_negative_smi, if_true, if_false, fall_through);
2047 2126
2048 context()->Plug(if_true, if_false); 2127 context()->Plug(if_true, if_false);
2049 } 2128 }
2050 2129
2051 2130
2052 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 2131 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
2053 ASSERT(args->length() == 1); 2132 ASSERT(args->length() == 1);
2054 2133
(...skipping 11 matching lines...) Expand all
2066 __ j(equal, if_true); 2145 __ j(equal, if_true);
2067 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2146 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2068 // Undetectable objects behave like undefined when tested with typeof. 2147 // Undetectable objects behave like undefined when tested with typeof.
2069 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2148 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2070 Immediate(1 << Map::kIsUndetectable)); 2149 Immediate(1 << Map::kIsUndetectable));
2071 __ j(not_zero, if_false); 2150 __ j(not_zero, if_false);
2072 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2151 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2073 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); 2152 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE));
2074 __ j(below, if_false); 2153 __ j(below, if_false);
2075 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); 2154 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE));
2155 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2076 Split(below_equal, if_true, if_false, fall_through); 2156 Split(below_equal, if_true, if_false, fall_through);
2077 2157
2078 context()->Plug(if_true, if_false); 2158 context()->Plug(if_true, if_false);
2079 } 2159 }
2080 2160
2081 2161
2082 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2162 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
2083 ASSERT(args->length() == 1); 2163 ASSERT(args->length() == 1);
2084 2164
2085 VisitForAccumulatorValue(args->at(0)); 2165 VisitForAccumulatorValue(args->at(0));
2086 2166
2087 Label materialize_true, materialize_false; 2167 Label materialize_true, materialize_false;
2088 Label* if_true = NULL; 2168 Label* if_true = NULL;
2089 Label* if_false = NULL; 2169 Label* if_false = NULL;
2090 Label* fall_through = NULL; 2170 Label* fall_through = NULL;
2091 context()->PrepareTest(&materialize_true, &materialize_false, 2171 context()->PrepareTest(&materialize_true, &materialize_false,
2092 &if_true, &if_false, &fall_through); 2172 &if_true, &if_false, &fall_through);
2093 2173
2094 __ JumpIfSmi(rax, if_false); 2174 __ JumpIfSmi(rax, if_false);
2095 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 2175 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
2176 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2096 Split(above_equal, if_true, if_false, fall_through); 2177 Split(above_equal, if_true, if_false, fall_through);
2097 2178
2098 context()->Plug(if_true, if_false); 2179 context()->Plug(if_true, if_false);
2099 } 2180 }
2100 2181
2101 2182
2102 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2183 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2103 ASSERT(args->length() == 1); 2184 ASSERT(args->length() == 1);
2104 2185
2105 VisitForAccumulatorValue(args->at(0)); 2186 VisitForAccumulatorValue(args->at(0));
2106 2187
2107 Label materialize_true, materialize_false; 2188 Label materialize_true, materialize_false;
2108 Label* if_true = NULL; 2189 Label* if_true = NULL;
2109 Label* if_false = NULL; 2190 Label* if_false = NULL;
2110 Label* fall_through = NULL; 2191 Label* fall_through = NULL;
2111 context()->PrepareTest(&materialize_true, &materialize_false, 2192 context()->PrepareTest(&materialize_true, &materialize_false,
2112 &if_true, &if_false, &fall_through); 2193 &if_true, &if_false, &fall_through);
2113 2194
2114 __ JumpIfSmi(rax, if_false); 2195 __ JumpIfSmi(rax, if_false);
2115 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2196 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2116 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2197 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2117 Immediate(1 << Map::kIsUndetectable)); 2198 Immediate(1 << Map::kIsUndetectable));
2199 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2118 Split(not_zero, if_true, if_false, fall_through); 2200 Split(not_zero, if_true, if_false, fall_through);
2119 2201
2120 context()->Plug(if_true, if_false); 2202 context()->Plug(if_true, if_false);
2121 } 2203 }
2122 2204
2123 2205
2124 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2206 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2125 ZoneList<Expression*>* args) { 2207 ZoneList<Expression*>* args) {
2126 ASSERT(args->length() == 1); 2208 ASSERT(args->length() == 1);
2127 2209
2128 VisitForAccumulatorValue(args->at(0)); 2210 VisitForAccumulatorValue(args->at(0));
2129 2211
2130 Label materialize_true, materialize_false; 2212 Label materialize_true, materialize_false;
2131 Label* if_true = NULL; 2213 Label* if_true = NULL;
2132 Label* if_false = NULL; 2214 Label* if_false = NULL;
2133 Label* fall_through = NULL; 2215 Label* fall_through = NULL;
2134 context()->PrepareTest(&materialize_true, &materialize_false, 2216 context()->PrepareTest(&materialize_true, &materialize_false,
2135 &if_true, &if_false, &fall_through); 2217 &if_true, &if_false, &fall_through);
2136 2218
2137 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only 2219 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
2138 // used in a few functions in runtime.js which should not normally be hit by 2220 // used in a few functions in runtime.js which should not normally be hit by
2139 // this compiler. 2221 // this compiler.
2222 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2140 __ jmp(if_false); 2223 __ jmp(if_false);
2141 context()->Plug(if_true, if_false); 2224 context()->Plug(if_true, if_false);
2142 } 2225 }
2143 2226
2144 2227
2145 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2228 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2146 ASSERT(args->length() == 1); 2229 ASSERT(args->length() == 1);
2147 2230
2148 VisitForAccumulatorValue(args->at(0)); 2231 VisitForAccumulatorValue(args->at(0));
2149 2232
2150 Label materialize_true, materialize_false; 2233 Label materialize_true, materialize_false;
2151 Label* if_true = NULL; 2234 Label* if_true = NULL;
2152 Label* if_false = NULL; 2235 Label* if_false = NULL;
2153 Label* fall_through = NULL; 2236 Label* fall_through = NULL;
2154 context()->PrepareTest(&materialize_true, &materialize_false, 2237 context()->PrepareTest(&materialize_true, &materialize_false,
2155 &if_true, &if_false, &fall_through); 2238 &if_true, &if_false, &fall_through);
2156 2239
2157 __ JumpIfSmi(rax, if_false); 2240 __ JumpIfSmi(rax, if_false);
2158 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2241 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2242 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2159 Split(equal, if_true, if_false, fall_through); 2243 Split(equal, if_true, if_false, fall_through);
2160 2244
2161 context()->Plug(if_true, if_false); 2245 context()->Plug(if_true, if_false);
2162 } 2246 }
2163 2247
2164 2248
2165 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2249 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2166 ASSERT(args->length() == 1); 2250 ASSERT(args->length() == 1);
2167 2251
2168 VisitForAccumulatorValue(args->at(0)); 2252 VisitForAccumulatorValue(args->at(0));
2169 2253
2170 Label materialize_true, materialize_false; 2254 Label materialize_true, materialize_false;
2171 Label* if_true = NULL; 2255 Label* if_true = NULL;
2172 Label* if_false = NULL; 2256 Label* if_false = NULL;
2173 Label* fall_through = NULL; 2257 Label* fall_through = NULL;
2174 context()->PrepareTest(&materialize_true, &materialize_false, 2258 context()->PrepareTest(&materialize_true, &materialize_false,
2175 &if_true, &if_false, &fall_through); 2259 &if_true, &if_false, &fall_through);
2176 2260
2177 __ JumpIfSmi(rax, if_false); 2261 __ JumpIfSmi(rax, if_false);
2178 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 2262 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
2263 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2179 Split(equal, if_true, if_false, fall_through); 2264 Split(equal, if_true, if_false, fall_through);
2180 2265
2181 context()->Plug(if_true, if_false); 2266 context()->Plug(if_true, if_false);
2182 } 2267 }
2183 2268
2184 2269
2185 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2270 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2186 ASSERT(args->length() == 1); 2271 ASSERT(args->length() == 1);
2187 2272
2188 VisitForAccumulatorValue(args->at(0)); 2273 VisitForAccumulatorValue(args->at(0));
2189 2274
2190 Label materialize_true, materialize_false; 2275 Label materialize_true, materialize_false;
2191 Label* if_true = NULL; 2276 Label* if_true = NULL;
2192 Label* if_false = NULL; 2277 Label* if_false = NULL;
2193 Label* fall_through = NULL; 2278 Label* fall_through = NULL;
2194 context()->PrepareTest(&materialize_true, &materialize_false, 2279 context()->PrepareTest(&materialize_true, &materialize_false,
2195 &if_true, &if_false, &fall_through); 2280 &if_true, &if_false, &fall_through);
2196 2281
2197 __ JumpIfSmi(rax, if_false); 2282 __ JumpIfSmi(rax, if_false);
2198 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); 2283 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
2284 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2199 Split(equal, if_true, if_false, fall_through); 2285 Split(equal, if_true, if_false, fall_through);
2200 2286
2201 context()->Plug(if_true, if_false); 2287 context()->Plug(if_true, if_false);
2202 } 2288 }
2203 2289
2204 2290
2205 2291
2206 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2292 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2207 ASSERT(args->length() == 0); 2293 ASSERT(args->length() == 0);
2208 2294
(...skipping 11 matching lines...) Expand all
2220 Label check_frame_marker; 2306 Label check_frame_marker;
2221 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), 2307 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset),
2222 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2308 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2223 __ j(not_equal, &check_frame_marker); 2309 __ j(not_equal, &check_frame_marker);
2224 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 2310 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2225 2311
2226 // Check the marker in the calling frame. 2312 // Check the marker in the calling frame.
2227 __ bind(&check_frame_marker); 2313 __ bind(&check_frame_marker);
2228 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), 2314 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset),
2229 Smi::FromInt(StackFrame::CONSTRUCT)); 2315 Smi::FromInt(StackFrame::CONSTRUCT));
2316 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2230 Split(equal, if_true, if_false, fall_through); 2317 Split(equal, if_true, if_false, fall_through);
2231 2318
2232 context()->Plug(if_true, if_false); 2319 context()->Plug(if_true, if_false);
2233 } 2320 }
2234 2321
2235 2322
2236 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2323 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2237 ASSERT(args->length() == 2); 2324 ASSERT(args->length() == 2);
2238 2325
2239 // Load the two objects into registers and perform the comparison. 2326 // Load the two objects into registers and perform the comparison.
2240 VisitForStackValue(args->at(0)); 2327 VisitForStackValue(args->at(0));
2241 VisitForAccumulatorValue(args->at(1)); 2328 VisitForAccumulatorValue(args->at(1));
2242 2329
2243 Label materialize_true, materialize_false; 2330 Label materialize_true, materialize_false;
2244 Label* if_true = NULL; 2331 Label* if_true = NULL;
2245 Label* if_false = NULL; 2332 Label* if_false = NULL;
2246 Label* fall_through = NULL; 2333 Label* fall_through = NULL;
2247 context()->PrepareTest(&materialize_true, &materialize_false, 2334 context()->PrepareTest(&materialize_true, &materialize_false,
2248 &if_true, &if_false, &fall_through); 2335 &if_true, &if_false, &fall_through);
2249 2336
2250 __ pop(rbx); 2337 __ pop(rbx);
2251 __ cmpq(rax, rbx); 2338 __ cmpq(rax, rbx);
2339 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2252 Split(equal, if_true, if_false, fall_through); 2340 Split(equal, if_true, if_false, fall_through);
2253 2341
2254 context()->Plug(if_true, if_false); 2342 context()->Plug(if_true, if_false);
2255 } 2343 }
2256 2344
2257 2345
2258 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2346 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2259 ASSERT(args->length() == 1); 2347 ASSERT(args->length() == 1);
2260 2348
2261 // ArgumentsAccessStub expects the key in rdx and the formal 2349 // ArgumentsAccessStub expects the key in rdx and the formal
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
2815 2903
2816 Label materialize_true, materialize_false; 2904 Label materialize_true, materialize_false;
2817 Label* if_true = NULL; 2905 Label* if_true = NULL;
2818 Label* if_false = NULL; 2906 Label* if_false = NULL;
2819 Label* fall_through = NULL; 2907 Label* fall_through = NULL;
2820 context()->PrepareTest(&materialize_true, &materialize_false, 2908 context()->PrepareTest(&materialize_true, &materialize_false,
2821 &if_true, &if_false, &fall_through); 2909 &if_true, &if_false, &fall_through);
2822 2910
2823 __ testl(FieldOperand(rax, String::kHashFieldOffset), 2911 __ testl(FieldOperand(rax, String::kHashFieldOffset),
2824 Immediate(String::kContainsCachedArrayIndexMask)); 2912 Immediate(String::kContainsCachedArrayIndexMask));
2913 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2825 __ j(zero, if_true); 2914 __ j(zero, if_true);
2826 __ jmp(if_false); 2915 __ jmp(if_false);
2827 2916
2828 context()->Plug(if_true, if_false); 2917 context()->Plug(if_true, if_false);
2829 } 2918 }
2830 2919
2831 2920
2832 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 2921 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
2833 ASSERT(args->length() == 1); 2922 ASSERT(args->length() == 1);
2834 2923
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2936 3025
2937 case Token::NOT: { 3026 case Token::NOT: {
2938 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3027 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2939 Label materialize_true, materialize_false; 3028 Label materialize_true, materialize_false;
2940 Label* if_true = NULL; 3029 Label* if_true = NULL;
2941 Label* if_false = NULL; 3030 Label* if_false = NULL;
2942 Label* fall_through = NULL; 3031 Label* fall_through = NULL;
2943 // Notice that the labels are swapped. 3032 // Notice that the labels are swapped.
2944 context()->PrepareTest(&materialize_true, &materialize_false, 3033 context()->PrepareTest(&materialize_true, &materialize_false,
2945 &if_false, &if_true, &fall_through); 3034 &if_false, &if_true, &fall_through);
3035 if (context()->IsTest()) ForwardBailoutToChild(expr);
2946 VisitForControl(expr->expression(), if_true, if_false, fall_through); 3036 VisitForControl(expr->expression(), if_true, if_false, fall_through);
2947 context()->Plug(if_false, if_true); // Labels swapped. 3037 context()->Plug(if_false, if_true); // Labels swapped.
2948 break; 3038 break;
2949 } 3039 }
2950 3040
2951 case Token::TYPEOF: { 3041 case Token::TYPEOF: {
2952 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3042 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2953 { StackValueContext context(this); 3043 { StackValueContext context(this);
2954 VisitForTypeofValue(expr->expression()); 3044 VisitForTypeofValue(expr->expression());
2955 } 3045 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
3049 } else { 3139 } else {
3050 // Reserve space for result of postfix operation. 3140 // Reserve space for result of postfix operation.
3051 if (expr->is_postfix() && !context()->IsEffect()) { 3141 if (expr->is_postfix() && !context()->IsEffect()) {
3052 __ Push(Smi::FromInt(0)); 3142 __ Push(Smi::FromInt(0));
3053 } 3143 }
3054 if (assign_type == NAMED_PROPERTY) { 3144 if (assign_type == NAMED_PROPERTY) {
3055 VisitForAccumulatorValue(prop->obj()); 3145 VisitForAccumulatorValue(prop->obj());
3056 __ push(rax); // Copy of receiver, needed for later store. 3146 __ push(rax); // Copy of receiver, needed for later store.
3057 EmitNamedPropertyLoad(prop); 3147 EmitNamedPropertyLoad(prop);
3058 } else { 3148 } else {
3059 VisitForStackValue(prop->obj()); 3149 if (prop->is_arguments_access()) {
3060 VisitForAccumulatorValue(prop->key()); 3150 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy();
3151 MemOperand slot_operand =
3152 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
3153 __ push(slot_operand);
3154 __ Move(rax, prop->key()->AsLiteral()->handle());
3155 } else {
3156 VisitForStackValue(prop->obj());
3157 VisitForAccumulatorValue(prop->key());
3158 }
3061 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 3159 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack
3062 __ push(rax); // Copy of key, needed for later store. 3160 __ push(rax); // Copy of key, needed for later store.
3063 EmitKeyedPropertyLoad(prop); 3161 EmitKeyedPropertyLoad(prop);
3064 } 3162 }
3065 } 3163 }
3066 3164
3165 // We need a second deoptimization point after loading the value
3166 // in case evaluating the property load my have a side effect.
3167 PrepareForBailout(expr->increment(), TOS_REG);
3168
3067 // Call ToNumber only if operand is not a smi. 3169 // Call ToNumber only if operand is not a smi.
3068 NearLabel no_conversion; 3170 NearLabel no_conversion;
3069 Condition is_smi; 3171 Condition is_smi;
3070 is_smi = masm_->CheckSmi(rax); 3172 is_smi = masm_->CheckSmi(rax);
3071 __ j(is_smi, &no_conversion); 3173 __ j(is_smi, &no_conversion);
3072 __ push(rax); 3174 __ push(rax);
3073 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3175 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
3074 __ bind(&no_conversion); 3176 __ bind(&no_conversion);
3075 3177
3076 // Save result for postfix expressions. 3178 // Save result for postfix expressions.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3126 __ bind(&done); 3228 __ bind(&done);
3127 3229
3128 // Store the value returned in rax. 3230 // Store the value returned in rax.
3129 switch (assign_type) { 3231 switch (assign_type) {
3130 case VARIABLE: 3232 case VARIABLE:
3131 if (expr->is_postfix()) { 3233 if (expr->is_postfix()) {
3132 // Perform the assignment as if via '='. 3234 // Perform the assignment as if via '='.
3133 { EffectContext context(this); 3235 { EffectContext context(this);
3134 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3236 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3135 Token::ASSIGN); 3237 Token::ASSIGN);
3238 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3136 context.Plug(rax); 3239 context.Plug(rax);
3137 } 3240 }
3138 // For all contexts except kEffect: We have the result on 3241 // For all contexts except kEffect: We have the result on
3139 // top of the stack. 3242 // top of the stack.
3140 if (!context()->IsEffect()) { 3243 if (!context()->IsEffect()) {
3141 context()->PlugTOS(); 3244 context()->PlugTOS();
3142 } 3245 }
3143 } else { 3246 } else {
3144 // Perform the assignment as if via '='. 3247 // Perform the assignment as if via '='.
3145 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3248 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3146 Token::ASSIGN); 3249 Token::ASSIGN);
3250 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3147 context()->Plug(rax); 3251 context()->Plug(rax);
3148 } 3252 }
3149 break; 3253 break;
3150 case NAMED_PROPERTY: { 3254 case NAMED_PROPERTY: {
3151 __ Move(rcx, prop->key()->AsLiteral()->handle()); 3255 __ Move(rcx, prop->key()->AsLiteral()->handle());
3152 __ pop(rdx); 3256 __ pop(rdx);
3153 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3257 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
3154 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3258 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3259 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3155 if (expr->is_postfix()) { 3260 if (expr->is_postfix()) {
3156 if (!context()->IsEffect()) { 3261 if (!context()->IsEffect()) {
3157 context()->PlugTOS(); 3262 context()->PlugTOS();
3158 } 3263 }
3159 } else { 3264 } else {
3160 context()->Plug(rax); 3265 context()->Plug(rax);
3161 } 3266 }
3162 break; 3267 break;
3163 } 3268 }
3164 case KEYED_PROPERTY: { 3269 case KEYED_PROPERTY: {
3165 __ pop(rcx); 3270 __ pop(rcx);
3166 __ pop(rdx); 3271 __ pop(rdx);
3167 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3272 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
3168 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3273 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3274 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3169 if (expr->is_postfix()) { 3275 if (expr->is_postfix()) {
3170 if (!context()->IsEffect()) { 3276 if (!context()->IsEffect()) {
3171 context()->PlugTOS(); 3277 context()->PlugTOS();
3172 } 3278 }
3173 } else { 3279 } else {
3174 context()->Plug(rax); 3280 context()->Plug(rax);
3175 } 3281 }
3176 break; 3282 break;
3177 } 3283 }
3178 } 3284 }
3179 } 3285 }
3180 3286
3181 3287
3182 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 3288 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
3183 VariableProxy* proxy = expr->AsVariableProxy(); 3289 VariableProxy* proxy = expr->AsVariableProxy();
3184 ASSERT(!context()->IsEffect()); 3290 ASSERT(!context()->IsEffect());
3185 ASSERT(!context()->IsTest()); 3291 ASSERT(!context()->IsTest());
3186 3292
3187 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 3293 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
3188 Comment cmnt(masm_, "Global variable"); 3294 Comment cmnt(masm_, "Global variable");
3189 __ Move(rcx, proxy->name()); 3295 __ Move(rcx, proxy->name());
3190 __ movq(rax, GlobalObjectOperand()); 3296 __ movq(rax, GlobalObjectOperand());
3191 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); 3297 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
3192 // Use a regular load, not a contextual load, to avoid a reference 3298 // Use a regular load, not a contextual load, to avoid a reference
3193 // error. 3299 // error.
3194 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3300 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3301 PrepareForBailout(expr, TOS_REG);
3195 context()->Plug(rax); 3302 context()->Plug(rax);
3196 } else if (proxy != NULL && 3303 } else if (proxy != NULL &&
3197 proxy->var()->AsSlot() != NULL && 3304 proxy->var()->AsSlot() != NULL &&
3198 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { 3305 proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
3199 Label done, slow; 3306 Label done, slow;
3200 3307
3201 // Generate code for loading from variables potentially shadowed 3308 // Generate code for loading from variables potentially shadowed
3202 // by eval-introduced variables. 3309 // by eval-introduced variables.
3203 Slot* slot = proxy->var()->AsSlot(); 3310 Slot* slot = proxy->var()->AsSlot();
3204 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 3311 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
3205 3312
3206 __ bind(&slow); 3313 __ bind(&slow);
3207 __ push(rsi); 3314 __ push(rsi);
3208 __ Push(proxy->name()); 3315 __ Push(proxy->name());
3209 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3316 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3317 PrepareForBailout(expr, TOS_REG);
3210 __ bind(&done); 3318 __ bind(&done);
3211 3319
3212 context()->Plug(rax); 3320 context()->Plug(rax);
3213 } else { 3321 } else {
3214 // This expression cannot throw a reference error at the top level. 3322 // This expression cannot throw a reference error at the top level.
3215 Visit(expr); 3323 context()->HandleExpression(expr);
3216 } 3324 }
3217 } 3325 }
3218 3326
3219 3327
3220 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, 3328 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
3221 Expression* left, 3329 Expression* left,
3222 Expression* right, 3330 Expression* right,
3223 Label* if_true, 3331 Label* if_true,
3224 Label* if_false, 3332 Label* if_false,
3225 Label* fall_through) { 3333 Label* fall_through) {
3226 if (op != Token::EQ && op != Token::EQ_STRICT) return false; 3334 if (op != Token::EQ && op != Token::EQ_STRICT) return false;
3227 3335
3228 // Check for the pattern: typeof <expression> == <string literal>. 3336 // Check for the pattern: typeof <expression> == <string literal>.
3229 Literal* right_literal = right->AsLiteral(); 3337 Literal* right_literal = right->AsLiteral();
3230 if (right_literal == NULL) return false; 3338 if (right_literal == NULL) return false;
3231 Handle<Object> right_literal_value = right_literal->handle(); 3339 Handle<Object> right_literal_value = right_literal->handle();
3232 if (!right_literal_value->IsString()) return false; 3340 if (!right_literal_value->IsString()) return false;
3233 UnaryOperation* left_unary = left->AsUnaryOperation(); 3341 UnaryOperation* left_unary = left->AsUnaryOperation();
3234 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; 3342 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
3235 Handle<String> check = Handle<String>::cast(right_literal_value); 3343 Handle<String> check = Handle<String>::cast(right_literal_value);
3236 3344
3237 { AccumulatorValueContext context(this); 3345 { AccumulatorValueContext context(this);
3238 VisitForTypeofValue(left_unary->expression()); 3346 VisitForTypeofValue(left_unary->expression());
3239 } 3347 }
3348 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3240 3349
3241 if (check->Equals(Heap::number_symbol())) { 3350 if (check->Equals(Heap::number_symbol())) {
3242 Condition is_smi = masm_->CheckSmi(rax); 3351 Condition is_smi = masm_->CheckSmi(rax);
3243 __ j(is_smi, if_true); 3352 __ j(is_smi, if_true);
3244 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 3353 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
3245 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 3354 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
3246 Split(equal, if_true, if_false, fall_through); 3355 Split(equal, if_true, if_false, fall_through);
3247 } else if (check->Equals(Heap::string_symbol())) { 3356 } else if (check->Equals(Heap::string_symbol())) {
3248 Condition is_smi = masm_->CheckSmi(rax); 3357 Condition is_smi = masm_->CheckSmi(rax);
3249 __ j(is_smi, if_false); 3358 __ j(is_smi, if_false);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
3323 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { 3432 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
3324 context()->Plug(if_true, if_false); 3433 context()->Plug(if_true, if_false);
3325 return; 3434 return;
3326 } 3435 }
3327 3436
3328 VisitForStackValue(expr->left()); 3437 VisitForStackValue(expr->left());
3329 switch (op) { 3438 switch (op) {
3330 case Token::IN: 3439 case Token::IN:
3331 VisitForStackValue(expr->right()); 3440 VisitForStackValue(expr->right());
3332 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3441 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3442 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
3333 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 3443 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
3334 Split(equal, if_true, if_false, fall_through); 3444 Split(equal, if_true, if_false, fall_through);
3335 break; 3445 break;
3336 3446
3337 case Token::INSTANCEOF: { 3447 case Token::INSTANCEOF: {
3338 VisitForStackValue(expr->right()); 3448 VisitForStackValue(expr->right());
3339 InstanceofStub stub(InstanceofStub::kNoFlags); 3449 InstanceofStub stub(InstanceofStub::kNoFlags);
3340 __ CallStub(&stub); 3450 __ CallStub(&stub);
3451 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3341 __ testq(rax, rax); 3452 __ testq(rax, rax);
3342 // The stub returns 0 for true. 3453 // The stub returns 0 for true.
3343 Split(zero, if_true, if_false, fall_through); 3454 Split(zero, if_true, if_false, fall_through);
3344 break; 3455 break;
3345 } 3456 }
3346 3457
3347 default: { 3458 default: {
3348 VisitForAccumulatorValue(expr->right()); 3459 VisitForAccumulatorValue(expr->right());
3349 Condition cc = no_condition; 3460 Condition cc = no_condition;
3350 bool strict = false; 3461 bool strict = false;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3389 __ SmiCompare(rdx, rax); 3500 __ SmiCompare(rdx, rax);
3390 Split(cc, if_true, if_false, NULL); 3501 Split(cc, if_true, if_false, NULL);
3391 __ bind(&slow_case); 3502 __ bind(&slow_case);
3392 } 3503 }
3393 3504
3394 CompareFlags flags = inline_smi_code 3505 CompareFlags flags = inline_smi_code
3395 ? NO_SMI_COMPARE_IN_STUB 3506 ? NO_SMI_COMPARE_IN_STUB
3396 : NO_COMPARE_FLAGS; 3507 : NO_COMPARE_FLAGS;
3397 CompareStub stub(cc, strict, flags); 3508 CompareStub stub(cc, strict, flags);
3398 __ CallStub(&stub); 3509 __ CallStub(&stub);
3510
3511 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3399 __ testq(rax, rax); 3512 __ testq(rax, rax);
3400 Split(cc, if_true, if_false, fall_through); 3513 Split(cc, if_true, if_false, fall_through);
3401 } 3514 }
3402 } 3515 }
3403 3516
3404 // Convert the result of the comparison into one expected for this 3517 // Convert the result of the comparison into one expected for this
3405 // expression's context. 3518 // expression's context.
3406 context()->Plug(if_true, if_false); 3519 context()->Plug(if_true, if_false);
3407 } 3520 }
3408 3521
3409 3522
3410 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { 3523 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
3411 Comment cmnt(masm_, "[ CompareToNull"); 3524 Comment cmnt(masm_, "[ CompareToNull");
3412 Label materialize_true, materialize_false; 3525 Label materialize_true, materialize_false;
3413 Label* if_true = NULL; 3526 Label* if_true = NULL;
3414 Label* if_false = NULL; 3527 Label* if_false = NULL;
3415 Label* fall_through = NULL; 3528 Label* fall_through = NULL;
3416 context()->PrepareTest(&materialize_true, &materialize_false, 3529 context()->PrepareTest(&materialize_true, &materialize_false,
3417 &if_true, &if_false, &fall_through); 3530 &if_true, &if_false, &fall_through);
3418 3531
3419 VisitForAccumulatorValue(expr->expression()); 3532 VisitForAccumulatorValue(expr->expression());
3533 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3420 __ CompareRoot(rax, Heap::kNullValueRootIndex); 3534 __ CompareRoot(rax, Heap::kNullValueRootIndex);
3421 if (expr->is_strict()) { 3535 if (expr->is_strict()) {
3422 Split(equal, if_true, if_false, fall_through); 3536 Split(equal, if_true, if_false, fall_through);
3423 } else { 3537 } else {
3424 __ j(equal, if_true); 3538 __ j(equal, if_true);
3425 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 3539 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
3426 __ j(equal, if_true); 3540 __ j(equal, if_true);
3427 Condition is_smi = masm_->CheckSmi(rax); 3541 Condition is_smi = masm_->CheckSmi(rax);
3428 __ j(is_smi, if_false); 3542 __ j(is_smi, if_false);
3429 // It can be an undetectable object. 3543 // It can be an undetectable object.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3521 __ ret(0); 3635 __ ret(0);
3522 } 3636 }
3523 3637
3524 3638
3525 #undef __ 3639 #undef __
3526 3640
3527 3641
3528 } } // namespace v8::internal 3642 } } // namespace v8::internal
3529 3643
3530 #endif // V8_TARGET_ARCH_X64 3644 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/codegen-x64.cc ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698