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

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

Issue 6614010: [Isolates] Merge 6700:7030 from bleeding_edge to isolates. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: '' Created 9 years, 9 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/ia32/deoptimizer-ia32.cc ('k') | src/ia32/ic-ia32.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 2011 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
(...skipping 29 matching lines...) Expand all
40 40
41 namespace v8 { 41 namespace v8 {
42 namespace internal { 42 namespace internal {
43 43
44 44
45 #define __ ACCESS_MASM(masm_) 45 #define __ ACCESS_MASM(masm_)
46 46
47 47
48 class JumpPatchSite BASE_EMBEDDED { 48 class JumpPatchSite BASE_EMBEDDED {
49 public: 49 public:
50 explicit JumpPatchSite(MacroAssembler* masm) 50 explicit JumpPatchSite(MacroAssembler* masm) : masm_(masm) {
51 : masm_(masm) {
52 #ifdef DEBUG 51 #ifdef DEBUG
53 info_emitted_ = false; 52 info_emitted_ = false;
54 #endif 53 #endif
55 } 54 }
56 55
57 ~JumpPatchSite() { 56 ~JumpPatchSite() {
58 ASSERT(patch_site_.is_bound() == info_emitted_); 57 ASSERT(patch_site_.is_bound() == info_emitted_);
59 } 58 }
60 59
61 void EmitJumpIfNotSmi(Register reg, NearLabel* target) { 60 void EmitJumpIfNotSmi(Register reg, NearLabel* target) {
62 __ test(reg, Immediate(kSmiTagMask)); 61 __ test(reg, Immediate(kSmiTagMask));
63 EmitJump(not_carry, target); // Always taken before patched. 62 EmitJump(not_carry, target); // Always taken before patched.
64 } 63 }
65 64
66 void EmitJumpIfSmi(Register reg, NearLabel* target) { 65 void EmitJumpIfSmi(Register reg, NearLabel* target) {
67 __ test(reg, Immediate(kSmiTagMask)); 66 __ test(reg, Immediate(kSmiTagMask));
68 EmitJump(carry, target); // Never taken before patched. 67 EmitJump(carry, target); // Never taken before patched.
69 } 68 }
70 69
71 void EmitPatchInfo() { 70 void EmitPatchInfo() {
72 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); 71 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_);
73 ASSERT(is_int8(delta_to_patch_site)); 72 ASSERT(is_int8(delta_to_patch_site));
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 #ifdef ENABLE_DEBUGGER_SUPPORT 315 #ifdef ENABLE_DEBUGGER_SUPPORT
317 // Check that the size of the code used for returning is large enough 316 // Check that the size of the code used for returning is large enough
318 // for the debugger's requirements. 317 // for the debugger's requirements.
319 ASSERT(Assembler::kJSReturnSequenceLength <= 318 ASSERT(Assembler::kJSReturnSequenceLength <=
320 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 319 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
321 #endif 320 #endif
322 } 321 }
323 } 322 }
324 323
325 324
326 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
327 Token::Value op, Expression* left, Expression* right) {
328 ASSERT(ShouldInlineSmiCase(op));
329 if (op == Token::DIV || op == Token::MOD || op == Token::MUL) {
330 // We never generate inlined constant smi operations for these.
331 return kNoConstants;
332 } else if (right->IsSmiLiteral()) {
333 return kRightConstant;
334 } else if (left->IsSmiLiteral() && !Token::IsShiftOp(op)) {
335 return kLeftConstant;
336 } else {
337 return kNoConstants;
338 }
339 }
340
341
342 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { 325 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
343 } 326 }
344 327
345 328
346 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { 329 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
347 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); 330 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
348 __ mov(result_register(), slot_operand); 331 __ mov(result_register(), slot_operand);
349 } 332 }
350 333
351 334
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 void FullCodeGenerator::DoTest(Label* if_true, 526 void FullCodeGenerator::DoTest(Label* if_true,
544 Label* if_false, 527 Label* if_false,
545 Label* fall_through) { 528 Label* fall_through) {
546 // Emit the inlined tests assumed by the stub. 529 // Emit the inlined tests assumed by the stub.
547 __ cmp(result_register(), isolate()->factory()->undefined_value()); 530 __ cmp(result_register(), isolate()->factory()->undefined_value());
548 __ j(equal, if_false); 531 __ j(equal, if_false);
549 __ cmp(result_register(), isolate()->factory()->true_value()); 532 __ cmp(result_register(), isolate()->factory()->true_value());
550 __ j(equal, if_true); 533 __ j(equal, if_true);
551 __ cmp(result_register(), isolate()->factory()->false_value()); 534 __ cmp(result_register(), isolate()->factory()->false_value());
552 __ j(equal, if_false); 535 __ j(equal, if_false);
553 ASSERT_EQ(0, kSmiTag); 536 STATIC_ASSERT(kSmiTag == 0);
554 __ test(result_register(), Operand(result_register())); 537 __ test(result_register(), Operand(result_register()));
555 __ j(zero, if_false); 538 __ j(zero, if_false);
556 __ test(result_register(), Immediate(kSmiTagMask)); 539 __ test(result_register(), Immediate(kSmiTagMask));
557 __ j(zero, if_true); 540 __ j(zero, if_true);
558 541
559 // Call the ToBoolean stub for all other cases. 542 // Call the ToBoolean stub for all other cases.
560 ToBooleanStub stub; 543 ToBooleanStub stub;
561 __ push(result_register()); 544 __ push(result_register());
562 __ CallStub(&stub); 545 __ CallStub(&stub);
563 __ test(eax, Operand(eax)); 546 __ test(eax, Operand(eax));
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 Register src, 594 Register src,
612 Register scratch1, 595 Register scratch1,
613 Register scratch2) { 596 Register scratch2) {
614 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented. 597 ASSERT(dst->type() != Slot::LOOKUP); // Not yet implemented.
615 ASSERT(!scratch1.is(src) && !scratch2.is(src)); 598 ASSERT(!scratch1.is(src) && !scratch2.is(src));
616 MemOperand location = EmitSlotSearch(dst, scratch1); 599 MemOperand location = EmitSlotSearch(dst, scratch1);
617 __ mov(location, src); 600 __ mov(location, src);
618 // Emit the write barrier code if the location is in the heap. 601 // Emit the write barrier code if the location is in the heap.
619 if (dst->type() == Slot::CONTEXT) { 602 if (dst->type() == Slot::CONTEXT) {
620 int offset = Context::SlotOffset(dst->index()); 603 int offset = Context::SlotOffset(dst->index());
604 ASSERT(!scratch1.is(esi) && !src.is(esi) && !scratch2.is(esi));
621 __ RecordWrite(scratch1, offset, src, scratch2); 605 __ RecordWrite(scratch1, offset, src, scratch2);
622 } 606 }
623 } 607 }
624 608
625 609
626 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state, 610 void FullCodeGenerator::PrepareForBailoutBeforeSplit(State state,
627 bool should_normalize, 611 bool should_normalize,
628 Label* if_true, 612 Label* if_true,
629 Label* if_false) { 613 Label* if_false) {
630 // Only prepare for bailouts before splits if we're in a test 614 // Only prepare for bailouts before splits if we're in a test
(...skipping 18 matching lines...) Expand all
649 } 633 }
650 634
651 635
652 void FullCodeGenerator::EmitDeclaration(Variable* variable, 636 void FullCodeGenerator::EmitDeclaration(Variable* variable,
653 Variable::Mode mode, 637 Variable::Mode mode,
654 FunctionLiteral* function) { 638 FunctionLiteral* function) {
655 Comment cmnt(masm_, "[ Declaration"); 639 Comment cmnt(masm_, "[ Declaration");
656 ASSERT(variable != NULL); // Must have been resolved. 640 ASSERT(variable != NULL); // Must have been resolved.
657 Slot* slot = variable->AsSlot(); 641 Slot* slot = variable->AsSlot();
658 Property* prop = variable->AsProperty(); 642 Property* prop = variable->AsProperty();
643
659 if (slot != NULL) { 644 if (slot != NULL) {
660 switch (slot->type()) { 645 switch (slot->type()) {
661 case Slot::PARAMETER: 646 case Slot::PARAMETER:
662 case Slot::LOCAL: 647 case Slot::LOCAL:
663 if (mode == Variable::CONST) { 648 if (mode == Variable::CONST) {
664 __ mov(Operand(ebp, SlotOffset(slot)), 649 __ mov(Operand(ebp, SlotOffset(slot)),
665 Immediate(isolate()->factory()->the_hole_value())); 650 Immediate(isolate()->factory()->the_hole_value()));
666 } else if (function != NULL) { 651 } else if (function != NULL) {
667 VisitForAccumulatorValue(function); 652 VisitForAccumulatorValue(function);
668 __ mov(Operand(ebp, SlotOffset(slot)), result_register()); 653 __ mov(Operand(ebp, SlotOffset(slot)), result_register());
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 VisitForAccumulatorValue(function); 719 VisitForAccumulatorValue(function);
735 __ pop(edx); 720 __ pop(edx);
736 } else { 721 } else {
737 __ mov(edx, eax); 722 __ mov(edx, eax);
738 __ mov(eax, isolate()->factory()->the_hole_value()); 723 __ mov(eax, isolate()->factory()->the_hole_value());
739 } 724 }
740 ASSERT(prop->key()->AsLiteral() != NULL && 725 ASSERT(prop->key()->AsLiteral() != NULL &&
741 prop->key()->AsLiteral()->handle()->IsSmi()); 726 prop->key()->AsLiteral()->handle()->IsSmi());
742 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); 727 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
743 728
744 Handle<Code> ic(isolate()->builtins()->builtin( 729 Handle<Code> ic(isolate()->builtins()->builtin(is_strict()
745 Builtins::KeyedStoreIC_Initialize)); 730 ? Builtins::KeyedStoreIC_Initialize_Strict
731 : Builtins::KeyedStoreIC_Initialize));
746 EmitCallIC(ic, RelocInfo::CODE_TARGET); 732 EmitCallIC(ic, RelocInfo::CODE_TARGET);
747 } 733 }
748 } 734 }
749 } 735 }
750 736
751 737
752 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 738 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
753 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 739 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
754 } 740 }
755 741
756 742
757 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 743 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
758 // Call the runtime to declare the globals. 744 // Call the runtime to declare the globals.
759 __ push(esi); // The context is the first argument. 745 __ push(esi); // The context is the first argument.
760 __ push(Immediate(pairs)); 746 __ push(Immediate(pairs));
761 __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 747 __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
762 __ CallRuntime(Runtime::kDeclareGlobals, 3); 748 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
749 __ CallRuntime(Runtime::kDeclareGlobals, 4);
763 // Return value is ignored. 750 // Return value is ignored.
764 } 751 }
765 752
766 753
767 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 754 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
768 Comment cmnt(masm_, "[ SwitchStatement"); 755 Comment cmnt(masm_, "[ SwitchStatement");
769 Breakable nested_statement(this, stmt); 756 Breakable nested_statement(this, stmt);
770 SetStatementPosition(stmt); 757 SetStatementPosition(stmt);
771 758
772 // Keep the switch value on the stack until a case matches. 759 // Keep the switch value on the stack until a case matches.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 __ j(not_equal, &next_test); 796 __ j(not_equal, &next_test);
810 __ Drop(1); // Switch value is no longer needed. 797 __ Drop(1); // Switch value is no longer needed.
811 __ jmp(clause->body_target()->entry_label()); 798 __ jmp(clause->body_target()->entry_label());
812 __ bind(&slow_case); 799 __ bind(&slow_case);
813 } 800 }
814 801
815 // Record position before stub call for type feedback. 802 // Record position before stub call for type feedback.
816 SetSourcePosition(clause->position()); 803 SetSourcePosition(clause->position());
817 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 804 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
818 EmitCallIC(ic, &patch_site); 805 EmitCallIC(ic, &patch_site);
819
820 __ test(eax, Operand(eax)); 806 __ test(eax, Operand(eax));
821 __ j(not_equal, &next_test); 807 __ j(not_equal, &next_test);
822 __ Drop(1); // Switch value is no longer needed. 808 __ Drop(1); // Switch value is no longer needed.
823 __ jmp(clause->body_target()->entry_label()); 809 __ jmp(clause->body_target()->entry_label());
824 } 810 }
825 811
826 // Discard the test value and jump to the default if present, otherwise to 812 // Discard the test value and jump to the default if present, otherwise to
827 // the end of the statement. 813 // the end of the statement.
828 __ bind(&next_test); 814 __ bind(&next_test);
829 __ Drop(1); // Switch value is no longer needed. 815 __ Drop(1); // Switch value is no longer needed.
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
890 __ j(not_equal, &call_runtime); 876 __ j(not_equal, &call_runtime);
891 877
892 // Check that instance descriptors are not empty so that we can 878 // Check that instance descriptors are not empty so that we can
893 // check for an enum cache. Leave the map in ebx for the subsequent 879 // check for an enum cache. Leave the map in ebx for the subsequent
894 // prototype load. 880 // prototype load.
895 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); 881 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
896 __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset)); 882 __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset));
897 __ cmp(edx, isolate()->factory()->empty_descriptor_array()); 883 __ cmp(edx, isolate()->factory()->empty_descriptor_array());
898 __ j(equal, &call_runtime); 884 __ j(equal, &call_runtime);
899 885
900 // Check that there in an enum cache in the non-empty instance 886 // Check that there is an enum cache in the non-empty instance
901 // descriptors (edx). This is the case if the next enumeration 887 // descriptors (edx). This is the case if the next enumeration
902 // index field does not contain a smi. 888 // index field does not contain a smi.
903 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); 889 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
904 __ test(edx, Immediate(kSmiTagMask)); 890 __ test(edx, Immediate(kSmiTagMask));
905 __ j(zero, &call_runtime); 891 __ j(zero, &call_runtime);
906 892
907 // For all objects but the receiver, check that the cache is empty. 893 // For all objects but the receiver, check that the cache is empty.
908 NearLabel check_prototype; 894 NearLabel check_prototype;
909 __ cmp(ecx, Operand(eax)); 895 __ cmp(ecx, Operand(eax));
910 __ j(equal, &check_prototype); 896 __ j(equal, &check_prototype);
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
1381 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1367 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1382 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1368 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1383 // Fall through. 1369 // Fall through.
1384 case ObjectLiteral::Property::COMPUTED: 1370 case ObjectLiteral::Property::COMPUTED:
1385 if (key->handle()->IsSymbol()) { 1371 if (key->handle()->IsSymbol()) {
1386 if (property->emit_store()) { 1372 if (property->emit_store()) {
1387 VisitForAccumulatorValue(value); 1373 VisitForAccumulatorValue(value);
1388 __ mov(ecx, Immediate(key->handle())); 1374 __ mov(ecx, Immediate(key->handle()));
1389 __ mov(edx, Operand(esp, 0)); 1375 __ mov(edx, Operand(esp, 0));
1390 Handle<Code> ic(isolate()->builtins()->builtin( 1376 Handle<Code> ic(isolate()->builtins()->builtin(
1391 Builtins::StoreIC_Initialize)); 1377 is_strict() ? Builtins::StoreIC_Initialize_Strict
1378 : Builtins::StoreIC_Initialize));
1392 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1379 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1393 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1380 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1394 } else { 1381 } else {
1395 VisitForEffect(value); 1382 VisitForEffect(value);
1396 } 1383 }
1397 break; 1384 break;
1398 } 1385 }
1399 // Fall through. 1386 // Fall through.
1400 case ObjectLiteral::Property::PROTOTYPE: 1387 case ObjectLiteral::Property::PROTOTYPE:
1401 __ push(Operand(esp, 0)); // Duplicate receiver. 1388 __ push(Operand(esp, 0)); // Duplicate receiver.
1402 VisitForStackValue(key); 1389 VisitForStackValue(key);
1403 VisitForStackValue(value); 1390 VisitForStackValue(value);
1404 if (property->emit_store()) { 1391 if (property->emit_store()) {
1405 __ CallRuntime(Runtime::kSetProperty, 3); 1392 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes
1393 __ CallRuntime(Runtime::kSetProperty, 4);
1406 } else { 1394 } else {
1407 __ Drop(3); 1395 __ Drop(3);
1408 } 1396 }
1409 break; 1397 break;
1410 case ObjectLiteral::Property::SETTER: 1398 case ObjectLiteral::Property::SETTER:
1411 case ObjectLiteral::Property::GETTER: 1399 case ObjectLiteral::Property::GETTER:
1412 __ push(Operand(esp, 0)); // Duplicate receiver. 1400 __ push(Operand(esp, 0)); // Duplicate receiver.
1413 VisitForStackValue(key); 1401 VisitForStackValue(key);
1414 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? 1402 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
1415 Smi::FromInt(1) : 1403 Smi::FromInt(1) :
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1574 } 1562 }
1575 } 1563 }
1576 1564
1577 // For property compound assignments we need another deoptimization 1565 // For property compound assignments we need another deoptimization
1578 // point after the property load. 1566 // point after the property load.
1579 if (property != NULL) { 1567 if (property != NULL) {
1580 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); 1568 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
1581 } 1569 }
1582 1570
1583 Token::Value op = expr->binary_op(); 1571 Token::Value op = expr->binary_op();
1584 ConstantOperand constant = ShouldInlineSmiCase(op) 1572 __ push(eax); // Left operand goes on the stack.
1585 ? GetConstantOperand(op, expr->target(), expr->value()) 1573 VisitForAccumulatorValue(expr->value());
1586 : kNoConstants;
1587 ASSERT(constant == kRightConstant || constant == kNoConstants);
1588 if (constant == kNoConstants) {
1589 __ push(eax); // Left operand goes on the stack.
1590 VisitForAccumulatorValue(expr->value());
1591 }
1592 1574
1593 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1575 OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1594 ? OVERWRITE_RIGHT 1576 ? OVERWRITE_RIGHT
1595 : NO_OVERWRITE; 1577 : NO_OVERWRITE;
1596 SetSourcePosition(expr->position() + 1); 1578 SetSourcePosition(expr->position() + 1);
1597 AccumulatorValueContext context(this); 1579 AccumulatorValueContext context(this);
1598 if (ShouldInlineSmiCase(op)) { 1580 if (ShouldInlineSmiCase(op)) {
1599 EmitInlineSmiBinaryOp(expr, 1581 EmitInlineSmiBinaryOp(expr,
1600 op, 1582 op,
1601 mode, 1583 mode,
1602 expr->target(), 1584 expr->target(),
1603 expr->value(), 1585 expr->value());
1604 constant);
1605 } else { 1586 } else {
1606 EmitBinaryOp(op, mode); 1587 EmitBinaryOp(op, mode);
1607 } 1588 }
1608 1589
1609 // Deoptimization point in case the binary operation may have side effects. 1590 // Deoptimization point in case the binary operation may have side effects.
1610 PrepareForBailout(expr->binary_operation(), TOS_REG); 1591 PrepareForBailout(expr->binary_operation(), TOS_REG);
1611 } else { 1592 } else {
1612 VisitForAccumulatorValue(expr->value()); 1593 VisitForAccumulatorValue(expr->value());
1613 } 1594 }
1614 1595
(...skipping 29 matching lines...) Expand all
1644 1625
1645 1626
1646 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1627 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1647 SetSourcePosition(prop->position()); 1628 SetSourcePosition(prop->position());
1648 Handle<Code> ic(isolate()->builtins()->builtin( 1629 Handle<Code> ic(isolate()->builtins()->builtin(
1649 Builtins::KeyedLoadIC_Initialize)); 1630 Builtins::KeyedLoadIC_Initialize));
1650 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1631 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1651 } 1632 }
1652 1633
1653 1634
1654 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr,
1655 OverwriteMode mode,
1656 bool left_is_constant_smi,
1657 Smi* value) {
1658 NearLabel call_stub, done;
1659 __ add(Operand(eax), Immediate(value));
1660 __ j(overflow, &call_stub);
1661 JumpPatchSite patch_site(masm_);
1662 patch_site.EmitJumpIfSmi(eax, &done);
1663
1664 // Undo the optimistic add operation and call the shared stub.
1665 __ bind(&call_stub);
1666 __ sub(Operand(eax), Immediate(value));
1667 Token::Value op = Token::ADD;
1668 TypeRecordingBinaryOpStub stub(op, mode);
1669 if (left_is_constant_smi) {
1670 __ mov(edx, Immediate(value));
1671 } else {
1672 __ mov(edx, eax);
1673 __ mov(eax, Immediate(value));
1674 }
1675 EmitCallIC(stub.GetCode(), &patch_site);
1676
1677 __ bind(&done);
1678 context()->Plug(eax);
1679 }
1680
1681
1682 void FullCodeGenerator::EmitConstantSmiSub(Expression* expr,
1683 OverwriteMode mode,
1684 bool left_is_constant_smi,
1685 Smi* value) {
1686 NearLabel call_stub, done;
1687 if (left_is_constant_smi) {
1688 __ mov(ecx, eax);
1689 __ mov(eax, Immediate(value));
1690 __ sub(Operand(eax), ecx);
1691 } else {
1692 __ sub(Operand(eax), Immediate(value));
1693 }
1694 __ j(overflow, &call_stub);
1695 JumpPatchSite patch_site(masm_);
1696 patch_site.EmitJumpIfSmi(eax, &done);
1697
1698 __ bind(&call_stub);
1699 if (left_is_constant_smi) {
1700 __ mov(edx, Immediate(value));
1701 __ mov(eax, ecx);
1702 } else {
1703 __ add(Operand(eax), Immediate(value)); // Undo the subtraction.
1704 __ mov(edx, eax);
1705 __ mov(eax, Immediate(value));
1706 }
1707 Token::Value op = Token::SUB;
1708 TypeRecordingBinaryOpStub stub(op, mode);
1709 EmitCallIC(stub.GetCode(), &patch_site);
1710
1711 __ bind(&done);
1712 context()->Plug(eax);
1713 }
1714
1715
1716 void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr,
1717 Token::Value op,
1718 OverwriteMode mode,
1719 Smi* value) {
1720 NearLabel call_stub, smi_case, done;
1721 int shift_value = value->value() & 0x1f;
1722
1723 JumpPatchSite patch_site(masm_);
1724 patch_site.EmitJumpIfSmi(eax, &smi_case);
1725
1726 // Call stub.
1727 __ bind(&call_stub);
1728 __ mov(edx, eax);
1729 __ mov(eax, Immediate(value));
1730 TypeRecordingBinaryOpStub stub(op, mode);
1731 EmitCallIC(stub.GetCode(), &patch_site);
1732 __ jmp(&done);
1733
1734 // Smi case.
1735 __ bind(&smi_case);
1736 switch (op) {
1737 case Token::SHL:
1738 if (shift_value != 0) {
1739 __ mov(edx, eax);
1740 if (shift_value > 1) {
1741 __ shl(edx, shift_value - 1);
1742 }
1743 // Convert int result to smi, checking that it is in int range.
1744 ASSERT(kSmiTagSize == 1); // Adjust code if not the case.
1745 __ add(edx, Operand(edx));
1746 __ j(overflow, &call_stub);
1747 __ mov(eax, edx); // Put result back into eax.
1748 }
1749 break;
1750 case Token::SAR:
1751 if (shift_value != 0) {
1752 __ sar(eax, shift_value);
1753 __ and_(eax, ~kSmiTagMask);
1754 }
1755 break;
1756 case Token::SHR:
1757 if (shift_value < 2) {
1758 __ mov(edx, eax);
1759 __ SmiUntag(edx);
1760 __ shr(edx, shift_value);
1761 __ test(edx, Immediate(0xc0000000));
1762 __ j(not_zero, &call_stub);
1763 __ SmiTag(edx);
1764 __ mov(eax, edx); // Put result back into eax.
1765 } else {
1766 __ SmiUntag(eax);
1767 __ shr(eax, shift_value);
1768 __ SmiTag(eax);
1769 }
1770 break;
1771 default:
1772 UNREACHABLE();
1773 }
1774
1775 __ bind(&done);
1776 context()->Plug(eax);
1777 }
1778
1779
1780 void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr,
1781 Token::Value op,
1782 OverwriteMode mode,
1783 Smi* value) {
1784 NearLabel smi_case, done;
1785
1786 JumpPatchSite patch_site(masm_);
1787 patch_site.EmitJumpIfSmi(eax, &smi_case);
1788
1789 // The order of the arguments does not matter for bit-ops with a
1790 // constant operand.
1791 __ mov(edx, Immediate(value));
1792 TypeRecordingBinaryOpStub stub(op, mode);
1793 EmitCallIC(stub.GetCode(), &patch_site);
1794 __ jmp(&done);
1795
1796 // Smi case.
1797 __ bind(&smi_case);
1798 switch (op) {
1799 case Token::BIT_OR:
1800 __ or_(Operand(eax), Immediate(value));
1801 break;
1802 case Token::BIT_XOR:
1803 __ xor_(Operand(eax), Immediate(value));
1804 break;
1805 case Token::BIT_AND:
1806 __ and_(Operand(eax), Immediate(value));
1807 break;
1808 default:
1809 UNREACHABLE();
1810 }
1811
1812 __ bind(&done);
1813 context()->Plug(eax);
1814 }
1815
1816
1817 void FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr,
1818 Token::Value op,
1819 OverwriteMode mode,
1820 bool left_is_constant_smi,
1821 Smi* value) {
1822 switch (op) {
1823 case Token::BIT_OR:
1824 case Token::BIT_XOR:
1825 case Token::BIT_AND:
1826 EmitConstantSmiBitOp(expr, op, mode, value);
1827 break;
1828 case Token::SHL:
1829 case Token::SAR:
1830 case Token::SHR:
1831 ASSERT(!left_is_constant_smi);
1832 EmitConstantSmiShiftOp(expr, op, mode, value);
1833 break;
1834 case Token::ADD:
1835 EmitConstantSmiAdd(expr, mode, left_is_constant_smi, value);
1836 break;
1837 case Token::SUB:
1838 EmitConstantSmiSub(expr, mode, left_is_constant_smi, value);
1839 break;
1840 default:
1841 UNREACHABLE();
1842 }
1843 }
1844
1845
1846 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, 1635 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
1847 Token::Value op, 1636 Token::Value op,
1848 OverwriteMode mode, 1637 OverwriteMode mode,
1849 Expression* left, 1638 Expression* left,
1850 Expression* right, 1639 Expression* right) {
1851 ConstantOperand constant) {
1852 if (constant == kRightConstant) {
1853 Smi* value = Smi::cast(*right->AsLiteral()->handle());
1854 EmitConstantSmiBinaryOp(expr, op, mode, false, value);
1855 return;
1856 } else if (constant == kLeftConstant) {
1857 Smi* value = Smi::cast(*left->AsLiteral()->handle());
1858 EmitConstantSmiBinaryOp(expr, op, mode, true, value);
1859 return;
1860 }
1861
1862 // Do combined smi check of the operands. Left operand is on the 1640 // Do combined smi check of the operands. Left operand is on the
1863 // stack. Right operand is in eax. 1641 // stack. Right operand is in eax.
1864 NearLabel done, smi_case, stub_call; 1642 NearLabel done, smi_case, stub_call;
1865 __ pop(edx); 1643 __ pop(edx);
1866 __ mov(ecx, eax); 1644 __ mov(ecx, eax);
1867 __ or_(eax, Operand(edx)); 1645 __ or_(eax, Operand(edx));
1868 JumpPatchSite patch_site(masm_); 1646 JumpPatchSite patch_site(masm_);
1869 patch_site.EmitJumpIfSmi(eax, &smi_case); 1647 patch_site.EmitJumpIfSmi(eax, &smi_case);
1870 1648
1871 __ bind(&stub_call); 1649 __ bind(&stub_call);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1984 EmitVariableAssignment(var, Token::ASSIGN); 1762 EmitVariableAssignment(var, Token::ASSIGN);
1985 break; 1763 break;
1986 } 1764 }
1987 case NAMED_PROPERTY: { 1765 case NAMED_PROPERTY: {
1988 __ push(eax); // Preserve value. 1766 __ push(eax); // Preserve value.
1989 VisitForAccumulatorValue(prop->obj()); 1767 VisitForAccumulatorValue(prop->obj());
1990 __ mov(edx, eax); 1768 __ mov(edx, eax);
1991 __ pop(eax); // Restore value. 1769 __ pop(eax); // Restore value.
1992 __ mov(ecx, prop->key()->AsLiteral()->handle()); 1770 __ mov(ecx, prop->key()->AsLiteral()->handle());
1993 Handle<Code> ic(isolate()->builtins()->builtin( 1771 Handle<Code> ic(isolate()->builtins()->builtin(
1994 Builtins::StoreIC_Initialize)); 1772 is_strict() ? Builtins::StoreIC_Initialize_Strict
1773 : Builtins::StoreIC_Initialize));
1995 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1774 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1996 break; 1775 break;
1997 } 1776 }
1998 case KEYED_PROPERTY: { 1777 case KEYED_PROPERTY: {
1999 __ push(eax); // Preserve value. 1778 __ push(eax); // Preserve value.
2000 VisitForStackValue(prop->obj()); 1779 if (prop->is_synthetic()) {
2001 VisitForAccumulatorValue(prop->key()); 1780 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2002 __ mov(ecx, eax); 1781 ASSERT(prop->key()->AsLiteral() != NULL);
2003 __ pop(edx); 1782 { AccumulatorValueContext for_object(this);
1783 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1784 }
1785 __ mov(edx, eax);
1786 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
1787 } else {
1788 VisitForStackValue(prop->obj());
1789 VisitForAccumulatorValue(prop->key());
1790 __ mov(ecx, eax);
1791 __ pop(edx);
1792 }
2004 __ pop(eax); // Restore value. 1793 __ pop(eax); // Restore value.
2005 Handle<Code> ic(isolate()->builtins()->builtin( 1794 Handle<Code> ic(isolate()->builtins()->builtin(
2006 Builtins::KeyedStoreIC_Initialize)); 1795 is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
1796 : Builtins::KeyedStoreIC_Initialize));
2007 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1797 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2008 break; 1798 break;
2009 } 1799 }
2010 } 1800 }
2011 PrepareForBailoutForId(bailout_ast_id, TOS_REG); 1801 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
2012 context()->Plug(eax); 1802 context()->Plug(eax);
2013 } 1803 }
2014 1804
2015 1805
2016 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1806 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2017 Token::Value op) { 1807 Token::Value op) {
2018 // Left-hand sides that rewrite to explicit property accesses do not reach 1808 // Left-hand sides that rewrite to explicit property accesses do not reach
2019 // here. 1809 // here.
2020 ASSERT(var != NULL); 1810 ASSERT(var != NULL);
2021 ASSERT(var->is_global() || var->AsSlot() != NULL); 1811 ASSERT(var->is_global() || var->AsSlot() != NULL);
2022 1812
2023 if (var->is_global()) { 1813 if (var->is_global()) {
2024 ASSERT(!var->is_this()); 1814 ASSERT(!var->is_this());
2025 // Assignment to a global variable. Use inline caching for the 1815 // Assignment to a global variable. Use inline caching for the
2026 // assignment. Right-hand-side value is passed in eax, variable name in 1816 // assignment. Right-hand-side value is passed in eax, variable name in
2027 // ecx, and the global object on the stack. 1817 // ecx, and the global object on the stack.
2028 __ mov(ecx, var->name()); 1818 __ mov(ecx, var->name());
2029 __ mov(edx, GlobalObjectOperand()); 1819 __ mov(edx, GlobalObjectOperand());
2030 Handle<Code> ic(isolate()->builtins()->builtin( 1820 Handle<Code> ic(isolate()->builtins()->builtin(
2031 Builtins::StoreIC_Initialize)); 1821 is_strict() ? Builtins::StoreIC_Initialize_Strict
2032 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1822 : Builtins::StoreIC_Initialize));
1823 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
2033 1824
2034 } else if (op == Token::INIT_CONST) { 1825 } else if (op == Token::INIT_CONST) {
2035 // Like var declarations, const declarations are hoisted to function 1826 // Like var declarations, const declarations are hoisted to function
2036 // scope. However, unlike var initializers, const initializers are able 1827 // scope. However, unlike var initializers, const initializers are able
2037 // to drill a hole to that function context, even from inside a 'with' 1828 // to drill a hole to that function context, even from inside a 'with'
2038 // context. We thus bypass the normal static scope lookup. 1829 // context. We thus bypass the normal static scope lookup.
2039 Slot* slot = var->AsSlot(); 1830 Slot* slot = var->AsSlot();
2040 Label skip; 1831 Label skip;
2041 switch (slot->type()) { 1832 switch (slot->type()) {
2042 case Slot::PARAMETER: 1833 case Slot::PARAMETER:
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2090 int offset = Context::SlotOffset(slot->index()); 1881 int offset = Context::SlotOffset(slot->index());
2091 __ RecordWrite(ecx, offset, edx, ebx); 1882 __ RecordWrite(ecx, offset, edx, ebx);
2092 break; 1883 break;
2093 } 1884 }
2094 1885
2095 case Slot::LOOKUP: 1886 case Slot::LOOKUP:
2096 // Call the runtime for the assignment. 1887 // Call the runtime for the assignment.
2097 __ push(eax); // Value. 1888 __ push(eax); // Value.
2098 __ push(esi); // Context. 1889 __ push(esi); // Context.
2099 __ push(Immediate(var->name())); 1890 __ push(Immediate(var->name()));
2100 __ CallRuntime(Runtime::kStoreContextSlot, 3); 1891 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
1892 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2101 break; 1893 break;
2102 } 1894 }
2103 } 1895 }
2104 } 1896 }
2105 1897
2106 1898
2107 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1899 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2108 // Assignment to a property, using a named store IC. 1900 // Assignment to a property, using a named store IC.
2109 Property* prop = expr->target()->AsProperty(); 1901 Property* prop = expr->target()->AsProperty();
2110 ASSERT(prop != NULL); 1902 ASSERT(prop != NULL);
(...skipping 11 matching lines...) Expand all
2122 1914
2123 // Record source code position before IC call. 1915 // Record source code position before IC call.
2124 SetSourcePosition(expr->position()); 1916 SetSourcePosition(expr->position());
2125 __ mov(ecx, prop->key()->AsLiteral()->handle()); 1917 __ mov(ecx, prop->key()->AsLiteral()->handle());
2126 if (expr->ends_initialization_block()) { 1918 if (expr->ends_initialization_block()) {
2127 __ mov(edx, Operand(esp, 0)); 1919 __ mov(edx, Operand(esp, 0));
2128 } else { 1920 } else {
2129 __ pop(edx); 1921 __ pop(edx);
2130 } 1922 }
2131 Handle<Code> ic(isolate()->builtins()->builtin( 1923 Handle<Code> ic(isolate()->builtins()->builtin(
2132 Builtins::StoreIC_Initialize)); 1924 is_strict() ? Builtins::StoreIC_Initialize_Strict
1925 : Builtins::StoreIC_Initialize));
2133 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1926 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2134 1927
2135 // If the assignment ends an initialization block, revert to fast case. 1928 // If the assignment ends an initialization block, revert to fast case.
2136 if (expr->ends_initialization_block()) { 1929 if (expr->ends_initialization_block()) {
2137 __ push(eax); // Result of assignment, saved even if not needed. 1930 __ push(eax); // Result of assignment, saved even if not needed.
2138 __ push(Operand(esp, kPointerSize)); // Receiver is under value. 1931 __ push(Operand(esp, kPointerSize)); // Receiver is under value.
2139 __ CallRuntime(Runtime::kToFastProperties, 1); 1932 __ CallRuntime(Runtime::kToFastProperties, 1);
2140 __ pop(eax); 1933 __ pop(eax);
2141 __ Drop(1); 1934 __ Drop(1);
2142 } 1935 }
(...skipping 18 matching lines...) Expand all
2161 1954
2162 __ pop(ecx); 1955 __ pop(ecx);
2163 if (expr->ends_initialization_block()) { 1956 if (expr->ends_initialization_block()) {
2164 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. 1957 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later.
2165 } else { 1958 } else {
2166 __ pop(edx); 1959 __ pop(edx);
2167 } 1960 }
2168 // Record source code position before IC call. 1961 // Record source code position before IC call.
2169 SetSourcePosition(expr->position()); 1962 SetSourcePosition(expr->position());
2170 Handle<Code> ic(isolate()->builtins()->builtin( 1963 Handle<Code> ic(isolate()->builtins()->builtin(
2171 Builtins::KeyedStoreIC_Initialize)); 1964 is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
1965 : Builtins::KeyedStoreIC_Initialize));
2172 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1966 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2173 1967
2174 // If the assignment ends an initialization block, revert to fast case. 1968 // If the assignment ends an initialization block, revert to fast case.
2175 if (expr->ends_initialization_block()) { 1969 if (expr->ends_initialization_block()) {
2176 __ pop(edx); 1970 __ pop(edx);
2177 __ push(eax); // Result of assignment, saved even if not needed. 1971 __ push(eax); // Result of assignment, saved even if not needed.
2178 __ push(edx); 1972 __ push(edx);
2179 __ CallRuntime(Runtime::kToFastProperties, 1); 1973 __ CallRuntime(Runtime::kToFastProperties, 1);
2180 __ pop(eax); 1974 __ pop(eax);
2181 } 1975 }
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
2276 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2070 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2277 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 2071 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
2278 __ CallStub(&stub); 2072 __ CallStub(&stub);
2279 RecordJSReturnSite(expr); 2073 RecordJSReturnSite(expr);
2280 // Restore context register. 2074 // Restore context register.
2281 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2075 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2282 context()->DropAndPlug(1, eax); 2076 context()->DropAndPlug(1, eax);
2283 } 2077 }
2284 2078
2285 2079
2080 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
2081 int arg_count) {
2082 // Push copy of the first argument or undefined if it doesn't exist.
2083 if (arg_count > 0) {
2084 __ push(Operand(esp, arg_count * kPointerSize));
2085 } else {
2086 __ push(Immediate(FACTORY->undefined_value()));
2087 }
2088
2089 // Push the receiver of the enclosing function.
2090 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
2091
2092 // Push the strict mode flag.
2093 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
2094
2095 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
2096 ? Runtime::kResolvePossiblyDirectEvalNoLookup
2097 : Runtime::kResolvePossiblyDirectEval, 4);
2098 }
2099
2100
2286 void FullCodeGenerator::VisitCall(Call* expr) { 2101 void FullCodeGenerator::VisitCall(Call* expr) {
2287 #ifdef DEBUG 2102 #ifdef DEBUG
2288 // We want to verify that RecordJSReturnSite gets called on all paths 2103 // We want to verify that RecordJSReturnSite gets called on all paths
2289 // through this function. Avoid early returns. 2104 // through this function. Avoid early returns.
2290 expr->return_is_recorded_ = false; 2105 expr->return_is_recorded_ = false;
2291 #endif 2106 #endif
2292 2107
2293 Comment cmnt(masm_, "[ Call"); 2108 Comment cmnt(masm_, "[ Call");
2294 Expression* fun = expr->expression(); 2109 Expression* fun = expr->expression();
2295 Variable* var = fun->AsVariableProxy()->AsVariable(); 2110 Variable* var = fun->AsVariableProxy()->AsVariable();
2296 2111
2297 if (var != NULL && var->is_possibly_eval()) { 2112 if (var != NULL && var->is_possibly_eval()) {
2298 // In a call to eval, we first call %ResolvePossiblyDirectEval to 2113 // In a call to eval, we first call %ResolvePossiblyDirectEval to
2299 // resolve the function we need to call and the receiver of the 2114 // resolve the function we need to call and the receiver of the
2300 // call. Then we call the resolved function using the given 2115 // call. Then we call the resolved function using the given
2301 // arguments. 2116 // arguments.
2302 ZoneList<Expression*>* args = expr->arguments(); 2117 ZoneList<Expression*>* args = expr->arguments();
2303 int arg_count = args->length(); 2118 int arg_count = args->length();
2304 { PreservePositionScope pos_scope(masm()->positions_recorder()); 2119 { PreservePositionScope pos_scope(masm()->positions_recorder());
2305 VisitForStackValue(fun); 2120 VisitForStackValue(fun);
2306 // Reserved receiver slot. 2121 // Reserved receiver slot.
2307 __ push(Immediate(isolate()->factory()->undefined_value())); 2122 __ push(Immediate(isolate()->factory()->undefined_value()));
2308 2123
2309 // Push the arguments. 2124 // Push the arguments.
2310 for (int i = 0; i < arg_count; i++) { 2125 for (int i = 0; i < arg_count; i++) {
2311 VisitForStackValue(args->at(i)); 2126 VisitForStackValue(args->at(i));
2312 } 2127 }
2313 2128
2314 // Push copy of the function - found below the arguments. 2129 // If we know that eval can only be shadowed by eval-introduced
2315 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); 2130 // variables we attempt to load the global eval function directly
2316 2131 // in generated code. If we succeed, there is no need to perform a
2317 // Push copy of the first argument or undefined if it doesn't exist. 2132 // context lookup in the runtime system.
2318 if (arg_count > 0) { 2133 Label done;
2319 __ push(Operand(esp, arg_count * kPointerSize)); 2134 if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
2320 } else { 2135 Label slow;
2321 __ push(Immediate(isolate()->factory()->undefined_value())); 2136 EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
2137 NOT_INSIDE_TYPEOF,
2138 &slow);
2139 // Push the function and resolve eval.
2140 __ push(eax);
2141 EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
2142 __ jmp(&done);
2143 __ bind(&slow);
2322 } 2144 }
2323 2145
2324 // Push the receiver of the enclosing function and do runtime call. 2146 // Push copy of the function (found below the arguments) and
2325 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); 2147 // resolve eval.
2326 // Push the strict mode flag. 2148 __ push(Operand(esp, (arg_count + 1) * kPointerSize));
2327 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); 2149 EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
2328 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4); 2150 if (done.is_linked()) {
2151 __ bind(&done);
2152 }
2329 2153
2330 // The runtime call returns a pair of values in eax (function) and 2154 // The runtime call returns a pair of values in eax (function) and
2331 // edx (receiver). Touch up the stack with the right values. 2155 // edx (receiver). Touch up the stack with the right values.
2332 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); 2156 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
2333 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); 2157 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
2334 } 2158 }
2335 // Record source position for debugger. 2159 // Record source position for debugger.
2336 SetSourcePosition(expr->position()); 2160 SetSourcePosition(expr->position());
2337 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2161 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2338 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 2162 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2383 __ bind(&call); 2207 __ bind(&call);
2384 } 2208 }
2385 2209
2386 EmitCallWithStub(expr); 2210 EmitCallWithStub(expr);
2387 } else if (fun->AsProperty() != NULL) { 2211 } else if (fun->AsProperty() != NULL) {
2388 // Call to an object property. 2212 // Call to an object property.
2389 Property* prop = fun->AsProperty(); 2213 Property* prop = fun->AsProperty();
2390 Literal* key = prop->key()->AsLiteral(); 2214 Literal* key = prop->key()->AsLiteral();
2391 if (key != NULL && key->handle()->IsSymbol()) { 2215 if (key != NULL && key->handle()->IsSymbol()) {
2392 // Call to a named property, use call IC. 2216 // Call to a named property, use call IC.
2393 VisitForStackValue(prop->obj()); 2217 { PreservePositionScope scope(masm()->positions_recorder());
2218 VisitForStackValue(prop->obj());
2219 }
2394 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2220 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2395 } else { 2221 } else {
2396 // Call to a keyed property. 2222 // Call to a keyed property.
2397 // For a synthetic property use keyed load IC followed by function call, 2223 // For a synthetic property use keyed load IC followed by function call,
2398 // for a regular property use keyed EmitCallIC. 2224 // for a regular property use keyed EmitCallIC.
2399 if (prop->is_synthetic()) { 2225 if (prop->is_synthetic()) {
2400 // Do not visit the object and key subexpressions (they are shared 2226 // Do not visit the object and key subexpressions (they are shared
2401 // by all occurrences of the same rewritten parameter). 2227 // by all occurrences of the same rewritten parameter).
2402 ASSERT(prop->obj()->AsVariableProxy() != NULL); 2228 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2403 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); 2229 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
(...skipping 993 matching lines...) Expand 10 before | Expand all | Expand 10 after
3397 Immediate(String::kContainsCachedArrayIndexMask)); 3223 Immediate(String::kContainsCachedArrayIndexMask));
3398 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3224 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3399 Split(zero, if_true, if_false, fall_through); 3225 Split(zero, if_true, if_false, fall_through);
3400 3226
3401 context()->Plug(if_true, if_false); 3227 context()->Plug(if_true, if_false);
3402 } 3228 }
3403 3229
3404 3230
3405 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 3231 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
3406 ASSERT(args->length() == 1); 3232 ASSERT(args->length() == 1);
3407
3408 VisitForAccumulatorValue(args->at(0)); 3233 VisitForAccumulatorValue(args->at(0));
3409 3234
3410 if (FLAG_debug_code) { 3235 if (FLAG_debug_code) {
3411 __ AbortIfNotString(eax); 3236 __ AbortIfNotString(eax);
3412 } 3237 }
3413 3238
3414 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); 3239 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
3415 __ IndexFromHash(eax, eax); 3240 __ IndexFromHash(eax, eax);
3416 3241
3417 context()->Plug(eax); 3242 context()->Plug(eax);
3418 } 3243 }
3419 3244
3420 3245
3421 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 3246 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
3422 Label bailout, done, one_char_separator, long_separator, 3247 Label bailout, done, one_char_separator, long_separator,
3423 non_trivial_array, not_size_one_array, loop, loop_condition, 3248 non_trivial_array, not_size_one_array, loop,
3424 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; 3249 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3425 3250
3426 ASSERT(args->length() == 2); 3251 ASSERT(args->length() == 2);
3427 // We will leave the separator on the stack until the end of the function. 3252 // We will leave the separator on the stack until the end of the function.
3428 VisitForStackValue(args->at(1)); 3253 VisitForStackValue(args->at(1));
3429 // Load this to eax (= array) 3254 // Load this to eax (= array)
3430 VisitForAccumulatorValue(args->at(0)); 3255 VisitForAccumulatorValue(args->at(0));
3431 // All aliases of the same register have disjoint lifetimes. 3256 // All aliases of the same register have disjoint lifetimes.
3432 Register array = eax; 3257 Register array = eax;
3433 Register elements = no_reg; // Will be eax. 3258 Register elements = no_reg; // Will be eax.
(...skipping 21 matching lines...) Expand all
3455 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 3280 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3456 __ j(not_equal, &bailout); 3281 __ j(not_equal, &bailout);
3457 3282
3458 // Check that the array has fast elements. 3283 // Check that the array has fast elements.
3459 __ test_b(FieldOperand(scratch, Map::kBitField2Offset), 3284 __ test_b(FieldOperand(scratch, Map::kBitField2Offset),
3460 1 << Map::kHasFastElements); 3285 1 << Map::kHasFastElements);
3461 __ j(zero, &bailout); 3286 __ j(zero, &bailout);
3462 3287
3463 // If the array has length zero, return the empty string. 3288 // If the array has length zero, return the empty string.
3464 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset)); 3289 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
3465 __ sar(array_length, 1); 3290 __ SmiUntag(array_length);
3466 __ j(not_zero, &non_trivial_array); 3291 __ j(not_zero, &non_trivial_array);
3467 __ mov(result_operand, FACTORY->empty_string()); 3292 __ mov(result_operand, FACTORY->empty_string());
3468 __ jmp(&done); 3293 __ jmp(&done);
3469 3294
3470 // Save the array length. 3295 // Save the array length.
3471 __ bind(&non_trivial_array); 3296 __ bind(&non_trivial_array);
3472 __ mov(array_length_operand, array_length); 3297 __ mov(array_length_operand, array_length);
3473 3298
3474 // Save the FixedArray containing array's elements. 3299 // Save the FixedArray containing array's elements.
3475 // End of array's live range. 3300 // End of array's live range.
3476 elements = array; 3301 elements = array;
3477 __ mov(elements, FieldOperand(array, JSArray::kElementsOffset)); 3302 __ mov(elements, FieldOperand(array, JSArray::kElementsOffset));
3478 array = no_reg; 3303 array = no_reg;
3479 3304
3480 3305
3481 // Check that all array elements are sequential ASCII strings, and 3306 // Check that all array elements are sequential ASCII strings, and
3482 // accumulate the sum of their lengths, as a smi-encoded value. 3307 // accumulate the sum of their lengths, as a smi-encoded value.
3483 __ Set(index, Immediate(0)); 3308 __ Set(index, Immediate(0));
3484 __ Set(string_length, Immediate(0)); 3309 __ Set(string_length, Immediate(0));
3485 // Loop condition: while (index < length). 3310 // Loop condition: while (index < length).
3486 // Live loop registers: index, array_length, string, 3311 // Live loop registers: index, array_length, string,
3487 // scratch, string_length, elements. 3312 // scratch, string_length, elements.
3488 __ jmp(&loop_condition); 3313 if (FLAG_debug_code) {
3314 __ cmp(index, Operand(array_length));
3315 __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin");
3316 }
3489 __ bind(&loop); 3317 __ bind(&loop);
3490 __ cmp(index, Operand(array_length)); 3318 __ mov(string, FieldOperand(elements,
3491 __ j(greater_equal, &done); 3319 index,
3492 3320 times_pointer_size,
3493 __ mov(string, FieldOperand(elements, index, 3321 FixedArray::kHeaderSize));
3494 times_pointer_size,
3495 FixedArray::kHeaderSize));
3496 __ test(string, Immediate(kSmiTagMask)); 3322 __ test(string, Immediate(kSmiTagMask));
3497 __ j(zero, &bailout); 3323 __ j(zero, &bailout);
3498 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); 3324 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3499 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3325 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3500 __ and_(scratch, Immediate( 3326 __ and_(scratch, Immediate(
3501 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3327 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3502 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 3328 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
3503 __ j(not_equal, &bailout); 3329 __ j(not_equal, &bailout);
3504 __ add(string_length, 3330 __ add(string_length,
3505 FieldOperand(string, SeqAsciiString::kLengthOffset)); 3331 FieldOperand(string, SeqAsciiString::kLengthOffset));
3506 __ j(overflow, &bailout); 3332 __ j(overflow, &bailout);
3507 __ add(Operand(index), Immediate(1)); 3333 __ add(Operand(index), Immediate(1));
3508 __ bind(&loop_condition);
3509 __ cmp(index, Operand(array_length)); 3334 __ cmp(index, Operand(array_length));
3510 __ j(less, &loop); 3335 __ j(less, &loop);
3511 3336
3512 // If array_length is 1, return elements[0], a string. 3337 // If array_length is 1, return elements[0], a string.
3513 __ cmp(array_length, 1); 3338 __ cmp(array_length, 1);
3514 __ j(not_equal, &not_size_one_array); 3339 __ j(not_equal, &not_size_one_array);
3515 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize)); 3340 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize));
3516 __ mov(result_operand, scratch); 3341 __ mov(result_operand, scratch);
3517 __ jmp(&done); 3342 __ jmp(&done);
3518 3343
3519 __ bind(&not_size_one_array); 3344 __ bind(&not_size_one_array);
3520 3345
3521 // End of array_length live range. 3346 // End of array_length live range.
3522 result_pos = array_length; 3347 result_pos = array_length;
3523 array_length = no_reg; 3348 array_length = no_reg;
3524 3349
3525 // Live registers: 3350 // Live registers:
3526 // string_length: Sum of string lengths, as a smi. 3351 // string_length: Sum of string lengths, as a smi.
3527 // elements: FixedArray of strings. 3352 // elements: FixedArray of strings.
3528 3353
3529 // Check that the separator is a flat ASCII string. 3354 // Check that the separator is a flat ASCII string.
3530 __ mov(string, separator_operand); 3355 __ mov(string, separator_operand);
3531 __ test(string, Immediate(kSmiTagMask)); 3356 __ test(string, Immediate(kSmiTagMask));
3532 __ j(zero, &bailout); 3357 __ j(zero, &bailout);
3533 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); 3358 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3534 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3359 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3535 __ and_(scratch, Immediate( 3360 __ and_(scratch, Immediate(
3536 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3361 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3537 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 3362 __ cmp(scratch, ASCII_STRING_TYPE);
3538 __ j(not_equal, &bailout); 3363 __ j(not_equal, &bailout);
3539 3364
3540 // Add (separator length times array_length) - separator length 3365 // Add (separator length times array_length) - separator length
3541 // to string_length. 3366 // to string_length.
3542 __ mov(scratch, separator_operand); 3367 __ mov(scratch, separator_operand);
3543 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset)); 3368 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset));
3544 __ sub(string_length, Operand(scratch)); // May be negative, temporarily. 3369 __ sub(string_length, Operand(scratch)); // May be negative, temporarily.
3545 __ imul(scratch, array_length_operand); 3370 __ imul(scratch, array_length_operand);
3546 __ j(overflow, &bailout); 3371 __ j(overflow, &bailout);
3547 __ add(string_length, Operand(scratch)); 3372 __ add(string_length, Operand(scratch));
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
3725 context()->Plug(eax); 3550 context()->Plug(eax);
3726 } 3551 }
3727 3552
3728 3553
3729 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 3554 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
3730 switch (expr->op()) { 3555 switch (expr->op()) {
3731 case Token::DELETE: { 3556 case Token::DELETE: {
3732 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 3557 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
3733 Property* prop = expr->expression()->AsProperty(); 3558 Property* prop = expr->expression()->AsProperty();
3734 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 3559 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
3735 if (prop == NULL && var == NULL) { 3560
3561 if (prop != NULL) {
3562 if (prop->is_synthetic()) {
3563 // Result of deleting parameters is false, even when they rewrite
3564 // to accesses on the arguments object.
3565 context()->Plug(false);
3566 } else {
3567 VisitForStackValue(prop->obj());
3568 VisitForStackValue(prop->key());
3569 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
3570 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3571 context()->Plug(eax);
3572 }
3573 } else if (var != NULL) {
3574 // Delete of an unqualified identifier is disallowed in strict mode
3575 // but "delete this" is.
3576 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
3577 if (var->is_global()) {
3578 __ push(GlobalObjectOperand());
3579 __ push(Immediate(var->name()));
3580 __ push(Immediate(Smi::FromInt(kNonStrictMode)));
3581 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3582 context()->Plug(eax);
3583 } else if (var->AsSlot() != NULL &&
3584 var->AsSlot()->type() != Slot::LOOKUP) {
3585 // Result of deleting non-global, non-dynamic variables is false.
3586 // The subexpression does not have side effects.
3587 context()->Plug(false);
3588 } else {
3589 // Non-global variable. Call the runtime to try to delete from the
3590 // context where the variable was introduced.
3591 __ push(context_register());
3592 __ push(Immediate(var->name()));
3593 __ CallRuntime(Runtime::kDeleteContextSlot, 2);
3594 context()->Plug(eax);
3595 }
3596 } else {
3736 // Result of deleting non-property, non-variable reference is true. 3597 // Result of deleting non-property, non-variable reference is true.
3737 // The subexpression may have side effects. 3598 // The subexpression may have side effects.
3738 VisitForEffect(expr->expression()); 3599 VisitForEffect(expr->expression());
3739 context()->Plug(true); 3600 context()->Plug(true);
3740 } else if (var != NULL &&
3741 !var->is_global() &&
3742 var->AsSlot() != NULL &&
3743 var->AsSlot()->type() != Slot::LOOKUP) {
3744 // Result of deleting non-global, non-dynamic variables is false.
3745 // The subexpression does not have side effects.
3746 context()->Plug(false);
3747 } else {
3748 // Property or variable reference. Call the delete builtin with
3749 // object and property name as arguments.
3750 if (prop != NULL) {
3751 VisitForStackValue(prop->obj());
3752 VisitForStackValue(prop->key());
3753 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3754 } else if (var->is_global()) {
3755 __ push(GlobalObjectOperand());
3756 __ push(Immediate(var->name()));
3757 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3758 } else {
3759 // Non-global variable. Call the runtime to delete from the
3760 // context where the variable was introduced.
3761 __ push(context_register());
3762 __ push(Immediate(var->name()));
3763 __ CallRuntime(Runtime::kDeleteContextSlot, 2);
3764 }
3765 context()->Plug(eax);
3766 } 3601 }
3767 break; 3602 break;
3768 } 3603 }
3769 3604
3770 case Token::VOID: { 3605 case Token::VOID: {
3771 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 3606 Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3772 VisitForEffect(expr->expression()); 3607 VisitForEffect(expr->expression());
3773 context()->Plug(isolate()->factory()->undefined_value()); 3608 context()->Plug(isolate()->factory()->undefined_value());
3774 break; 3609 break;
3775 } 3610 }
3776 3611
3777 case Token::NOT: { 3612 case Token::NOT: {
3778 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3613 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3614 if (context()->IsEffect()) {
3615 // Unary NOT has no side effects so it's only necessary to visit the
3616 // subexpression. Match the optimizing compiler by not branching.
3617 VisitForEffect(expr->expression());
3618 } else {
3619 Label materialize_true, materialize_false;
3620 Label* if_true = NULL;
3621 Label* if_false = NULL;
3622 Label* fall_through = NULL;
3779 3623
3780 Label materialize_true, materialize_false; 3624 // Notice that the labels are swapped.
3781 Label* if_true = NULL; 3625 context()->PrepareTest(&materialize_true, &materialize_false,
3782 Label* if_false = NULL; 3626 &if_false, &if_true, &fall_through);
3783 Label* fall_through = NULL; 3627 if (context()->IsTest()) ForwardBailoutToChild(expr);
3784 // Notice that the labels are swapped. 3628 VisitForControl(expr->expression(), if_true, if_false, fall_through);
3785 context()->PrepareTest(&materialize_true, &materialize_false, 3629 context()->Plug(if_false, if_true); // Labels swapped.
3786 &if_false, &if_true, &fall_through); 3630 }
3787 if (context()->IsTest()) ForwardBailoutToChild(expr);
3788 VisitForControl(expr->expression(), if_true, if_false, fall_through);
3789 context()->Plug(if_false, if_true); // Labels swapped.
3790 break; 3631 break;
3791 } 3632 }
3792 3633
3793 case Token::TYPEOF: { 3634 case Token::TYPEOF: {
3794 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3635 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3795 { StackValueContext context(this); 3636 { StackValueContext context(this);
3796 VisitForTypeofValue(expr->expression()); 3637 VisitForTypeofValue(expr->expression());
3797 } 3638 }
3798 __ CallRuntime(Runtime::kTypeof, 1); 3639 __ CallRuntime(Runtime::kTypeof, 1);
3799 context()->Plug(eax); 3640 context()->Plug(eax);
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
4006 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3847 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4007 Token::ASSIGN); 3848 Token::ASSIGN);
4008 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3849 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4009 context()->Plug(eax); 3850 context()->Plug(eax);
4010 } 3851 }
4011 break; 3852 break;
4012 case NAMED_PROPERTY: { 3853 case NAMED_PROPERTY: {
4013 __ mov(ecx, prop->key()->AsLiteral()->handle()); 3854 __ mov(ecx, prop->key()->AsLiteral()->handle());
4014 __ pop(edx); 3855 __ pop(edx);
4015 Handle<Code> ic(isolate()->builtins()->builtin( 3856 Handle<Code> ic(isolate()->builtins()->builtin(
4016 Builtins::StoreIC_Initialize)); 3857 is_strict() ? Builtins::StoreIC_Initialize_Strict
3858 : Builtins::StoreIC_Initialize));
4017 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3859 EmitCallIC(ic, RelocInfo::CODE_TARGET);
4018 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3860 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4019 if (expr->is_postfix()) { 3861 if (expr->is_postfix()) {
4020 if (!context()->IsEffect()) { 3862 if (!context()->IsEffect()) {
4021 context()->PlugTOS(); 3863 context()->PlugTOS();
4022 } 3864 }
4023 } else { 3865 } else {
4024 context()->Plug(eax); 3866 context()->Plug(eax);
4025 } 3867 }
4026 break; 3868 break;
4027 } 3869 }
4028 case KEYED_PROPERTY: { 3870 case KEYED_PROPERTY: {
4029 __ pop(ecx); 3871 __ pop(ecx);
4030 __ pop(edx); 3872 __ pop(edx);
4031 Handle<Code> ic(isolate()->builtins()->builtin( 3873 Handle<Code> ic(isolate()->builtins()->builtin(
4032 Builtins::KeyedStoreIC_Initialize)); 3874 is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict
3875 : Builtins::KeyedStoreIC_Initialize));
4033 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3876 EmitCallIC(ic, RelocInfo::CODE_TARGET);
4034 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3877 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4035 if (expr->is_postfix()) { 3878 if (expr->is_postfix()) {
4036 // Result is on the stack 3879 // Result is on the stack
4037 if (!context()->IsEffect()) { 3880 if (!context()->IsEffect()) {
4038 context()->PlugTOS(); 3881 context()->PlugTOS();
4039 } 3882 }
4040 } else { 3883 } else {
4041 context()->Plug(eax); 3884 context()->Plug(eax);
4042 } 3885 }
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after
4371 __ nop(); // Signals no inlined code. 4214 __ nop(); // Signals no inlined code.
4372 break; 4215 break;
4373 default: 4216 default:
4374 // Do nothing. 4217 // Do nothing.
4375 break; 4218 break;
4376 } 4219 }
4377 } 4220 }
4378 4221
4379 4222
4380 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { 4223 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
4224 switch (ic->kind()) {
4225 case Code::LOAD_IC:
4226 __ IncrementCounter(COUNTERS->named_load_full(), 1);
4227 break;
4228 case Code::KEYED_LOAD_IC:
4229 __ IncrementCounter(COUNTERS->keyed_load_full(), 1);
4230 break;
4231 case Code::STORE_IC:
4232 __ IncrementCounter(COUNTERS->named_store_full(), 1);
4233 break;
4234 case Code::KEYED_STORE_IC:
4235 __ IncrementCounter(COUNTERS->keyed_store_full(), 1);
4236 default:
4237 break;
4238 }
4239
4381 __ call(ic, RelocInfo::CODE_TARGET); 4240 __ call(ic, RelocInfo::CODE_TARGET);
4382 if (patch_site != NULL && patch_site->is_bound()) { 4241 if (patch_site != NULL && patch_site->is_bound()) {
4383 patch_site->EmitPatchInfo(); 4242 patch_site->EmitPatchInfo();
4384 } else { 4243 } else {
4385 __ nop(); // Signals no inlined code. 4244 __ nop(); // Signals no inlined code.
4386 } 4245 }
4387 } 4246 }
4388 4247
4389 4248
4390 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4249 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
4427 // And return. 4286 // And return.
4428 __ ret(0); 4287 __ ret(0);
4429 } 4288 }
4430 4289
4431 4290
4432 #undef __ 4291 #undef __
4433 4292
4434 } } // namespace v8::internal 4293 } } // namespace v8::internal
4435 4294
4436 #endif // V8_TARGET_ARCH_IA32 4295 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/deoptimizer-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698