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

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

Issue 6577036: [Isolates] Merge from bleeding_edge to isolates, revisions 6100-6300. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 10 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/deoptimizer-x64.cc ('k') | src/x64/ic-x64.cc » ('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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 192
193 { Comment cmnt(masm_, "[ return <undefined>;"); 193 { Comment cmnt(masm_, "[ return <undefined>;");
194 // Emit a 'return undefined' in case control fell off the end of the body. 194 // Emit a 'return undefined' in case control fell off the end of the body.
195 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 195 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
196 EmitReturnSequence(); 196 EmitReturnSequence();
197 } 197 }
198 } 198 }
199 199
200 200
201 void FullCodeGenerator::ClearAccumulator() { 201 void FullCodeGenerator::ClearAccumulator() {
202 __ xor_(rax, rax); 202 __ Set(rax, 0);
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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 __ Push(Smi::FromInt(is_eval() ? 1 : 0)); 692 __ Push(Smi::FromInt(is_eval() ? 1 : 0));
664 __ CallRuntime(Runtime::kDeclareGlobals, 3); 693 __ CallRuntime(Runtime::kDeclareGlobals, 3);
665 // Return value is ignored. 694 // Return value is ignored.
666 } 695 }
667 696
668 697
669 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 698 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
670 Comment cmnt(masm_, "[ SwitchStatement"); 699 Comment cmnt(masm_, "[ SwitchStatement");
671 Breakable nested_statement(this, stmt); 700 Breakable nested_statement(this, stmt);
672 SetStatementPosition(stmt); 701 SetStatementPosition(stmt);
702
673 // Keep the switch value on the stack until a case matches. 703 // Keep the switch value on the stack until a case matches.
674 VisitForStackValue(stmt->tag()); 704 VisitForStackValue(stmt->tag());
705 PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
675 706
676 ZoneList<CaseClause*>* clauses = stmt->cases(); 707 ZoneList<CaseClause*>* clauses = stmt->cases();
677 CaseClause* default_clause = NULL; // Can occur anywhere in the list. 708 CaseClause* default_clause = NULL; // Can occur anywhere in the list.
678 709
679 Label next_test; // Recycled for each test. 710 Label next_test; // Recycled for each test.
680 // Compile all the tests with branches to their bodies. 711 // Compile all the tests with branches to their bodies.
681 for (int i = 0; i < clauses->length(); i++) { 712 for (int i = 0; i < clauses->length(); i++) {
682 CaseClause* clause = clauses->at(i); 713 CaseClause* clause = clauses->at(i);
683 // The default is not a test, but remember it as final fall through. 714 // The default is not a test, but remember it as final fall through.
684 if (clause->is_default()) { 715 if (clause->is_default()) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 760
730 // Compile all the case bodies. 761 // Compile all the case bodies.
731 for (int i = 0; i < clauses->length(); i++) { 762 for (int i = 0; i < clauses->length(); i++) {
732 Comment cmnt(masm_, "[ Case body"); 763 Comment cmnt(masm_, "[ Case body");
733 CaseClause* clause = clauses->at(i); 764 CaseClause* clause = clauses->at(i);
734 __ bind(clause->body_target()->entry_label()); 765 __ bind(clause->body_target()->entry_label());
735 VisitStatements(clause->statements()); 766 VisitStatements(clause->statements());
736 } 767 }
737 768
738 __ bind(nested_statement.break_target()); 769 __ bind(nested_statement.break_target());
770 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
739 } 771 }
740 772
741 773
742 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 774 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
743 Comment cmnt(masm_, "[ ForInStatement"); 775 Comment cmnt(masm_, "[ ForInStatement");
744 SetStatementPosition(stmt); 776 SetStatementPosition(stmt);
745 777
746 Label loop, exit; 778 Label loop, exit;
747 ForIn loop_statement(this, stmt); 779 ForIn loop_statement(this, stmt);
748 increment_loop_depth(); 780 increment_loop_depth();
(...skipping 476 matching lines...) Expand 10 before | Expand all | Expand 10 after
1225 // Fall through. 1257 // Fall through.
1226 case ObjectLiteral::Property::COMPUTED: 1258 case ObjectLiteral::Property::COMPUTED:
1227 if (key->handle()->IsSymbol()) { 1259 if (key->handle()->IsSymbol()) {
1228 VisitForAccumulatorValue(value); 1260 VisitForAccumulatorValue(value);
1229 __ Move(rcx, key->handle()); 1261 __ Move(rcx, key->handle());
1230 __ movq(rdx, Operand(rsp, 0)); 1262 __ movq(rdx, Operand(rsp, 0));
1231 if (property->emit_store()) { 1263 if (property->emit_store()) {
1232 Handle<Code> ic(isolate()->builtins()->builtin( 1264 Handle<Code> ic(isolate()->builtins()->builtin(
1233 Builtins::StoreIC_Initialize)); 1265 Builtins::StoreIC_Initialize));
1234 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1266 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1267 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1235 } 1268 }
1236 break; 1269 break;
1237 } 1270 }
1238 // Fall through. 1271 // Fall through.
1239 case ObjectLiteral::Property::PROTOTYPE: 1272 case ObjectLiteral::Property::PROTOTYPE:
1240 __ push(Operand(rsp, 0)); // Duplicate receiver. 1273 __ push(Operand(rsp, 0)); // Duplicate receiver.
1241 VisitForStackValue(key); 1274 VisitForStackValue(key);
1242 VisitForStackValue(value); 1275 VisitForStackValue(value);
1243 if (property->emit_store()) { 1276 if (property->emit_store()) {
1244 __ CallRuntime(Runtime::kSetProperty, 3); 1277 __ CallRuntime(Runtime::kSetProperty, 3);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1313 VisitForAccumulatorValue(subexpr); 1346 VisitForAccumulatorValue(subexpr);
1314 1347
1315 // Store the subexpression value in the array's elements. 1348 // Store the subexpression value in the array's elements.
1316 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal. 1349 __ movq(rbx, Operand(rsp, 0)); // Copy of array literal.
1317 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); 1350 __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
1318 int offset = FixedArray::kHeaderSize + (i * kPointerSize); 1351 int offset = FixedArray::kHeaderSize + (i * kPointerSize);
1319 __ movq(FieldOperand(rbx, offset), result_register()); 1352 __ movq(FieldOperand(rbx, offset), result_register());
1320 1353
1321 // Update the write barrier for the array store. 1354 // Update the write barrier for the array store.
1322 __ RecordWrite(rbx, offset, result_register(), rcx); 1355 __ RecordWrite(rbx, offset, result_register(), rcx);
1356
1357 PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
1323 } 1358 }
1324 1359
1325 if (result_saved) { 1360 if (result_saved) {
1326 context()->PlugTOS(); 1361 context()->PlugTOS();
1327 } else { 1362 } else {
1328 context()->Plug(rax); 1363 context()->Plug(rax);
1329 } 1364 }
1330 } 1365 }
1331 1366
1332 1367
(...skipping 24 matching lines...) Expand all
1357 break; 1392 break;
1358 case NAMED_PROPERTY: 1393 case NAMED_PROPERTY:
1359 if (expr->is_compound()) { 1394 if (expr->is_compound()) {
1360 // We need the receiver both on the stack and in the accumulator. 1395 // We need the receiver both on the stack and in the accumulator.
1361 VisitForAccumulatorValue(property->obj()); 1396 VisitForAccumulatorValue(property->obj());
1362 __ push(result_register()); 1397 __ push(result_register());
1363 } else { 1398 } else {
1364 VisitForStackValue(property->obj()); 1399 VisitForStackValue(property->obj());
1365 } 1400 }
1366 break; 1401 break;
1367 case KEYED_PROPERTY: 1402 case KEYED_PROPERTY: {
1368 if (expr->is_compound()) { 1403 if (expr->is_compound()) {
1369 VisitForStackValue(property->obj()); 1404 if (property->is_arguments_access()) {
1370 VisitForAccumulatorValue(property->key()); 1405 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1406 MemOperand slot_operand =
1407 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1408 __ push(slot_operand);
1409 __ Move(rax, property->key()->AsLiteral()->handle());
1410 } else {
1411 VisitForStackValue(property->obj());
1412 VisitForAccumulatorValue(property->key());
1413 }
1371 __ movq(rdx, Operand(rsp, 0)); 1414 __ movq(rdx, Operand(rsp, 0));
1372 __ push(rax); 1415 __ push(rax);
1373 } else { 1416 } else {
1374 VisitForStackValue(property->obj()); 1417 if (property->is_arguments_access()) {
1375 VisitForStackValue(property->key()); 1418 VariableProxy* obj_proxy = property->obj()->AsVariableProxy();
1419 MemOperand slot_operand =
1420 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
1421 __ push(slot_operand);
1422 __ Push(property->key()->AsLiteral()->handle());
1423 } else {
1424 VisitForStackValue(property->obj());
1425 VisitForStackValue(property->key());
1426 }
1376 } 1427 }
1377 break; 1428 break;
1429 }
1378 } 1430 }
1379 1431
1380 if (expr->is_compound()) { 1432 if (expr->is_compound()) {
1381 { AccumulatorValueContext context(this); 1433 { AccumulatorValueContext context(this);
1382 switch (assign_type) { 1434 switch (assign_type) {
1383 case VARIABLE: 1435 case VARIABLE:
1384 EmitVariableLoad(expr->target()->AsVariableProxy()->var()); 1436 EmitVariableLoad(expr->target()->AsVariableProxy()->var());
1385 break; 1437 break;
1386 case NAMED_PROPERTY: 1438 case NAMED_PROPERTY:
1387 EmitNamedPropertyLoad(property); 1439 EmitNamedPropertyLoad(property);
1388 break; 1440 break;
1389 case KEYED_PROPERTY: 1441 case KEYED_PROPERTY:
1390 EmitKeyedPropertyLoad(property); 1442 EmitKeyedPropertyLoad(property);
1391 break; 1443 break;
1392 } 1444 }
1393 } 1445 }
1394 1446
1447 // For property compound assignments we need another deoptimization
1448 // point after the property load.
1449 if (property != NULL) {
1450 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
1451 }
1452
1395 Token::Value op = expr->binary_op(); 1453 Token::Value op = expr->binary_op();
1396 ConstantOperand constant = ShouldInlineSmiCase(op) 1454 ConstantOperand constant = ShouldInlineSmiCase(op)
1397 ? GetConstantOperand(op, expr->target(), expr->value()) 1455 ? GetConstantOperand(op, expr->target(), expr->value())
1398 : kNoConstants; 1456 : kNoConstants;
1399 ASSERT(constant == kRightConstant || constant == kNoConstants); 1457 ASSERT(constant == kRightConstant || constant == kNoConstants);
1400 if (constant == kNoConstants) { 1458 if (constant == kNoConstants) {
1401 __ push(rax); // Left operand goes on the stack. 1459 __ push(rax); // Left operand goes on the stack.
1402 VisitForAccumulatorValue(expr->value()); 1460 VisitForAccumulatorValue(expr->value());
1403 } 1461 }
1404 1462
1405 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1463 OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1406 ? OVERWRITE_RIGHT 1464 ? OVERWRITE_RIGHT
1407 : NO_OVERWRITE; 1465 : NO_OVERWRITE;
1408 SetSourcePosition(expr->position() + 1); 1466 SetSourcePosition(expr->position() + 1);
1409 AccumulatorValueContext context(this); 1467 AccumulatorValueContext context(this);
1410 if (ShouldInlineSmiCase(op)) { 1468 if (ShouldInlineSmiCase(op)) {
1411 EmitInlineSmiBinaryOp(expr, 1469 EmitInlineSmiBinaryOp(expr,
1412 op, 1470 op,
1413 mode, 1471 mode,
1414 expr->target(), 1472 expr->target(),
1415 expr->value(), 1473 expr->value(),
1416 constant); 1474 constant);
1417 } else { 1475 } else {
1418 EmitBinaryOp(op, mode); 1476 EmitBinaryOp(op, mode);
1419 } 1477 }
1478 // Deoptimization point in case the binary operation may have side effects.
1479 PrepareForBailout(expr->binary_operation(), TOS_REG);
1420 } else { 1480 } else {
1421 VisitForAccumulatorValue(expr->value()); 1481 VisitForAccumulatorValue(expr->value());
1422 } 1482 }
1423 1483
1424 // Record source position before possible IC call. 1484 // Record source position before possible IC call.
1425 SetSourcePosition(expr->position()); 1485 SetSourcePosition(expr->position());
1426 1486
1427 // Store the value. 1487 // Store the value.
1428 switch (assign_type) { 1488 switch (assign_type) {
1429 case VARIABLE: 1489 case VARIABLE:
1430 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(), 1490 EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
1431 expr->op()); 1491 expr->op());
1492 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1432 context()->Plug(rax); 1493 context()->Plug(rax);
1433 break; 1494 break;
1434 case NAMED_PROPERTY: 1495 case NAMED_PROPERTY:
1435 EmitNamedPropertyAssignment(expr); 1496 EmitNamedPropertyAssignment(expr);
1436 break; 1497 break;
1437 case KEYED_PROPERTY: 1498 case KEYED_PROPERTY:
1438 EmitKeyedPropertyAssignment(expr); 1499 EmitKeyedPropertyAssignment(expr);
1439 break; 1500 break;
1440 } 1501 }
1441 } 1502 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1533 __ pop(rdx); 1594 __ pop(rdx);
1534 stub.GenerateCall(masm_, rdx, rax); 1595 stub.GenerateCall(masm_, rdx, rax);
1535 } else { 1596 } else {
1536 __ push(result_register()); 1597 __ push(result_register());
1537 __ CallStub(&stub); 1598 __ CallStub(&stub);
1538 } 1599 }
1539 context()->Plug(rax); 1600 context()->Plug(rax);
1540 } 1601 }
1541 1602
1542 1603
1543 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_id) { 1604 void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
1544 // Invalid left-hand sides are rewritten to have a 'throw 1605 // Invalid left-hand sides are rewritten to have a 'throw
1545 // ReferenceError' on the left-hand side. 1606 // ReferenceError' on the left-hand side.
1546 if (!expr->IsValidLeftHandSide()) { 1607 if (!expr->IsValidLeftHandSide()) {
1547 VisitForEffect(expr); 1608 VisitForEffect(expr);
1548 return; 1609 return;
1549 } 1610 }
1550 1611
1551 // Left-hand side can only be a property, a global or a (parameter or local) 1612 // Left-hand side can only be a property, a global or a (parameter or local)
1552 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY. 1613 // slot. Variables with rewrite to .arguments are treated as KEYED_PROPERTY.
1553 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; 1614 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
(...skipping 29 matching lines...) Expand all
1583 VisitForAccumulatorValue(prop->key()); 1644 VisitForAccumulatorValue(prop->key());
1584 __ movq(rcx, rax); 1645 __ movq(rcx, rax);
1585 __ pop(rdx); 1646 __ pop(rdx);
1586 __ pop(rax); 1647 __ pop(rax);
1587 Handle<Code> ic(isolate()->builtins()->builtin( 1648 Handle<Code> ic(isolate()->builtins()->builtin(
1588 Builtins::KeyedStoreIC_Initialize)); 1649 Builtins::KeyedStoreIC_Initialize));
1589 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1650 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1590 break; 1651 break;
1591 } 1652 }
1592 } 1653 }
1654 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
1593 context()->Plug(rax); 1655 context()->Plug(rax);
1594 } 1656 }
1595 1657
1596 1658
1597 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1659 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
1598 Token::Value op) { 1660 Token::Value op) {
1599 // Left-hand sides that rewrite to explicit property accesses do not reach 1661 // Left-hand sides that rewrite to explicit property accesses do not reach
1600 // here. 1662 // here.
1601 ASSERT(var != NULL); 1663 ASSERT(var != NULL);
1602 ASSERT(var->is_global() || var->AsSlot() != NULL); 1664 ASSERT(var->is_global() || var->AsSlot() != NULL);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
1696 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1758 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1697 1759
1698 // If the assignment ends an initialization block, revert to fast case. 1760 // If the assignment ends an initialization block, revert to fast case.
1699 if (expr->ends_initialization_block()) { 1761 if (expr->ends_initialization_block()) {
1700 __ push(rax); // Result of assignment, saved even if not needed. 1762 __ push(rax); // Result of assignment, saved even if not needed.
1701 __ push(Operand(rsp, kPointerSize)); // Receiver is under value. 1763 __ push(Operand(rsp, kPointerSize)); // Receiver is under value.
1702 __ CallRuntime(Runtime::kToFastProperties, 1); 1764 __ CallRuntime(Runtime::kToFastProperties, 1);
1703 __ pop(rax); 1765 __ pop(rax);
1704 __ Drop(1); 1766 __ Drop(1);
1705 } 1767 }
1768 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1706 context()->Plug(rax); 1769 context()->Plug(rax);
1707 } 1770 }
1708 1771
1709 1772
1710 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 1773 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
1711 // Assignment to a property, using a keyed store IC. 1774 // Assignment to a property, using a keyed store IC.
1712 1775
1713 // If the assignment starts a block of assignments to the same object, 1776 // If the assignment starts a block of assignments to the same object,
1714 // change to slow case to avoid the quadratic behavior of repeatedly 1777 // change to slow case to avoid the quadratic behavior of repeatedly
1715 // adding fast properties. 1778 // adding fast properties.
(...skipping 19 matching lines...) Expand all
1735 1798
1736 // If the assignment ends an initialization block, revert to fast case. 1799 // If the assignment ends an initialization block, revert to fast case.
1737 if (expr->ends_initialization_block()) { 1800 if (expr->ends_initialization_block()) {
1738 __ pop(rdx); 1801 __ pop(rdx);
1739 __ push(rax); // Result of assignment, saved even if not needed. 1802 __ push(rax); // Result of assignment, saved even if not needed.
1740 __ push(rdx); 1803 __ push(rdx);
1741 __ CallRuntime(Runtime::kToFastProperties, 1); 1804 __ CallRuntime(Runtime::kToFastProperties, 1);
1742 __ pop(rax); 1805 __ pop(rax);
1743 } 1806 }
1744 1807
1808 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
1745 context()->Plug(rax); 1809 context()->Plug(rax);
1746 } 1810 }
1747 1811
1748 1812
1749 void FullCodeGenerator::VisitProperty(Property* expr) { 1813 void FullCodeGenerator::VisitProperty(Property* expr) {
1750 Comment cmnt(masm_, "[ Property"); 1814 Comment cmnt(masm_, "[ Property");
1751 Expression* key = expr->key(); 1815 Expression* key = expr->key();
1752 1816
1753 if (key->IsPropertyName()) { 1817 if (key->IsPropertyName()) {
1754 VisitForAccumulatorValue(expr->obj()); 1818 VisitForAccumulatorValue(expr->obj());
(...skipping 21 matching lines...) Expand all
1776 } 1840 }
1777 __ Move(rcx, name); 1841 __ Move(rcx, name);
1778 } 1842 }
1779 // Record source position for debugger. 1843 // Record source position for debugger.
1780 SetSourcePosition(expr->position()); 1844 SetSourcePosition(expr->position());
1781 // Call the IC initialization code. 1845 // Call the IC initialization code.
1782 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1846 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1783 Handle<Code> ic = 1847 Handle<Code> ic =
1784 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop); 1848 ISOLATE->stub_cache()->ComputeCallInitialize(arg_count, in_loop);
1785 EmitCallIC(ic, mode); 1849 EmitCallIC(ic, mode);
1850 RecordJSReturnSite(expr);
1786 // Restore context register. 1851 // Restore context register.
1787 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1852 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1788 context()->Plug(rax); 1853 context()->Plug(rax);
1789 } 1854 }
1790 1855
1791 1856
1792 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 1857 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
1793 Expression* key, 1858 Expression* key,
1794 RelocInfo::Mode mode) { 1859 RelocInfo::Mode mode) {
1795 // Load the key. 1860 // Load the key.
(...skipping 14 matching lines...) Expand all
1810 } 1875 }
1811 } 1876 }
1812 // Record source position for debugger. 1877 // Record source position for debugger.
1813 SetSourcePosition(expr->position()); 1878 SetSourcePosition(expr->position());
1814 // Call the IC initialization code. 1879 // Call the IC initialization code.
1815 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1880 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1816 Handle<Code> ic = 1881 Handle<Code> ic =
1817 ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop); 1882 ISOLATE->stub_cache()->ComputeKeyedCallInitialize(arg_count, in_loop);
1818 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. 1883 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key.
1819 EmitCallIC(ic, mode); 1884 EmitCallIC(ic, mode);
1885 RecordJSReturnSite(expr);
1820 // Restore context register. 1886 // Restore context register.
1821 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1887 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1822 context()->DropAndPlug(1, rax); // Drop the key still on the stack. 1888 context()->DropAndPlug(1, rax); // Drop the key still on the stack.
1823 } 1889 }
1824 1890
1825 1891
1826 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 1892 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
1827 // Code common for calls using the call stub. 1893 // Code common for calls using the call stub.
1828 ZoneList<Expression*>* args = expr->arguments(); 1894 ZoneList<Expression*>* args = expr->arguments();
1829 int arg_count = args->length(); 1895 int arg_count = args->length();
1830 { PreservePositionScope scope(masm()->positions_recorder()); 1896 { PreservePositionScope scope(masm()->positions_recorder());
1831 for (int i = 0; i < arg_count; i++) { 1897 for (int i = 0; i < arg_count; i++) {
1832 VisitForStackValue(args->at(i)); 1898 VisitForStackValue(args->at(i));
1833 } 1899 }
1834 } 1900 }
1835 // Record source position for debugger. 1901 // Record source position for debugger.
1836 SetSourcePosition(expr->position()); 1902 SetSourcePosition(expr->position());
1837 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1903 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1838 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1904 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1839 __ CallStub(&stub); 1905 __ CallStub(&stub);
1906 RecordJSReturnSite(expr);
1840 // Restore context register. 1907 // Restore context register.
1841 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1908 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1842 // Discard the function left on TOS. 1909 // Discard the function left on TOS.
1843 context()->DropAndPlug(1, rax); 1910 context()->DropAndPlug(1, rax);
1844 } 1911 }
1845 1912
1846 1913
1847 void FullCodeGenerator::VisitCall(Call* expr) { 1914 void FullCodeGenerator::VisitCall(Call* expr) {
1915 #ifdef DEBUG
1916 // We want to verify that RecordJSReturnSite gets called on all paths
1917 // through this function. Avoid early returns.
1918 expr->return_is_recorded_ = false;
1919 #endif
1920
1848 Comment cmnt(masm_, "[ Call"); 1921 Comment cmnt(masm_, "[ Call");
1849 Expression* fun = expr->expression(); 1922 Expression* fun = expr->expression();
1850 Variable* var = fun->AsVariableProxy()->AsVariable(); 1923 Variable* var = fun->AsVariableProxy()->AsVariable();
1851 1924
1852 if (var != NULL && var->is_possibly_eval()) { 1925 if (var != NULL && var->is_possibly_eval()) {
1853 // In a call to eval, we first call %ResolvePossiblyDirectEval to 1926 // In a call to eval, we first call %ResolvePossiblyDirectEval to
1854 // resolve the function we need to call and the receiver of the 1927 // resolve the function we need to call and the receiver of the
1855 // call. The we call the resolved function using the given 1928 // call. Then we call the resolved function using the given
1856 // arguments. 1929 // arguments.
1857 ZoneList<Expression*>* args = expr->arguments(); 1930 ZoneList<Expression*>* args = expr->arguments();
1858 int arg_count = args->length(); 1931 int arg_count = args->length();
1859 { PreservePositionScope pos_scope(masm()->positions_recorder()); 1932 { PreservePositionScope pos_scope(masm()->positions_recorder());
1860 VisitForStackValue(fun); 1933 VisitForStackValue(fun);
1861 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. 1934 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot.
1862 1935
1863 // Push the arguments. 1936 // Push the arguments.
1864 for (int i = 0; i < arg_count; i++) { 1937 for (int i = 0; i < arg_count; i++) {
1865 VisitForStackValue(args->at(i)); 1938 VisitForStackValue(args->at(i));
(...skipping 16 matching lines...) Expand all
1882 // The runtime call returns a pair of values in rax (function) and 1955 // The runtime call returns a pair of values in rax (function) and
1883 // rdx (receiver). Touch up the stack with the right values. 1956 // rdx (receiver). Touch up the stack with the right values.
1884 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); 1957 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
1885 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); 1958 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
1886 } 1959 }
1887 // Record source position for debugger. 1960 // Record source position for debugger.
1888 SetSourcePosition(expr->position()); 1961 SetSourcePosition(expr->position());
1889 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 1962 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
1890 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 1963 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
1891 __ CallStub(&stub); 1964 __ CallStub(&stub);
1965 RecordJSReturnSite(expr);
1892 // Restore context register. 1966 // Restore context register.
1893 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 1967 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
1894 context()->DropAndPlug(1, rax); 1968 context()->DropAndPlug(1, rax);
1895 } else if (var != NULL && !var->is_this() && var->is_global()) { 1969 } else if (var != NULL && !var->is_this() && var->is_global()) {
1896 // Call to a global variable. 1970 // Call to a global variable.
1897 // Push global object as receiver for the call IC lookup. 1971 // Push global object as receiver for the call IC lookup.
1898 __ push(GlobalObjectOperand()); 1972 __ push(GlobalObjectOperand());
1899 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); 1973 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT);
1900 } else if (var != NULL && var->AsSlot() != NULL && 1974 } else if (var != NULL && var->AsSlot() != NULL &&
1901 var->AsSlot()->type() == Slot::LOOKUP) { 1975 var->AsSlot()->type() == Slot::LOOKUP) {
1902 // Call to a lookup slot (dynamically introduced variable). 1976 // Call to a lookup slot (dynamically introduced variable).
1903 Label slow, done; 1977 Label slow, done;
1904 1978
1905 { PreservePositionScope scope(masm()->positions_recorder()); 1979 { PreservePositionScope scope(masm()->positions_recorder());
1906 // Generate code for loading from variables potentially shadowed 1980 // Generate code for loading from variables potentially shadowed
1907 // by eval-introduced variables. 1981 // by eval-introduced variables.
1908 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), 1982 EmitDynamicLoadFromSlotFastCase(var->AsSlot(),
1909 NOT_INSIDE_TYPEOF, 1983 NOT_INSIDE_TYPEOF,
1910 &slow, 1984 &slow,
1911 &done); 1985 &done);
1912 1986
1913 __ bind(&slow); 1987 __ bind(&slow);
1914 // Call the runtime to find the function to call (returned in rax) 1988 }
1915 // and the object holding it (returned in rdx). 1989 // Call the runtime to find the function to call (returned in rax)
1916 __ push(context_register()); 1990 // and the object holding it (returned in rdx).
1917 __ Push(var->name()); 1991 __ push(context_register());
1918 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1992 __ Push(var->name());
1919 __ push(rax); // Function. 1993 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1920 __ push(rdx); // Receiver. 1994 __ push(rax); // Function.
1995 __ push(rdx); // Receiver.
1921 1996
1922 // If fast case code has been generated, emit code to push the 1997 // If fast case code has been generated, emit code to push the
1923 // function and receiver and have the slow path jump around this 1998 // function and receiver and have the slow path jump around this
1924 // code. 1999 // code.
1925 if (done.is_linked()) { 2000 if (done.is_linked()) {
1926 NearLabel call; 2001 NearLabel call;
1927 __ jmp(&call); 2002 __ jmp(&call);
1928 __ bind(&done); 2003 __ bind(&done);
1929 // Push function. 2004 // Push function.
1930 __ push(rax); 2005 __ push(rax);
1931 // Push global receiver. 2006 // Push global receiver.
1932 __ movq(rbx, GlobalObjectOperand()); 2007 __ movq(rbx, GlobalObjectOperand());
1933 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 2008 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1934 __ bind(&call); 2009 __ bind(&call);
1935 }
1936 } 2010 }
1937 2011
1938 EmitCallWithStub(expr); 2012 EmitCallWithStub(expr);
1939
1940 } else if (fun->AsProperty() != NULL) { 2013 } else if (fun->AsProperty() != NULL) {
1941 // Call to an object property. 2014 // Call to an object property.
1942 Property* prop = fun->AsProperty(); 2015 Property* prop = fun->AsProperty();
1943 Literal* key = prop->key()->AsLiteral(); 2016 Literal* key = prop->key()->AsLiteral();
1944 if (key != NULL && key->handle()->IsSymbol()) { 2017 if (key != NULL && key->handle()->IsSymbol()) {
1945 // Call to a named property, use call IC. 2018 // Call to a named property, use call IC.
1946 { PreservePositionScope scope(masm()->positions_recorder()); 2019 { PreservePositionScope scope(masm()->positions_recorder());
1947 VisitForStackValue(prop->obj()); 2020 VisitForStackValue(prop->obj());
1948 } 2021 }
1949 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2022 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
1950 } else { 2023 } else {
1951 // Call to a keyed property. 2024 // Call to a keyed property.
1952 // For a synthetic property use keyed load IC followed by function call, 2025 // For a synthetic property use keyed load IC followed by function call,
1953 // for a regular property use KeyedCallIC. 2026 // for a regular property use keyed EmitCallIC.
1954 { PreservePositionScope scope(masm()->positions_recorder()); 2027 { PreservePositionScope scope(masm()->positions_recorder());
1955 VisitForStackValue(prop->obj()); 2028 VisitForStackValue(prop->obj());
1956 } 2029 }
1957 if (prop->is_synthetic()) { 2030 if (prop->is_synthetic()) {
1958 { PreservePositionScope scope(masm()->positions_recorder()); 2031 { PreservePositionScope scope(masm()->positions_recorder());
1959 VisitForAccumulatorValue(prop->key()); 2032 VisitForAccumulatorValue(prop->key());
1960 __ movq(rdx, Operand(rsp, 0));
1961 } 2033 }
1962 // Record source code position for IC call. 2034 // Record source code position for IC call.
1963 SetSourcePosition(prop->position()); 2035 SetSourcePosition(prop->position());
2036 __ pop(rdx); // We do not need to keep the receiver.
2037
1964 Handle<Code> ic(isolate()->builtins()->builtin( 2038 Handle<Code> ic(isolate()->builtins()->builtin(
1965 Builtins::KeyedLoadIC_Initialize)); 2039 Builtins::KeyedLoadIC_Initialize));
1966 EmitCallIC(ic, RelocInfo::CODE_TARGET); 2040 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1967 // Pop receiver.
1968 __ pop(rbx);
1969 // Push result (function). 2041 // Push result (function).
1970 __ push(rax); 2042 __ push(rax);
1971 // Push receiver object on stack. 2043 // Push Global receiver.
1972 __ movq(rcx, GlobalObjectOperand()); 2044 __ movq(rcx, GlobalObjectOperand());
1973 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 2045 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
1974 EmitCallWithStub(expr); 2046 EmitCallWithStub(expr);
1975 } else { 2047 } else {
1976 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); 2048 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
1977 } 2049 }
1978 } 2050 }
1979 } else { 2051 } else {
1980 // Call to some other expression. If the expression is an anonymous 2052 // Call to some other expression. If the expression is an anonymous
1981 // function literal not called in a loop, mark it as one that should 2053 // function literal not called in a loop, mark it as one that should
1982 // also use the fast code generator. 2054 // also use the full code generator.
1983 FunctionLiteral* lit = fun->AsFunctionLiteral(); 2055 FunctionLiteral* lit = fun->AsFunctionLiteral();
1984 if (lit != NULL && 2056 if (lit != NULL &&
1985 lit->name()->Equals(isolate()->heap()->empty_string()) && 2057 lit->name()->Equals(isolate()->heap()->empty_string()) &&
1986 loop_depth() == 0) { 2058 loop_depth() == 0) {
1987 lit->set_try_full_codegen(true); 2059 lit->set_try_full_codegen(true);
1988 } 2060 }
1989 { PreservePositionScope scope(masm()->positions_recorder()); 2061 { PreservePositionScope scope(masm()->positions_recorder());
1990 VisitForStackValue(fun); 2062 VisitForStackValue(fun);
1991 } 2063 }
1992 // Load global receiver object. 2064 // Load global receiver object.
1993 __ movq(rbx, GlobalObjectOperand()); 2065 __ movq(rbx, GlobalObjectOperand());
1994 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); 2066 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
1995 // Emit function call. 2067 // Emit function call.
1996 EmitCallWithStub(expr); 2068 EmitCallWithStub(expr);
1997 } 2069 }
2070
2071 #ifdef DEBUG
2072 // RecordJSReturnSite should have been called.
2073 ASSERT(expr->return_is_recorded_);
2074 #endif
1998 } 2075 }
1999 2076
2000 2077
2001 void FullCodeGenerator::VisitCallNew(CallNew* expr) { 2078 void FullCodeGenerator::VisitCallNew(CallNew* expr) {
2002 Comment cmnt(masm_, "[ CallNew"); 2079 Comment cmnt(masm_, "[ CallNew");
2003 // According to ECMA-262, section 11.2.2, page 44, the function 2080 // According to ECMA-262, section 11.2.2, page 44, the function
2004 // expression in new calls must be evaluated before the 2081 // expression in new calls must be evaluated before the
2005 // arguments. 2082 // arguments.
2006 2083
2007 // Push constructor on the stack. If it's not a function it's used as 2084 // Push constructor on the stack. If it's not a function it's used as
(...skipping 28 matching lines...) Expand all
2036 2113
2037 VisitForAccumulatorValue(args->at(0)); 2114 VisitForAccumulatorValue(args->at(0));
2038 2115
2039 Label materialize_true, materialize_false; 2116 Label materialize_true, materialize_false;
2040 Label* if_true = NULL; 2117 Label* if_true = NULL;
2041 Label* if_false = NULL; 2118 Label* if_false = NULL;
2042 Label* fall_through = NULL; 2119 Label* fall_through = NULL;
2043 context()->PrepareTest(&materialize_true, &materialize_false, 2120 context()->PrepareTest(&materialize_true, &materialize_false,
2044 &if_true, &if_false, &fall_through); 2121 &if_true, &if_false, &fall_through);
2045 2122
2123 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2046 __ JumpIfSmi(rax, if_true); 2124 __ JumpIfSmi(rax, if_true);
2047 __ jmp(if_false); 2125 __ jmp(if_false);
2048 2126
2049 context()->Plug(if_true, if_false); 2127 context()->Plug(if_true, if_false);
2050 } 2128 }
2051 2129
2052 2130
2053 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { 2131 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) {
2054 ASSERT(args->length() == 1); 2132 ASSERT(args->length() == 1);
2055 2133
2056 VisitForAccumulatorValue(args->at(0)); 2134 VisitForAccumulatorValue(args->at(0));
2057 2135
2058 Label materialize_true, materialize_false; 2136 Label materialize_true, materialize_false;
2059 Label* if_true = NULL; 2137 Label* if_true = NULL;
2060 Label* if_false = NULL; 2138 Label* if_false = NULL;
2061 Label* fall_through = NULL; 2139 Label* fall_through = NULL;
2062 context()->PrepareTest(&materialize_true, &materialize_false, 2140 context()->PrepareTest(&materialize_true, &materialize_false,
2063 &if_true, &if_false, &fall_through); 2141 &if_true, &if_false, &fall_through);
2064 2142
2143 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2065 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax); 2144 Condition non_negative_smi = masm()->CheckNonNegativeSmi(rax);
2066 Split(non_negative_smi, if_true, if_false, fall_through); 2145 Split(non_negative_smi, if_true, if_false, fall_through);
2067 2146
2068 context()->Plug(if_true, if_false); 2147 context()->Plug(if_true, if_false);
2069 } 2148 }
2070 2149
2071 2150
2072 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { 2151 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
2073 ASSERT(args->length() == 1); 2152 ASSERT(args->length() == 1);
2074 2153
(...skipping 11 matching lines...) Expand all
2086 __ j(equal, if_true); 2165 __ j(equal, if_true);
2087 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2166 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2088 // Undetectable objects behave like undefined when tested with typeof. 2167 // Undetectable objects behave like undefined when tested with typeof.
2089 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2168 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2090 Immediate(1 << Map::kIsUndetectable)); 2169 Immediate(1 << Map::kIsUndetectable));
2091 __ j(not_zero, if_false); 2170 __ j(not_zero, if_false);
2092 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); 2171 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset));
2093 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); 2172 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE));
2094 __ j(below, if_false); 2173 __ j(below, if_false);
2095 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); 2174 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE));
2175 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2096 Split(below_equal, if_true, if_false, fall_through); 2176 Split(below_equal, if_true, if_false, fall_through);
2097 2177
2098 context()->Plug(if_true, if_false); 2178 context()->Plug(if_true, if_false);
2099 } 2179 }
2100 2180
2101 2181
2102 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { 2182 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) {
2103 ASSERT(args->length() == 1); 2183 ASSERT(args->length() == 1);
2104 2184
2105 VisitForAccumulatorValue(args->at(0)); 2185 VisitForAccumulatorValue(args->at(0));
2106 2186
2107 Label materialize_true, materialize_false; 2187 Label materialize_true, materialize_false;
2108 Label* if_true = NULL; 2188 Label* if_true = NULL;
2109 Label* if_false = NULL; 2189 Label* if_false = NULL;
2110 Label* fall_through = NULL; 2190 Label* fall_through = NULL;
2111 context()->PrepareTest(&materialize_true, &materialize_false, 2191 context()->PrepareTest(&materialize_true, &materialize_false,
2112 &if_true, &if_false, &fall_through); 2192 &if_true, &if_false, &fall_through);
2113 2193
2114 __ JumpIfSmi(rax, if_false); 2194 __ JumpIfSmi(rax, if_false);
2115 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); 2195 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx);
2196 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2116 Split(above_equal, if_true, if_false, fall_through); 2197 Split(above_equal, if_true, if_false, fall_through);
2117 2198
2118 context()->Plug(if_true, if_false); 2199 context()->Plug(if_true, if_false);
2119 } 2200 }
2120 2201
2121 2202
2122 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { 2203 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) {
2123 ASSERT(args->length() == 1); 2204 ASSERT(args->length() == 1);
2124 2205
2125 VisitForAccumulatorValue(args->at(0)); 2206 VisitForAccumulatorValue(args->at(0));
2126 2207
2127 Label materialize_true, materialize_false; 2208 Label materialize_true, materialize_false;
2128 Label* if_true = NULL; 2209 Label* if_true = NULL;
2129 Label* if_false = NULL; 2210 Label* if_false = NULL;
2130 Label* fall_through = NULL; 2211 Label* fall_through = NULL;
2131 context()->PrepareTest(&materialize_true, &materialize_false, 2212 context()->PrepareTest(&materialize_true, &materialize_false,
2132 &if_true, &if_false, &fall_through); 2213 &if_true, &if_false, &fall_through);
2133 2214
2134 __ JumpIfSmi(rax, if_false); 2215 __ JumpIfSmi(rax, if_false);
2135 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 2216 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
2136 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), 2217 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
2137 Immediate(1 << Map::kIsUndetectable)); 2218 Immediate(1 << Map::kIsUndetectable));
2219 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2138 Split(not_zero, if_true, if_false, fall_through); 2220 Split(not_zero, if_true, if_false, fall_through);
2139 2221
2140 context()->Plug(if_true, if_false); 2222 context()->Plug(if_true, if_false);
2141 } 2223 }
2142 2224
2143 2225
2144 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 2226 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
2145 ZoneList<Expression*>* args) { 2227 ZoneList<Expression*>* args) {
2146 ASSERT(args->length() == 1); 2228 ASSERT(args->length() == 1);
2147 2229
2148 VisitForAccumulatorValue(args->at(0)); 2230 VisitForAccumulatorValue(args->at(0));
2149 2231
2150 Label materialize_true, materialize_false; 2232 Label materialize_true, materialize_false;
2151 Label* if_true = NULL; 2233 Label* if_true = NULL;
2152 Label* if_false = NULL; 2234 Label* if_false = NULL;
2153 Label* fall_through = NULL; 2235 Label* fall_through = NULL;
2154 context()->PrepareTest(&materialize_true, &materialize_false, 2236 context()->PrepareTest(&materialize_true, &materialize_false,
2155 &if_true, &if_false, &fall_through); 2237 &if_true, &if_false, &fall_through);
2156 2238
2157 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only 2239 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only
2158 // used in a few functions in runtime.js which should not normally be hit by 2240 // used in a few functions in runtime.js which should not normally be hit by
2159 // this compiler. 2241 // this compiler.
2242 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2160 __ jmp(if_false); 2243 __ jmp(if_false);
2161 context()->Plug(if_true, if_false); 2244 context()->Plug(if_true, if_false);
2162 } 2245 }
2163 2246
2164 2247
2165 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { 2248 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) {
2166 ASSERT(args->length() == 1); 2249 ASSERT(args->length() == 1);
2167 2250
2168 VisitForAccumulatorValue(args->at(0)); 2251 VisitForAccumulatorValue(args->at(0));
2169 2252
2170 Label materialize_true, materialize_false; 2253 Label materialize_true, materialize_false;
2171 Label* if_true = NULL; 2254 Label* if_true = NULL;
2172 Label* if_false = NULL; 2255 Label* if_false = NULL;
2173 Label* fall_through = NULL; 2256 Label* fall_through = NULL;
2174 context()->PrepareTest(&materialize_true, &materialize_false, 2257 context()->PrepareTest(&materialize_true, &materialize_false,
2175 &if_true, &if_false, &fall_through); 2258 &if_true, &if_false, &fall_through);
2176 2259
2177 __ JumpIfSmi(rax, if_false); 2260 __ JumpIfSmi(rax, if_false);
2178 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2261 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2262 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2179 Split(equal, if_true, if_false, fall_through); 2263 Split(equal, if_true, if_false, fall_through);
2180 2264
2181 context()->Plug(if_true, if_false); 2265 context()->Plug(if_true, if_false);
2182 } 2266 }
2183 2267
2184 2268
2185 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { 2269 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) {
2186 ASSERT(args->length() == 1); 2270 ASSERT(args->length() == 1);
2187 2271
2188 VisitForAccumulatorValue(args->at(0)); 2272 VisitForAccumulatorValue(args->at(0));
2189 2273
2190 Label materialize_true, materialize_false; 2274 Label materialize_true, materialize_false;
2191 Label* if_true = NULL; 2275 Label* if_true = NULL;
2192 Label* if_false = NULL; 2276 Label* if_false = NULL;
2193 Label* fall_through = NULL; 2277 Label* fall_through = NULL;
2194 context()->PrepareTest(&materialize_true, &materialize_false, 2278 context()->PrepareTest(&materialize_true, &materialize_false,
2195 &if_true, &if_false, &fall_through); 2279 &if_true, &if_false, &fall_through);
2196 2280
2197 __ JumpIfSmi(rax, if_false); 2281 __ JumpIfSmi(rax, if_false);
2198 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); 2282 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx);
2283 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2199 Split(equal, if_true, if_false, fall_through); 2284 Split(equal, if_true, if_false, fall_through);
2200 2285
2201 context()->Plug(if_true, if_false); 2286 context()->Plug(if_true, if_false);
2202 } 2287 }
2203 2288
2204 2289
2205 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { 2290 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) {
2206 ASSERT(args->length() == 1); 2291 ASSERT(args->length() == 1);
2207 2292
2208 VisitForAccumulatorValue(args->at(0)); 2293 VisitForAccumulatorValue(args->at(0));
2209 2294
2210 Label materialize_true, materialize_false; 2295 Label materialize_true, materialize_false;
2211 Label* if_true = NULL; 2296 Label* if_true = NULL;
2212 Label* if_false = NULL; 2297 Label* if_false = NULL;
2213 Label* fall_through = NULL; 2298 Label* fall_through = NULL;
2214 context()->PrepareTest(&materialize_true, &materialize_false, 2299 context()->PrepareTest(&materialize_true, &materialize_false,
2215 &if_true, &if_false, &fall_through); 2300 &if_true, &if_false, &fall_through);
2216 2301
2217 __ JumpIfSmi(rax, if_false); 2302 __ JumpIfSmi(rax, if_false);
2218 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); 2303 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx);
2304 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2219 Split(equal, if_true, if_false, fall_through); 2305 Split(equal, if_true, if_false, fall_through);
2220 2306
2221 context()->Plug(if_true, if_false); 2307 context()->Plug(if_true, if_false);
2222 } 2308 }
2223 2309
2224 2310
2225 2311
2226 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { 2312 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) {
2227 ASSERT(args->length() == 0); 2313 ASSERT(args->length() == 0);
2228 2314
(...skipping 11 matching lines...) Expand all
2240 Label check_frame_marker; 2326 Label check_frame_marker;
2241 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), 2327 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset),
2242 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 2328 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
2243 __ j(not_equal, &check_frame_marker); 2329 __ j(not_equal, &check_frame_marker);
2244 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); 2330 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset));
2245 2331
2246 // Check the marker in the calling frame. 2332 // Check the marker in the calling frame.
2247 __ bind(&check_frame_marker); 2333 __ bind(&check_frame_marker);
2248 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), 2334 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset),
2249 Smi::FromInt(StackFrame::CONSTRUCT)); 2335 Smi::FromInt(StackFrame::CONSTRUCT));
2336 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2250 Split(equal, if_true, if_false, fall_through); 2337 Split(equal, if_true, if_false, fall_through);
2251 2338
2252 context()->Plug(if_true, if_false); 2339 context()->Plug(if_true, if_false);
2253 } 2340 }
2254 2341
2255 2342
2256 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { 2343 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) {
2257 ASSERT(args->length() == 2); 2344 ASSERT(args->length() == 2);
2258 2345
2259 // Load the two objects into registers and perform the comparison. 2346 // Load the two objects into registers and perform the comparison.
2260 VisitForStackValue(args->at(0)); 2347 VisitForStackValue(args->at(0));
2261 VisitForAccumulatorValue(args->at(1)); 2348 VisitForAccumulatorValue(args->at(1));
2262 2349
2263 Label materialize_true, materialize_false; 2350 Label materialize_true, materialize_false;
2264 Label* if_true = NULL; 2351 Label* if_true = NULL;
2265 Label* if_false = NULL; 2352 Label* if_false = NULL;
2266 Label* fall_through = NULL; 2353 Label* fall_through = NULL;
2267 context()->PrepareTest(&materialize_true, &materialize_false, 2354 context()->PrepareTest(&materialize_true, &materialize_false,
2268 &if_true, &if_false, &fall_through); 2355 &if_true, &if_false, &fall_through);
2269 2356
2270 __ pop(rbx); 2357 __ pop(rbx);
2271 __ cmpq(rax, rbx); 2358 __ cmpq(rax, rbx);
2359 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2272 Split(equal, if_true, if_false, fall_through); 2360 Split(equal, if_true, if_false, fall_through);
2273 2361
2274 context()->Plug(if_true, if_false); 2362 context()->Plug(if_true, if_false);
2275 } 2363 }
2276 2364
2277 2365
2278 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { 2366 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
2279 ASSERT(args->length() == 1); 2367 ASSERT(args->length() == 1);
2280 2368
2281 // ArgumentsAccessStub expects the key in rdx and the formal 2369 // ArgumentsAccessStub expects the key in rdx and the formal
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
2835 2923
2836 Label materialize_true, materialize_false; 2924 Label materialize_true, materialize_false;
2837 Label* if_true = NULL; 2925 Label* if_true = NULL;
2838 Label* if_false = NULL; 2926 Label* if_false = NULL;
2839 Label* fall_through = NULL; 2927 Label* fall_through = NULL;
2840 context()->PrepareTest(&materialize_true, &materialize_false, 2928 context()->PrepareTest(&materialize_true, &materialize_false,
2841 &if_true, &if_false, &fall_through); 2929 &if_true, &if_false, &fall_through);
2842 2930
2843 __ testl(FieldOperand(rax, String::kHashFieldOffset), 2931 __ testl(FieldOperand(rax, String::kHashFieldOffset),
2844 Immediate(String::kContainsCachedArrayIndexMask)); 2932 Immediate(String::kContainsCachedArrayIndexMask));
2933 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
2845 __ j(zero, if_true); 2934 __ j(zero, if_true);
2846 __ jmp(if_false); 2935 __ jmp(if_false);
2847 2936
2848 context()->Plug(if_true, if_false); 2937 context()->Plug(if_true, if_false);
2849 } 2938 }
2850 2939
2851 2940
2852 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 2941 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
2853 ASSERT(args->length() == 1); 2942 ASSERT(args->length() == 1);
2854 2943
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2957 3046
2958 case Token::NOT: { 3047 case Token::NOT: {
2959 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3048 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
2960 Label materialize_true, materialize_false; 3049 Label materialize_true, materialize_false;
2961 Label* if_true = NULL; 3050 Label* if_true = NULL;
2962 Label* if_false = NULL; 3051 Label* if_false = NULL;
2963 Label* fall_through = NULL; 3052 Label* fall_through = NULL;
2964 // Notice that the labels are swapped. 3053 // Notice that the labels are swapped.
2965 context()->PrepareTest(&materialize_true, &materialize_false, 3054 context()->PrepareTest(&materialize_true, &materialize_false,
2966 &if_false, &if_true, &fall_through); 3055 &if_false, &if_true, &fall_through);
3056 if (context()->IsTest()) ForwardBailoutToChild(expr);
2967 VisitForControl(expr->expression(), if_true, if_false, fall_through); 3057 VisitForControl(expr->expression(), if_true, if_false, fall_through);
2968 context()->Plug(if_false, if_true); // Labels swapped. 3058 context()->Plug(if_false, if_true); // Labels swapped.
2969 break; 3059 break;
2970 } 3060 }
2971 3061
2972 case Token::TYPEOF: { 3062 case Token::TYPEOF: {
2973 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3063 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
2974 { StackValueContext context(this); 3064 { StackValueContext context(this);
2975 VisitForTypeofValue(expr->expression()); 3065 VisitForTypeofValue(expr->expression());
2976 } 3066 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
3070 } else { 3160 } else {
3071 // Reserve space for result of postfix operation. 3161 // Reserve space for result of postfix operation.
3072 if (expr->is_postfix() && !context()->IsEffect()) { 3162 if (expr->is_postfix() && !context()->IsEffect()) {
3073 __ Push(Smi::FromInt(0)); 3163 __ Push(Smi::FromInt(0));
3074 } 3164 }
3075 if (assign_type == NAMED_PROPERTY) { 3165 if (assign_type == NAMED_PROPERTY) {
3076 VisitForAccumulatorValue(prop->obj()); 3166 VisitForAccumulatorValue(prop->obj());
3077 __ push(rax); // Copy of receiver, needed for later store. 3167 __ push(rax); // Copy of receiver, needed for later store.
3078 EmitNamedPropertyLoad(prop); 3168 EmitNamedPropertyLoad(prop);
3079 } else { 3169 } else {
3080 VisitForStackValue(prop->obj()); 3170 if (prop->is_arguments_access()) {
3081 VisitForAccumulatorValue(prop->key()); 3171 VariableProxy* obj_proxy = prop->obj()->AsVariableProxy();
3172 MemOperand slot_operand =
3173 EmitSlotSearch(obj_proxy->var()->AsSlot(), rcx);
3174 __ push(slot_operand);
3175 __ Move(rax, prop->key()->AsLiteral()->handle());
3176 } else {
3177 VisitForStackValue(prop->obj());
3178 VisitForAccumulatorValue(prop->key());
3179 }
3082 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack 3180 __ movq(rdx, Operand(rsp, 0)); // Leave receiver on stack
3083 __ push(rax); // Copy of key, needed for later store. 3181 __ push(rax); // Copy of key, needed for later store.
3084 EmitKeyedPropertyLoad(prop); 3182 EmitKeyedPropertyLoad(prop);
3085 } 3183 }
3086 } 3184 }
3087 3185
3186 // We need a second deoptimization point after loading the value
3187 // in case evaluating the property load my have a side effect.
3188 PrepareForBailout(expr->increment(), TOS_REG);
3189
3088 // Call ToNumber only if operand is not a smi. 3190 // Call ToNumber only if operand is not a smi.
3089 NearLabel no_conversion; 3191 NearLabel no_conversion;
3090 Condition is_smi; 3192 Condition is_smi;
3091 is_smi = masm_->CheckSmi(rax); 3193 is_smi = masm_->CheckSmi(rax);
3092 __ j(is_smi, &no_conversion); 3194 __ j(is_smi, &no_conversion);
3093 __ push(rax); 3195 __ push(rax);
3094 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); 3196 __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION);
3095 __ bind(&no_conversion); 3197 __ bind(&no_conversion);
3096 3198
3097 // Save result for postfix expressions. 3199 // Save result for postfix expressions.
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3147 __ bind(&done); 3249 __ bind(&done);
3148 3250
3149 // Store the value returned in rax. 3251 // Store the value returned in rax.
3150 switch (assign_type) { 3252 switch (assign_type) {
3151 case VARIABLE: 3253 case VARIABLE:
3152 if (expr->is_postfix()) { 3254 if (expr->is_postfix()) {
3153 // Perform the assignment as if via '='. 3255 // Perform the assignment as if via '='.
3154 { EffectContext context(this); 3256 { EffectContext context(this);
3155 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3257 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3156 Token::ASSIGN); 3258 Token::ASSIGN);
3259 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3157 context.Plug(rax); 3260 context.Plug(rax);
3158 } 3261 }
3159 // For all contexts except kEffect: We have the result on 3262 // For all contexts except kEffect: We have the result on
3160 // top of the stack. 3263 // top of the stack.
3161 if (!context()->IsEffect()) { 3264 if (!context()->IsEffect()) {
3162 context()->PlugTOS(); 3265 context()->PlugTOS();
3163 } 3266 }
3164 } else { 3267 } else {
3165 // Perform the assignment as if via '='. 3268 // Perform the assignment as if via '='.
3166 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3269 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
3167 Token::ASSIGN); 3270 Token::ASSIGN);
3271 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3168 context()->Plug(rax); 3272 context()->Plug(rax);
3169 } 3273 }
3170 break; 3274 break;
3171 case NAMED_PROPERTY: { 3275 case NAMED_PROPERTY: {
3172 __ Move(rcx, prop->key()->AsLiteral()->handle()); 3276 __ Move(rcx, prop->key()->AsLiteral()->handle());
3173 __ pop(rdx); 3277 __ pop(rdx);
3174 Handle<Code> ic(isolate()->builtins()->builtin( 3278 Handle<Code> ic(isolate()->builtins()->builtin(
3175 Builtins::StoreIC_Initialize)); 3279 Builtins::StoreIC_Initialize));
3176 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3280 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3281 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3177 if (expr->is_postfix()) { 3282 if (expr->is_postfix()) {
3178 if (!context()->IsEffect()) { 3283 if (!context()->IsEffect()) {
3179 context()->PlugTOS(); 3284 context()->PlugTOS();
3180 } 3285 }
3181 } else { 3286 } else {
3182 context()->Plug(rax); 3287 context()->Plug(rax);
3183 } 3288 }
3184 break; 3289 break;
3185 } 3290 }
3186 case KEYED_PROPERTY: { 3291 case KEYED_PROPERTY: {
3187 __ pop(rcx); 3292 __ pop(rcx);
3188 __ pop(rdx); 3293 __ pop(rdx);
3189 Handle<Code> ic(isolate()->builtins()->builtin( 3294 Handle<Code> ic(isolate()->builtins()->builtin(
3190 Builtins::KeyedStoreIC_Initialize)); 3295 Builtins::KeyedStoreIC_Initialize));
3191 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3296 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3297 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
3192 if (expr->is_postfix()) { 3298 if (expr->is_postfix()) {
3193 if (!context()->IsEffect()) { 3299 if (!context()->IsEffect()) {
3194 context()->PlugTOS(); 3300 context()->PlugTOS();
3195 } 3301 }
3196 } else { 3302 } else {
3197 context()->Plug(rax); 3303 context()->Plug(rax);
3198 } 3304 }
3199 break; 3305 break;
3200 } 3306 }
3201 } 3307 }
3202 } 3308 }
3203 3309
3204 3310
3205 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 3311 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
3206 VariableProxy* proxy = expr->AsVariableProxy(); 3312 VariableProxy* proxy = expr->AsVariableProxy();
3207 ASSERT(!context()->IsEffect()); 3313 ASSERT(!context()->IsEffect());
3208 ASSERT(!context()->IsTest()); 3314 ASSERT(!context()->IsTest());
3209 3315
3210 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) { 3316 if (proxy != NULL && !proxy->var()->is_this() && proxy->var()->is_global()) {
3211 Comment cmnt(masm_, "Global variable"); 3317 Comment cmnt(masm_, "Global variable");
3212 __ Move(rcx, proxy->name()); 3318 __ Move(rcx, proxy->name());
3213 __ movq(rax, GlobalObjectOperand()); 3319 __ movq(rax, GlobalObjectOperand());
3214 Handle<Code> ic(isolate()->builtins()->builtin( 3320 Handle<Code> ic(isolate()->builtins()->builtin(
3215 Builtins::LoadIC_Initialize)); 3321 Builtins::LoadIC_Initialize));
3216 // Use a regular load, not a contextual load, to avoid a reference 3322 // Use a regular load, not a contextual load, to avoid a reference
3217 // error. 3323 // error.
3218 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3324 EmitCallIC(ic, RelocInfo::CODE_TARGET);
3325 PrepareForBailout(expr, TOS_REG);
3219 context()->Plug(rax); 3326 context()->Plug(rax);
3220 } else if (proxy != NULL && 3327 } else if (proxy != NULL &&
3221 proxy->var()->AsSlot() != NULL && 3328 proxy->var()->AsSlot() != NULL &&
3222 proxy->var()->AsSlot()->type() == Slot::LOOKUP) { 3329 proxy->var()->AsSlot()->type() == Slot::LOOKUP) {
3223 Label done, slow; 3330 Label done, slow;
3224 3331
3225 // Generate code for loading from variables potentially shadowed 3332 // Generate code for loading from variables potentially shadowed
3226 // by eval-introduced variables. 3333 // by eval-introduced variables.
3227 Slot* slot = proxy->var()->AsSlot(); 3334 Slot* slot = proxy->var()->AsSlot();
3228 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done); 3335 EmitDynamicLoadFromSlotFastCase(slot, INSIDE_TYPEOF, &slow, &done);
3229 3336
3230 __ bind(&slow); 3337 __ bind(&slow);
3231 __ push(rsi); 3338 __ push(rsi);
3232 __ Push(proxy->name()); 3339 __ Push(proxy->name());
3233 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 3340 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
3341 PrepareForBailout(expr, TOS_REG);
3234 __ bind(&done); 3342 __ bind(&done);
3235 3343
3236 context()->Plug(rax); 3344 context()->Plug(rax);
3237 } else { 3345 } else {
3238 // This expression cannot throw a reference error at the top level. 3346 // This expression cannot throw a reference error at the top level.
3239 Visit(expr); 3347 context()->HandleExpression(expr);
3240 } 3348 }
3241 } 3349 }
3242 3350
3243 3351
3244 bool FullCodeGenerator::TryLiteralCompare(Token::Value op, 3352 bool FullCodeGenerator::TryLiteralCompare(Token::Value op,
3245 Expression* left, 3353 Expression* left,
3246 Expression* right, 3354 Expression* right,
3247 Label* if_true, 3355 Label* if_true,
3248 Label* if_false, 3356 Label* if_false,
3249 Label* fall_through) { 3357 Label* fall_through) {
3250 if (op != Token::EQ && op != Token::EQ_STRICT) return false; 3358 if (op != Token::EQ && op != Token::EQ_STRICT) return false;
3251 3359
3252 // Check for the pattern: typeof <expression> == <string literal>. 3360 // Check for the pattern: typeof <expression> == <string literal>.
3253 Literal* right_literal = right->AsLiteral(); 3361 Literal* right_literal = right->AsLiteral();
3254 if (right_literal == NULL) return false; 3362 if (right_literal == NULL) return false;
3255 Handle<Object> right_literal_value = right_literal->handle(); 3363 Handle<Object> right_literal_value = right_literal->handle();
3256 if (!right_literal_value->IsString()) return false; 3364 if (!right_literal_value->IsString()) return false;
3257 UnaryOperation* left_unary = left->AsUnaryOperation(); 3365 UnaryOperation* left_unary = left->AsUnaryOperation();
3258 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; 3366 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
3259 Handle<String> check = Handle<String>::cast(right_literal_value); 3367 Handle<String> check = Handle<String>::cast(right_literal_value);
3260 3368
3261 { AccumulatorValueContext context(this); 3369 { AccumulatorValueContext context(this);
3262 VisitForTypeofValue(left_unary->expression()); 3370 VisitForTypeofValue(left_unary->expression());
3263 } 3371 }
3372 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3264 3373
3265 if (check->Equals(isolate()->heap()->number_symbol())) { 3374 if (check->Equals(isolate()->heap()->number_symbol())) {
3266 Condition is_smi = masm_->CheckSmi(rax); 3375 Condition is_smi = masm_->CheckSmi(rax);
3267 __ j(is_smi, if_true); 3376 __ j(is_smi, if_true);
3268 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset)); 3377 __ movq(rax, FieldOperand(rax, HeapObject::kMapOffset));
3269 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); 3378 __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
3270 Split(equal, if_true, if_false, fall_through); 3379 Split(equal, if_true, if_false, fall_through);
3271 } else if (check->Equals(isolate()->heap()->string_symbol())) { 3380 } else if (check->Equals(isolate()->heap()->string_symbol())) {
3272 Condition is_smi = masm_->CheckSmi(rax); 3381 Condition is_smi = masm_->CheckSmi(rax);
3273 __ j(is_smi, if_false); 3382 __ j(is_smi, if_false);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
3347 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { 3456 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) {
3348 context()->Plug(if_true, if_false); 3457 context()->Plug(if_true, if_false);
3349 return; 3458 return;
3350 } 3459 }
3351 3460
3352 VisitForStackValue(expr->left()); 3461 VisitForStackValue(expr->left());
3353 switch (op) { 3462 switch (op) {
3354 case Token::IN: 3463 case Token::IN:
3355 VisitForStackValue(expr->right()); 3464 VisitForStackValue(expr->right());
3356 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); 3465 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION);
3466 PrepareForBailoutBeforeSplit(TOS_REG, false, NULL, NULL);
3357 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 3467 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
3358 Split(equal, if_true, if_false, fall_through); 3468 Split(equal, if_true, if_false, fall_through);
3359 break; 3469 break;
3360 3470
3361 case Token::INSTANCEOF: { 3471 case Token::INSTANCEOF: {
3362 VisitForStackValue(expr->right()); 3472 VisitForStackValue(expr->right());
3363 InstanceofStub stub(InstanceofStub::kNoFlags); 3473 InstanceofStub stub(InstanceofStub::kNoFlags);
3364 __ CallStub(&stub); 3474 __ CallStub(&stub);
3475 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3365 __ testq(rax, rax); 3476 __ testq(rax, rax);
3366 // The stub returns 0 for true. 3477 // The stub returns 0 for true.
3367 Split(zero, if_true, if_false, fall_through); 3478 Split(zero, if_true, if_false, fall_through);
3368 break; 3479 break;
3369 } 3480 }
3370 3481
3371 default: { 3482 default: {
3372 VisitForAccumulatorValue(expr->right()); 3483 VisitForAccumulatorValue(expr->right());
3373 Condition cc = no_condition; 3484 Condition cc = no_condition;
3374 bool strict = false; 3485 bool strict = false;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3413 __ SmiCompare(rdx, rax); 3524 __ SmiCompare(rdx, rax);
3414 Split(cc, if_true, if_false, NULL); 3525 Split(cc, if_true, if_false, NULL);
3415 __ bind(&slow_case); 3526 __ bind(&slow_case);
3416 } 3527 }
3417 3528
3418 CompareFlags flags = inline_smi_code 3529 CompareFlags flags = inline_smi_code
3419 ? NO_SMI_COMPARE_IN_STUB 3530 ? NO_SMI_COMPARE_IN_STUB
3420 : NO_COMPARE_FLAGS; 3531 : NO_COMPARE_FLAGS;
3421 CompareStub stub(cc, strict, flags); 3532 CompareStub stub(cc, strict, flags);
3422 __ CallStub(&stub); 3533 __ CallStub(&stub);
3534
3535 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3423 __ testq(rax, rax); 3536 __ testq(rax, rax);
3424 Split(cc, if_true, if_false, fall_through); 3537 Split(cc, if_true, if_false, fall_through);
3425 } 3538 }
3426 } 3539 }
3427 3540
3428 // Convert the result of the comparison into one expected for this 3541 // Convert the result of the comparison into one expected for this
3429 // expression's context. 3542 // expression's context.
3430 context()->Plug(if_true, if_false); 3543 context()->Plug(if_true, if_false);
3431 } 3544 }
3432 3545
3433 3546
3434 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { 3547 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) {
3435 Comment cmnt(masm_, "[ CompareToNull"); 3548 Comment cmnt(masm_, "[ CompareToNull");
3436 Label materialize_true, materialize_false; 3549 Label materialize_true, materialize_false;
3437 Label* if_true = NULL; 3550 Label* if_true = NULL;
3438 Label* if_false = NULL; 3551 Label* if_false = NULL;
3439 Label* fall_through = NULL; 3552 Label* fall_through = NULL;
3440 context()->PrepareTest(&materialize_true, &materialize_false, 3553 context()->PrepareTest(&materialize_true, &materialize_false,
3441 &if_true, &if_false, &fall_through); 3554 &if_true, &if_false, &fall_through);
3442 3555
3443 VisitForAccumulatorValue(expr->expression()); 3556 VisitForAccumulatorValue(expr->expression());
3557 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3444 __ CompareRoot(rax, Heap::kNullValueRootIndex); 3558 __ CompareRoot(rax, Heap::kNullValueRootIndex);
3445 if (expr->is_strict()) { 3559 if (expr->is_strict()) {
3446 Split(equal, if_true, if_false, fall_through); 3560 Split(equal, if_true, if_false, fall_through);
3447 } else { 3561 } else {
3448 __ j(equal, if_true); 3562 __ j(equal, if_true);
3449 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 3563 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
3450 __ j(equal, if_true); 3564 __ j(equal, if_true);
3451 Condition is_smi = masm_->CheckSmi(rax); 3565 Condition is_smi = masm_->CheckSmi(rax);
3452 __ j(is_smi, if_false); 3566 __ j(is_smi, if_false);
3453 // It can be an undetectable object. 3567 // It can be an undetectable object.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3545 __ ret(0); 3659 __ ret(0);
3546 } 3660 }
3547 3661
3548 3662
3549 #undef __ 3663 #undef __
3550 3664
3551 3665
3552 } } // namespace v8::internal 3666 } } // namespace v8::internal
3553 3667
3554 #endif // V8_TARGET_ARCH_X64 3668 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/deoptimizer-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698