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

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

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
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 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 __ lea(edx, 192 __ lea(edx,
193 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); 193 Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
194 __ push(edx); 194 __ push(edx);
195 __ push(Immediate(Smi::FromInt(scope()->num_parameters()))); 195 __ push(Immediate(Smi::FromInt(scope()->num_parameters())));
196 // Arguments to ArgumentsAccessStub: 196 // Arguments to ArgumentsAccessStub:
197 // function, receiver address, parameter count. 197 // function, receiver address, parameter count.
198 // The stub will rewrite receiver and parameter count if the previous 198 // The stub will rewrite receiver and parameter count if the previous
199 // stack frame was an arguments adapter frame. 199 // stack frame was an arguments adapter frame.
200 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT); 200 ArgumentsAccessStub stub(ArgumentsAccessStub::NEW_OBJECT);
201 __ CallStub(&stub); 201 __ CallStub(&stub);
202 __ mov(ecx, eax); // Duplicate result. 202
203 Variable* arguments_shadow = scope()->arguments_shadow();
204 if (arguments_shadow != NULL) {
205 __ mov(ecx, eax); // Duplicate result.
206 Move(arguments_shadow->AsSlot(), ecx, ebx, edx);
207 }
203 Move(arguments->AsSlot(), eax, ebx, edx); 208 Move(arguments->AsSlot(), eax, ebx, edx);
204 Slot* dot_arguments_slot = scope()->arguments_shadow()->AsSlot();
205 Move(dot_arguments_slot, ecx, ebx, edx);
206 } 209 }
207 210
208 if (FLAG_trace) { 211 if (FLAG_trace) {
209 __ CallRuntime(Runtime::kTraceEnter, 0); 212 __ CallRuntime(Runtime::kTraceEnter, 0);
210 } 213 }
211 214
212 // Visit the declarations and body unless there is an illegal 215 // Visit the declarations and body unless there is an illegal
213 // redeclaration. 216 // redeclaration.
214 if (scope()->HasIllegalRedeclaration()) { 217 if (scope()->HasIllegalRedeclaration()) {
215 Comment cmnt(masm_, "[ Declarations"); 218 Comment cmnt(masm_, "[ Declarations");
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 #ifdef ENABLE_DEBUGGER_SUPPORT 318 #ifdef ENABLE_DEBUGGER_SUPPORT
316 // Check that the size of the code used for returning is large enough 319 // Check that the size of the code used for returning is large enough
317 // for the debugger's requirements. 320 // for the debugger's requirements.
318 ASSERT(Assembler::kJSReturnSequenceLength <= 321 ASSERT(Assembler::kJSReturnSequenceLength <=
319 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); 322 masm_->SizeOfCodeGeneratedSince(&check_exit_codesize));
320 #endif 323 #endif
321 } 324 }
322 } 325 }
323 326
324 327
325 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand(
326 Token::Value op, Expression* left, Expression* right) {
327 ASSERT(ShouldInlineSmiCase(op));
328 if (op == Token::DIV || op == Token::MOD || op == Token::MUL) {
329 // We never generate inlined constant smi operations for these.
330 return kNoConstants;
331 } else if (right->IsSmiLiteral()) {
332 return kRightConstant;
333 } else if (left->IsSmiLiteral() && !Token::IsShiftOp(op)) {
334 return kLeftConstant;
335 } else {
336 return kNoConstants;
337 }
338 }
339
340
341 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { 328 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const {
342 } 329 }
343 330
344 331
345 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { 332 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const {
346 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); 333 MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register());
347 __ mov(result_register(), slot_operand); 334 __ mov(result_register(), slot_operand);
348 } 335 }
349 336
350 337
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 void FullCodeGenerator::DoTest(Label* if_true, 527 void FullCodeGenerator::DoTest(Label* if_true,
541 Label* if_false, 528 Label* if_false,
542 Label* fall_through) { 529 Label* fall_through) {
543 // Emit the inlined tests assumed by the stub. 530 // Emit the inlined tests assumed by the stub.
544 __ cmp(result_register(), Factory::undefined_value()); 531 __ cmp(result_register(), Factory::undefined_value());
545 __ j(equal, if_false); 532 __ j(equal, if_false);
546 __ cmp(result_register(), Factory::true_value()); 533 __ cmp(result_register(), Factory::true_value());
547 __ j(equal, if_true); 534 __ j(equal, if_true);
548 __ cmp(result_register(), Factory::false_value()); 535 __ cmp(result_register(), Factory::false_value());
549 __ j(equal, if_false); 536 __ j(equal, if_false);
550 ASSERT_EQ(0, kSmiTag); 537 STATIC_ASSERT(kSmiTag == 0);
551 __ test(result_register(), Operand(result_register())); 538 __ test(result_register(), Operand(result_register()));
552 __ j(zero, if_false); 539 __ j(zero, if_false);
553 __ test(result_register(), Immediate(kSmiTagMask)); 540 __ test(result_register(), Immediate(kSmiTagMask));
554 __ j(zero, if_true); 541 __ j(zero, if_true);
555 542
556 // Call the ToBoolean stub for all other cases. 543 // Call the ToBoolean stub for all other cases.
557 ToBooleanStub stub; 544 ToBooleanStub stub;
558 __ push(result_register()); 545 __ push(result_register());
559 __ CallStub(&stub); 546 __ CallStub(&stub);
560 __ test(eax, Operand(eax)); 547 __ test(eax, Operand(eax));
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 } 635 }
649 636
650 637
651 void FullCodeGenerator::EmitDeclaration(Variable* variable, 638 void FullCodeGenerator::EmitDeclaration(Variable* variable,
652 Variable::Mode mode, 639 Variable::Mode mode,
653 FunctionLiteral* function) { 640 FunctionLiteral* function) {
654 Comment cmnt(masm_, "[ Declaration"); 641 Comment cmnt(masm_, "[ Declaration");
655 ASSERT(variable != NULL); // Must have been resolved. 642 ASSERT(variable != NULL); // Must have been resolved.
656 Slot* slot = variable->AsSlot(); 643 Slot* slot = variable->AsSlot();
657 Property* prop = variable->AsProperty(); 644 Property* prop = variable->AsProperty();
645
658 if (slot != NULL) { 646 if (slot != NULL) {
659 switch (slot->type()) { 647 switch (slot->type()) {
660 case Slot::PARAMETER: 648 case Slot::PARAMETER:
661 case Slot::LOCAL: 649 case Slot::LOCAL:
662 if (mode == Variable::CONST) { 650 if (mode == Variable::CONST) {
663 __ mov(Operand(ebp, SlotOffset(slot)), 651 __ mov(Operand(ebp, SlotOffset(slot)),
664 Immediate(Factory::the_hole_value())); 652 Immediate(Factory::the_hole_value()));
665 } else if (function != NULL) { 653 } else if (function != NULL) {
666 VisitForAccumulatorValue(function); 654 VisitForAccumulatorValue(function);
667 __ mov(Operand(ebp, SlotOffset(slot)), result_register()); 655 __ mov(Operand(ebp, SlotOffset(slot)), result_register());
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 VisitForAccumulatorValue(function); 721 VisitForAccumulatorValue(function);
734 __ pop(edx); 722 __ pop(edx);
735 } else { 723 } else {
736 __ mov(edx, eax); 724 __ mov(edx, eax);
737 __ mov(eax, Factory::the_hole_value()); 725 __ mov(eax, Factory::the_hole_value());
738 } 726 }
739 ASSERT(prop->key()->AsLiteral() != NULL && 727 ASSERT(prop->key()->AsLiteral() != NULL &&
740 prop->key()->AsLiteral()->handle()->IsSmi()); 728 prop->key()->AsLiteral()->handle()->IsSmi());
741 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); 729 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
742 730
743 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 731 Handle<Code> ic(Builtins::builtin(
732 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict
733 : Builtins::KeyedStoreIC_Initialize));
744 EmitCallIC(ic, RelocInfo::CODE_TARGET); 734 EmitCallIC(ic, RelocInfo::CODE_TARGET);
745 } 735 }
746 } 736 }
747 } 737 }
748 738
749 739
750 void FullCodeGenerator::VisitDeclaration(Declaration* decl) { 740 void FullCodeGenerator::VisitDeclaration(Declaration* decl) {
751 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun()); 741 EmitDeclaration(decl->proxy()->var(), decl->mode(), decl->fun());
752 } 742 }
753 743
754 744
755 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) { 745 void FullCodeGenerator::DeclareGlobals(Handle<FixedArray> pairs) {
756 // Call the runtime to declare the globals. 746 // Call the runtime to declare the globals.
757 __ push(esi); // The context is the first argument. 747 __ push(esi); // The context is the first argument.
758 __ push(Immediate(pairs)); 748 __ push(Immediate(pairs));
759 __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0))); 749 __ push(Immediate(Smi::FromInt(is_eval() ? 1 : 0)));
760 __ CallRuntime(Runtime::kDeclareGlobals, 3); 750 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
751 __ CallRuntime(Runtime::kDeclareGlobals, 4);
761 // Return value is ignored. 752 // Return value is ignored.
762 } 753 }
763 754
764 755
765 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) { 756 void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
766 Comment cmnt(masm_, "[ SwitchStatement"); 757 Comment cmnt(masm_, "[ SwitchStatement");
767 Breakable nested_statement(this, stmt); 758 Breakable nested_statement(this, stmt);
768 SetStatementPosition(stmt); 759 SetStatementPosition(stmt);
769 760
770 // Keep the switch value on the stack until a case matches. 761 // Keep the switch value on the stack until a case matches.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 __ j(not_equal, &next_test); 798 __ j(not_equal, &next_test);
808 __ Drop(1); // Switch value is no longer needed. 799 __ Drop(1); // Switch value is no longer needed.
809 __ jmp(clause->body_target()->entry_label()); 800 __ jmp(clause->body_target()->entry_label());
810 __ bind(&slow_case); 801 __ bind(&slow_case);
811 } 802 }
812 803
813 // Record position before stub call for type feedback. 804 // Record position before stub call for type feedback.
814 SetSourcePosition(clause->position()); 805 SetSourcePosition(clause->position());
815 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); 806 Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT);
816 EmitCallIC(ic, &patch_site); 807 EmitCallIC(ic, &patch_site);
817
818 __ test(eax, Operand(eax)); 808 __ test(eax, Operand(eax));
819 __ j(not_equal, &next_test); 809 __ j(not_equal, &next_test);
820 __ Drop(1); // Switch value is no longer needed. 810 __ Drop(1); // Switch value is no longer needed.
821 __ jmp(clause->body_target()->entry_label()); 811 __ jmp(clause->body_target()->entry_label());
822 } 812 }
823 813
824 // Discard the test value and jump to the default if present, otherwise to 814 // Discard the test value and jump to the default if present, otherwise to
825 // the end of the statement. 815 // the end of the statement.
826 __ bind(&next_test); 816 __ bind(&next_test);
827 __ Drop(1); // Switch value is no longer needed. 817 __ Drop(1); // Switch value is no longer needed.
828 if (default_clause == NULL) { 818 if (default_clause == NULL) {
829 __ jmp(nested_statement.break_target()); 819 __ jmp(nested_statement.break_target());
830 } else { 820 } else {
831 __ jmp(default_clause->body_target()->entry_label()); 821 __ jmp(default_clause->body_target()->entry_label());
832 } 822 }
833 823
834 // Compile all the case bodies. 824 // Compile all the case bodies.
835 for (int i = 0; i < clauses->length(); i++) { 825 for (int i = 0; i < clauses->length(); i++) {
836 Comment cmnt(masm_, "[ Case body"); 826 Comment cmnt(masm_, "[ Case body");
837 CaseClause* clause = clauses->at(i); 827 CaseClause* clause = clauses->at(i);
838 __ bind(clause->body_target()->entry_label()); 828 __ bind(clause->body_target()->entry_label());
829 PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
839 VisitStatements(clause->statements()); 830 VisitStatements(clause->statements());
840 } 831 }
841 832
842 __ bind(nested_statement.break_target()); 833 __ bind(nested_statement.break_target());
843 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 834 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
844 } 835 }
845 836
846 837
847 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 838 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
848 Comment cmnt(masm_, "[ ForInStatement"); 839 Comment cmnt(masm_, "[ ForInStatement");
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 __ j(not_equal, &call_runtime); 879 __ j(not_equal, &call_runtime);
889 880
890 // Check that instance descriptors are not empty so that we can 881 // Check that instance descriptors are not empty so that we can
891 // check for an enum cache. Leave the map in ebx for the subsequent 882 // check for an enum cache. Leave the map in ebx for the subsequent
892 // prototype load. 883 // prototype load.
893 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset)); 884 __ mov(ebx, FieldOperand(ecx, HeapObject::kMapOffset));
894 __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset)); 885 __ mov(edx, FieldOperand(ebx, Map::kInstanceDescriptorsOffset));
895 __ cmp(edx, Factory::empty_descriptor_array()); 886 __ cmp(edx, Factory::empty_descriptor_array());
896 __ j(equal, &call_runtime); 887 __ j(equal, &call_runtime);
897 888
898 // Check that there in an enum cache in the non-empty instance 889 // Check that there is an enum cache in the non-empty instance
899 // descriptors (edx). This is the case if the next enumeration 890 // descriptors (edx). This is the case if the next enumeration
900 // index field does not contain a smi. 891 // index field does not contain a smi.
901 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset)); 892 __ mov(edx, FieldOperand(edx, DescriptorArray::kEnumerationIndexOffset));
902 __ test(edx, Immediate(kSmiTagMask)); 893 __ test(edx, Immediate(kSmiTagMask));
903 __ j(zero, &call_runtime); 894 __ j(zero, &call_runtime);
904 895
905 // For all objects but the receiver, check that the cache is empty. 896 // For all objects but the receiver, check that the cache is empty.
906 NearLabel check_prototype; 897 NearLabel check_prototype;
907 __ cmp(ecx, Operand(eax)); 898 __ cmp(ecx, Operand(eax));
908 __ j(equal, &check_prototype); 899 __ j(equal, &check_prototype);
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
1373 switch (property->kind()) { 1364 switch (property->kind()) {
1374 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1365 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1375 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1366 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1376 // Fall through. 1367 // Fall through.
1377 case ObjectLiteral::Property::COMPUTED: 1368 case ObjectLiteral::Property::COMPUTED:
1378 if (key->handle()->IsSymbol()) { 1369 if (key->handle()->IsSymbol()) {
1379 if (property->emit_store()) { 1370 if (property->emit_store()) {
1380 VisitForAccumulatorValue(value); 1371 VisitForAccumulatorValue(value);
1381 __ mov(ecx, Immediate(key->handle())); 1372 __ mov(ecx, Immediate(key->handle()));
1382 __ mov(edx, Operand(esp, 0)); 1373 __ mov(edx, Operand(esp, 0));
1383 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1374 Handle<Code> ic(Builtins::builtin(
1375 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict
1376 : Builtins::StoreIC_Initialize));
1384 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1377 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1385 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1378 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1386 } else { 1379 } else {
1387 VisitForEffect(value); 1380 VisitForEffect(value);
1388 } 1381 }
1389 break; 1382 break;
1390 } 1383 }
1391 // Fall through. 1384 // Fall through.
1392 case ObjectLiteral::Property::PROTOTYPE: 1385 case ObjectLiteral::Property::PROTOTYPE:
1393 __ push(Operand(esp, 0)); // Duplicate receiver. 1386 __ push(Operand(esp, 0)); // Duplicate receiver.
1394 VisitForStackValue(key); 1387 VisitForStackValue(key);
1395 VisitForStackValue(value); 1388 VisitForStackValue(value);
1396 if (property->emit_store()) { 1389 if (property->emit_store()) {
1397 __ CallRuntime(Runtime::kSetProperty, 3); 1390 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes
1391 __ CallRuntime(Runtime::kSetProperty, 4);
1398 } else { 1392 } else {
1399 __ Drop(3); 1393 __ Drop(3);
1400 } 1394 }
1401 break; 1395 break;
1402 case ObjectLiteral::Property::SETTER: 1396 case ObjectLiteral::Property::SETTER:
1403 case ObjectLiteral::Property::GETTER: 1397 case ObjectLiteral::Property::GETTER:
1404 __ push(Operand(esp, 0)); // Duplicate receiver. 1398 __ push(Operand(esp, 0)); // Duplicate receiver.
1405 VisitForStackValue(key); 1399 VisitForStackValue(key);
1406 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ? 1400 __ push(Immediate(property->kind() == ObjectLiteral::Property::SETTER ?
1407 Smi::FromInt(1) : 1401 Smi::FromInt(1) :
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 } 1559 }
1566 } 1560 }
1567 1561
1568 // For property compound assignments we need another deoptimization 1562 // For property compound assignments we need another deoptimization
1569 // point after the property load. 1563 // point after the property load.
1570 if (property != NULL) { 1564 if (property != NULL) {
1571 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); 1565 PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG);
1572 } 1566 }
1573 1567
1574 Token::Value op = expr->binary_op(); 1568 Token::Value op = expr->binary_op();
1575 ConstantOperand constant = ShouldInlineSmiCase(op) 1569 __ push(eax); // Left operand goes on the stack.
1576 ? GetConstantOperand(op, expr->target(), expr->value()) 1570 VisitForAccumulatorValue(expr->value());
1577 : kNoConstants;
1578 ASSERT(constant == kRightConstant || constant == kNoConstants);
1579 if (constant == kNoConstants) {
1580 __ push(eax); // Left operand goes on the stack.
1581 VisitForAccumulatorValue(expr->value());
1582 }
1583 1571
1584 OverwriteMode mode = expr->value()->ResultOverwriteAllowed() 1572 OverwriteMode mode = expr->value()->ResultOverwriteAllowed()
1585 ? OVERWRITE_RIGHT 1573 ? OVERWRITE_RIGHT
1586 : NO_OVERWRITE; 1574 : NO_OVERWRITE;
1587 SetSourcePosition(expr->position() + 1); 1575 SetSourcePosition(expr->position() + 1);
1588 AccumulatorValueContext context(this); 1576 AccumulatorValueContext context(this);
1589 if (ShouldInlineSmiCase(op)) { 1577 if (ShouldInlineSmiCase(op)) {
1590 EmitInlineSmiBinaryOp(expr, 1578 EmitInlineSmiBinaryOp(expr,
1591 op, 1579 op,
1592 mode, 1580 mode,
1593 expr->target(), 1581 expr->target(),
1594 expr->value(), 1582 expr->value());
1595 constant);
1596 } else { 1583 } else {
1597 EmitBinaryOp(op, mode); 1584 EmitBinaryOp(op, mode);
1598 } 1585 }
1599 1586
1600 // Deoptimization point in case the binary operation may have side effects. 1587 // Deoptimization point in case the binary operation may have side effects.
1601 PrepareForBailout(expr->binary_operation(), TOS_REG); 1588 PrepareForBailout(expr->binary_operation(), TOS_REG);
1602 } else { 1589 } else {
1603 VisitForAccumulatorValue(expr->value()); 1590 VisitForAccumulatorValue(expr->value());
1604 } 1591 }
1605 1592
(...skipping 27 matching lines...) Expand all
1633 } 1620 }
1634 1621
1635 1622
1636 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 1623 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
1637 SetSourcePosition(prop->position()); 1624 SetSourcePosition(prop->position());
1638 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 1625 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
1639 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1626 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1640 } 1627 }
1641 1628
1642 1629
1643 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr,
1644 OverwriteMode mode,
1645 bool left_is_constant_smi,
1646 Smi* value) {
1647 NearLabel call_stub, done;
1648 __ add(Operand(eax), Immediate(value));
1649 __ j(overflow, &call_stub);
1650 JumpPatchSite patch_site(masm_);
1651 patch_site.EmitJumpIfSmi(eax, &done);
1652
1653 // Undo the optimistic add operation and call the shared stub.
1654 __ bind(&call_stub);
1655 __ sub(Operand(eax), Immediate(value));
1656 Token::Value op = Token::ADD;
1657 TypeRecordingBinaryOpStub stub(op, mode);
1658 if (left_is_constant_smi) {
1659 __ mov(edx, Immediate(value));
1660 } else {
1661 __ mov(edx, eax);
1662 __ mov(eax, Immediate(value));
1663 }
1664 EmitCallIC(stub.GetCode(), &patch_site);
1665
1666 __ bind(&done);
1667 context()->Plug(eax);
1668 }
1669
1670
1671 void FullCodeGenerator::EmitConstantSmiSub(Expression* expr,
1672 OverwriteMode mode,
1673 bool left_is_constant_smi,
1674 Smi* value) {
1675 NearLabel call_stub, done;
1676 if (left_is_constant_smi) {
1677 __ mov(ecx, eax);
1678 __ mov(eax, Immediate(value));
1679 __ sub(Operand(eax), ecx);
1680 } else {
1681 __ sub(Operand(eax), Immediate(value));
1682 }
1683 __ j(overflow, &call_stub);
1684 JumpPatchSite patch_site(masm_);
1685 patch_site.EmitJumpIfSmi(eax, &done);
1686
1687 __ bind(&call_stub);
1688 if (left_is_constant_smi) {
1689 __ mov(edx, Immediate(value));
1690 __ mov(eax, ecx);
1691 } else {
1692 __ add(Operand(eax), Immediate(value)); // Undo the subtraction.
1693 __ mov(edx, eax);
1694 __ mov(eax, Immediate(value));
1695 }
1696 Token::Value op = Token::SUB;
1697 TypeRecordingBinaryOpStub stub(op, mode);
1698 EmitCallIC(stub.GetCode(), &patch_site);
1699
1700 __ bind(&done);
1701 context()->Plug(eax);
1702 }
1703
1704
1705 void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr,
1706 Token::Value op,
1707 OverwriteMode mode,
1708 Smi* value) {
1709 NearLabel call_stub, smi_case, done;
1710 int shift_value = value->value() & 0x1f;
1711
1712 JumpPatchSite patch_site(masm_);
1713 patch_site.EmitJumpIfSmi(eax, &smi_case);
1714
1715 // Call stub.
1716 __ bind(&call_stub);
1717 __ mov(edx, eax);
1718 __ mov(eax, Immediate(value));
1719 TypeRecordingBinaryOpStub stub(op, mode);
1720 EmitCallIC(stub.GetCode(), &patch_site);
1721 __ jmp(&done);
1722
1723 // Smi case.
1724 __ bind(&smi_case);
1725 switch (op) {
1726 case Token::SHL:
1727 if (shift_value != 0) {
1728 __ mov(edx, eax);
1729 if (shift_value > 1) {
1730 __ shl(edx, shift_value - 1);
1731 }
1732 // Convert int result to smi, checking that it is in int range.
1733 ASSERT(kSmiTagSize == 1); // Adjust code if not the case.
1734 __ add(edx, Operand(edx));
1735 __ j(overflow, &call_stub);
1736 __ mov(eax, edx); // Put result back into eax.
1737 }
1738 break;
1739 case Token::SAR:
1740 if (shift_value != 0) {
1741 __ sar(eax, shift_value);
1742 __ and_(eax, ~kSmiTagMask);
1743 }
1744 break;
1745 case Token::SHR:
1746 if (shift_value < 2) {
1747 __ mov(edx, eax);
1748 __ SmiUntag(edx);
1749 __ shr(edx, shift_value);
1750 __ test(edx, Immediate(0xc0000000));
1751 __ j(not_zero, &call_stub);
1752 __ SmiTag(edx);
1753 __ mov(eax, edx); // Put result back into eax.
1754 } else {
1755 __ SmiUntag(eax);
1756 __ shr(eax, shift_value);
1757 __ SmiTag(eax);
1758 }
1759 break;
1760 default:
1761 UNREACHABLE();
1762 }
1763
1764 __ bind(&done);
1765 context()->Plug(eax);
1766 }
1767
1768
1769 void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr,
1770 Token::Value op,
1771 OverwriteMode mode,
1772 Smi* value) {
1773 NearLabel smi_case, done;
1774
1775 JumpPatchSite patch_site(masm_);
1776 patch_site.EmitJumpIfSmi(eax, &smi_case);
1777
1778 // The order of the arguments does not matter for bit-ops with a
1779 // constant operand.
1780 __ mov(edx, Immediate(value));
1781 TypeRecordingBinaryOpStub stub(op, mode);
1782 EmitCallIC(stub.GetCode(), &patch_site);
1783 __ jmp(&done);
1784
1785 // Smi case.
1786 __ bind(&smi_case);
1787 switch (op) {
1788 case Token::BIT_OR:
1789 __ or_(Operand(eax), Immediate(value));
1790 break;
1791 case Token::BIT_XOR:
1792 __ xor_(Operand(eax), Immediate(value));
1793 break;
1794 case Token::BIT_AND:
1795 __ and_(Operand(eax), Immediate(value));
1796 break;
1797 default:
1798 UNREACHABLE();
1799 }
1800
1801 __ bind(&done);
1802 context()->Plug(eax);
1803 }
1804
1805
1806 void FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr,
1807 Token::Value op,
1808 OverwriteMode mode,
1809 bool left_is_constant_smi,
1810 Smi* value) {
1811 switch (op) {
1812 case Token::BIT_OR:
1813 case Token::BIT_XOR:
1814 case Token::BIT_AND:
1815 EmitConstantSmiBitOp(expr, op, mode, value);
1816 break;
1817 case Token::SHL:
1818 case Token::SAR:
1819 case Token::SHR:
1820 ASSERT(!left_is_constant_smi);
1821 EmitConstantSmiShiftOp(expr, op, mode, value);
1822 break;
1823 case Token::ADD:
1824 EmitConstantSmiAdd(expr, mode, left_is_constant_smi, value);
1825 break;
1826 case Token::SUB:
1827 EmitConstantSmiSub(expr, mode, left_is_constant_smi, value);
1828 break;
1829 default:
1830 UNREACHABLE();
1831 }
1832 }
1833
1834
1835 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, 1630 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr,
1836 Token::Value op, 1631 Token::Value op,
1837 OverwriteMode mode, 1632 OverwriteMode mode,
1838 Expression* left, 1633 Expression* left,
1839 Expression* right, 1634 Expression* right) {
1840 ConstantOperand constant) {
1841 if (constant == kRightConstant) {
1842 Smi* value = Smi::cast(*right->AsLiteral()->handle());
1843 EmitConstantSmiBinaryOp(expr, op, mode, false, value);
1844 return;
1845 } else if (constant == kLeftConstant) {
1846 Smi* value = Smi::cast(*left->AsLiteral()->handle());
1847 EmitConstantSmiBinaryOp(expr, op, mode, true, value);
1848 return;
1849 }
1850
1851 // Do combined smi check of the operands. Left operand is on the 1635 // Do combined smi check of the operands. Left operand is on the
1852 // stack. Right operand is in eax. 1636 // stack. Right operand is in eax.
1853 NearLabel done, smi_case, stub_call; 1637 NearLabel done, smi_case, stub_call;
1854 __ pop(edx); 1638 __ pop(edx);
1855 __ mov(ecx, eax); 1639 __ mov(ecx, eax);
1856 __ or_(eax, Operand(edx)); 1640 __ or_(eax, Operand(edx));
1857 JumpPatchSite patch_site(masm_); 1641 JumpPatchSite patch_site(masm_);
1858 patch_site.EmitJumpIfSmi(eax, &smi_case); 1642 patch_site.EmitJumpIfSmi(eax, &smi_case);
1859 1643
1860 __ bind(&stub_call); 1644 __ bind(&stub_call);
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1972 EffectContext context(this); 1756 EffectContext context(this);
1973 EmitVariableAssignment(var, Token::ASSIGN); 1757 EmitVariableAssignment(var, Token::ASSIGN);
1974 break; 1758 break;
1975 } 1759 }
1976 case NAMED_PROPERTY: { 1760 case NAMED_PROPERTY: {
1977 __ push(eax); // Preserve value. 1761 __ push(eax); // Preserve value.
1978 VisitForAccumulatorValue(prop->obj()); 1762 VisitForAccumulatorValue(prop->obj());
1979 __ mov(edx, eax); 1763 __ mov(edx, eax);
1980 __ pop(eax); // Restore value. 1764 __ pop(eax); // Restore value.
1981 __ mov(ecx, prop->key()->AsLiteral()->handle()); 1765 __ mov(ecx, prop->key()->AsLiteral()->handle());
1982 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1766 Handle<Code> ic(Builtins::builtin(
1767 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict
1768 : Builtins::StoreIC_Initialize));
1983 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1769 EmitCallIC(ic, RelocInfo::CODE_TARGET);
1984 break; 1770 break;
1985 } 1771 }
1986 case KEYED_PROPERTY: { 1772 case KEYED_PROPERTY: {
1987 __ push(eax); // Preserve value. 1773 __ push(eax); // Preserve value.
1988 if (prop->is_synthetic()) { 1774 if (prop->is_synthetic()) {
1989 ASSERT(prop->obj()->AsVariableProxy() != NULL); 1775 ASSERT(prop->obj()->AsVariableProxy() != NULL);
1990 ASSERT(prop->key()->AsLiteral() != NULL); 1776 ASSERT(prop->key()->AsLiteral() != NULL);
1991 { AccumulatorValueContext for_object(this); 1777 { AccumulatorValueContext for_object(this);
1992 EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); 1778 EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
1993 } 1779 }
1994 __ mov(edx, eax); 1780 __ mov(edx, eax);
1995 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); 1781 __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
1996 } else { 1782 } else {
1997 VisitForStackValue(prop->obj()); 1783 VisitForStackValue(prop->obj());
1998 VisitForAccumulatorValue(prop->key()); 1784 VisitForAccumulatorValue(prop->key());
1999 __ mov(ecx, eax); 1785 __ mov(ecx, eax);
2000 __ pop(edx); 1786 __ pop(edx);
2001 } 1787 }
2002 __ pop(eax); // Restore value. 1788 __ pop(eax); // Restore value.
2003 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1789 Handle<Code> ic(Builtins::builtin(
1790 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict
1791 : Builtins::KeyedStoreIC_Initialize));
2004 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1792 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2005 break; 1793 break;
2006 } 1794 }
2007 } 1795 }
2008 PrepareForBailoutForId(bailout_ast_id, TOS_REG); 1796 PrepareForBailoutForId(bailout_ast_id, TOS_REG);
2009 context()->Plug(eax); 1797 context()->Plug(eax);
2010 } 1798 }
2011 1799
2012 1800
2013 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 1801 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2014 Token::Value op) { 1802 Token::Value op) {
2015 // Left-hand sides that rewrite to explicit property accesses do not reach 1803 // Left-hand sides that rewrite to explicit property accesses do not reach
2016 // here. 1804 // here.
2017 ASSERT(var != NULL); 1805 ASSERT(var != NULL);
2018 ASSERT(var->is_global() || var->AsSlot() != NULL); 1806 ASSERT(var->is_global() || var->AsSlot() != NULL);
2019 1807
2020 if (var->is_global()) { 1808 if (var->is_global()) {
2021 ASSERT(!var->is_this()); 1809 ASSERT(!var->is_this());
2022 // Assignment to a global variable. Use inline caching for the 1810 // Assignment to a global variable. Use inline caching for the
2023 // assignment. Right-hand-side value is passed in eax, variable name in 1811 // assignment. Right-hand-side value is passed in eax, variable name in
2024 // ecx, and the global object on the stack. 1812 // ecx, and the global object on the stack.
2025 __ mov(ecx, var->name()); 1813 __ mov(ecx, var->name());
2026 __ mov(edx, GlobalObjectOperand()); 1814 __ mov(edx, GlobalObjectOperand());
2027 Handle<Code> ic(Builtins::builtin( 1815 Handle<Code> ic(Builtins::builtin(
2028 is_strict() ? Builtins::StoreIC_Initialize_Strict 1816 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict
2029 : Builtins::StoreIC_Initialize)); 1817 : Builtins::StoreIC_Initialize));
2030 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); 1818 EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
2031 1819
2032 } else if (op == Token::INIT_CONST) { 1820 } else if (op == Token::INIT_CONST) {
2033 // Like var declarations, const declarations are hoisted to function 1821 // Like var declarations, const declarations are hoisted to function
2034 // scope. However, unlike var initializers, const initializers are able 1822 // scope. However, unlike var initializers, const initializers are able
2035 // to drill a hole to that function context, even from inside a 'with' 1823 // to drill a hole to that function context, even from inside a 'with'
2036 // context. We thus bypass the normal static scope lookup. 1824 // context. We thus bypass the normal static scope lookup.
2037 Slot* slot = var->AsSlot(); 1825 Slot* slot = var->AsSlot();
2038 Label skip; 1826 Label skip;
2039 switch (slot->type()) { 1827 switch (slot->type()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2089 int offset = Context::SlotOffset(slot->index()); 1877 int offset = Context::SlotOffset(slot->index());
2090 __ RecordWrite(ecx, offset, edx, ebx, kDontSaveFPRegs); 1878 __ RecordWrite(ecx, offset, edx, ebx, kDontSaveFPRegs);
2091 break; 1879 break;
2092 } 1880 }
2093 1881
2094 case Slot::LOOKUP: 1882 case Slot::LOOKUP:
2095 // Call the runtime for the assignment. 1883 // Call the runtime for the assignment.
2096 __ push(eax); // Value. 1884 __ push(eax); // Value.
2097 __ push(esi); // Context. 1885 __ push(esi); // Context.
2098 __ push(Immediate(var->name())); 1886 __ push(Immediate(var->name()));
2099 __ CallRuntime(Runtime::kStoreContextSlot, 3); 1887 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
1888 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2100 break; 1889 break;
2101 } 1890 }
2102 } 1891 }
2103 } 1892 }
2104 1893
2105 1894
2106 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 1895 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2107 // Assignment to a property, using a named store IC. 1896 // Assignment to a property, using a named store IC.
2108 Property* prop = expr->target()->AsProperty(); 1897 Property* prop = expr->target()->AsProperty();
2109 ASSERT(prop != NULL); 1898 ASSERT(prop != NULL);
(...skipping 10 matching lines...) Expand all
2120 } 1909 }
2121 1910
2122 // Record source code position before IC call. 1911 // Record source code position before IC call.
2123 SetSourcePosition(expr->position()); 1912 SetSourcePosition(expr->position());
2124 __ mov(ecx, prop->key()->AsLiteral()->handle()); 1913 __ mov(ecx, prop->key()->AsLiteral()->handle());
2125 if (expr->ends_initialization_block()) { 1914 if (expr->ends_initialization_block()) {
2126 __ mov(edx, Operand(esp, 0)); 1915 __ mov(edx, Operand(esp, 0));
2127 } else { 1916 } else {
2128 __ pop(edx); 1917 __ pop(edx);
2129 } 1918 }
2130 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 1919 Handle<Code> ic(Builtins::builtin(
1920 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict
1921 : Builtins::StoreIC_Initialize));
2131 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1922 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2132 1923
2133 // If the assignment ends an initialization block, revert to fast case. 1924 // If the assignment ends an initialization block, revert to fast case.
2134 if (expr->ends_initialization_block()) { 1925 if (expr->ends_initialization_block()) {
2135 __ push(eax); // Result of assignment, saved even if not needed. 1926 __ push(eax); // Result of assignment, saved even if not needed.
2136 __ push(Operand(esp, kPointerSize)); // Receiver is under value. 1927 __ push(Operand(esp, kPointerSize)); // Receiver is under value.
2137 __ CallRuntime(Runtime::kToFastProperties, 1); 1928 __ CallRuntime(Runtime::kToFastProperties, 1);
2138 __ pop(eax); 1929 __ pop(eax);
2139 __ Drop(1); 1930 __ Drop(1);
2140 } 1931 }
(...skipping 17 matching lines...) Expand all
2158 } 1949 }
2159 1950
2160 __ pop(ecx); 1951 __ pop(ecx);
2161 if (expr->ends_initialization_block()) { 1952 if (expr->ends_initialization_block()) {
2162 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later. 1953 __ mov(edx, Operand(esp, 0)); // Leave receiver on the stack for later.
2163 } else { 1954 } else {
2164 __ pop(edx); 1955 __ pop(edx);
2165 } 1956 }
2166 // Record source code position before IC call. 1957 // Record source code position before IC call.
2167 SetSourcePosition(expr->position()); 1958 SetSourcePosition(expr->position());
2168 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 1959 Handle<Code> ic(Builtins::builtin(
1960 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict
1961 : Builtins::KeyedStoreIC_Initialize));
2169 EmitCallIC(ic, RelocInfo::CODE_TARGET); 1962 EmitCallIC(ic, RelocInfo::CODE_TARGET);
2170 1963
2171 // If the assignment ends an initialization block, revert to fast case. 1964 // If the assignment ends an initialization block, revert to fast case.
2172 if (expr->ends_initialization_block()) { 1965 if (expr->ends_initialization_block()) {
2173 __ pop(edx); 1966 __ pop(edx);
2174 __ push(eax); // Result of assignment, saved even if not needed. 1967 __ push(eax); // Result of assignment, saved even if not needed.
2175 __ push(edx); 1968 __ push(edx);
2176 __ CallRuntime(Runtime::kToFastProperties, 1); 1969 __ CallRuntime(Runtime::kToFastProperties, 1);
2177 __ pop(eax); 1970 __ pop(eax);
2178 } 1971 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
2271 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2064 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2272 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 2065 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
2273 __ CallStub(&stub); 2066 __ CallStub(&stub);
2274 RecordJSReturnSite(expr); 2067 RecordJSReturnSite(expr);
2275 // Restore context register. 2068 // Restore context register.
2276 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2069 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2277 context()->DropAndPlug(1, eax); 2070 context()->DropAndPlug(1, eax);
2278 } 2071 }
2279 2072
2280 2073
2074 void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
2075 int arg_count) {
2076 // Push copy of the first argument or undefined if it doesn't exist.
2077 if (arg_count > 0) {
2078 __ push(Operand(esp, arg_count * kPointerSize));
2079 } else {
2080 __ push(Immediate(Factory::undefined_value()));
2081 }
2082
2083 // Push the receiver of the enclosing function.
2084 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize));
2085
2086 // Push the strict mode flag.
2087 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
2088
2089 __ CallRuntime(flag == SKIP_CONTEXT_LOOKUP
2090 ? Runtime::kResolvePossiblyDirectEvalNoLookup
2091 : Runtime::kResolvePossiblyDirectEval, 4);
2092 }
2093
2094
2281 void FullCodeGenerator::VisitCall(Call* expr) { 2095 void FullCodeGenerator::VisitCall(Call* expr) {
2282 #ifdef DEBUG 2096 #ifdef DEBUG
2283 // We want to verify that RecordJSReturnSite gets called on all paths 2097 // We want to verify that RecordJSReturnSite gets called on all paths
2284 // through this function. Avoid early returns. 2098 // through this function. Avoid early returns.
2285 expr->return_is_recorded_ = false; 2099 expr->return_is_recorded_ = false;
2286 #endif 2100 #endif
2287 2101
2288 Comment cmnt(masm_, "[ Call"); 2102 Comment cmnt(masm_, "[ Call");
2289 Expression* fun = expr->expression(); 2103 Expression* fun = expr->expression();
2290 Variable* var = fun->AsVariableProxy()->AsVariable(); 2104 Variable* var = fun->AsVariableProxy()->AsVariable();
2291 2105
2292 if (var != NULL && var->is_possibly_eval()) { 2106 if (var != NULL && var->is_possibly_eval()) {
2293 // In a call to eval, we first call %ResolvePossiblyDirectEval to 2107 // In a call to eval, we first call %ResolvePossiblyDirectEval to
2294 // resolve the function we need to call and the receiver of the 2108 // resolve the function we need to call and the receiver of the
2295 // call. Then we call the resolved function using the given 2109 // call. Then we call the resolved function using the given
2296 // arguments. 2110 // arguments.
2297 ZoneList<Expression*>* args = expr->arguments(); 2111 ZoneList<Expression*>* args = expr->arguments();
2298 int arg_count = args->length(); 2112 int arg_count = args->length();
2299 { PreservePositionScope pos_scope(masm()->positions_recorder()); 2113 { PreservePositionScope pos_scope(masm()->positions_recorder());
2300 VisitForStackValue(fun); 2114 VisitForStackValue(fun);
2301 // Reserved receiver slot. 2115 // Reserved receiver slot.
2302 __ push(Immediate(Factory::undefined_value())); 2116 __ push(Immediate(Factory::undefined_value()));
2303 2117
2304 // Push the arguments. 2118 // Push the arguments.
2305 for (int i = 0; i < arg_count; i++) { 2119 for (int i = 0; i < arg_count; i++) {
2306 VisitForStackValue(args->at(i)); 2120 VisitForStackValue(args->at(i));
2307 } 2121 }
2308 2122
2309 // Push copy of the function - found below the arguments. 2123 // If we know that eval can only be shadowed by eval-introduced
2310 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); 2124 // variables we attempt to load the global eval function directly
2311 2125 // in generated code. If we succeed, there is no need to perform a
2312 // Push copy of the first argument or undefined if it doesn't exist. 2126 // context lookup in the runtime system.
2313 if (arg_count > 0) { 2127 Label done;
2314 __ push(Operand(esp, arg_count * kPointerSize)); 2128 if (var->AsSlot() != NULL && var->mode() == Variable::DYNAMIC_GLOBAL) {
2315 } else { 2129 Label slow;
2316 __ push(Immediate(Factory::undefined_value())); 2130 EmitLoadGlobalSlotCheckExtensions(var->AsSlot(),
2131 NOT_INSIDE_TYPEOF,
2132 &slow);
2133 // Push the function and resolve eval.
2134 __ push(eax);
2135 EmitResolvePossiblyDirectEval(SKIP_CONTEXT_LOOKUP, arg_count);
2136 __ jmp(&done);
2137 __ bind(&slow);
2317 } 2138 }
2318 2139
2319 // Push the receiver of the enclosing function and do runtime call. 2140 // Push copy of the function (found below the arguments) and
2320 __ push(Operand(ebp, (2 + scope()->num_parameters()) * kPointerSize)); 2141 // resolve eval.
2321 // Push the strict mode flag. 2142 __ push(Operand(esp, (arg_count + 1) * kPointerSize));
2322 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); 2143 EmitResolvePossiblyDirectEval(PERFORM_CONTEXT_LOOKUP, arg_count);
2323 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 4); 2144 if (done.is_linked()) {
2145 __ bind(&done);
2146 }
2324 2147
2325 // The runtime call returns a pair of values in eax (function) and 2148 // The runtime call returns a pair of values in eax (function) and
2326 // edx (receiver). Touch up the stack with the right values. 2149 // edx (receiver). Touch up the stack with the right values.
2327 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); 2150 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
2328 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); 2151 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
2329 } 2152 }
2330 // Record source position for debugger. 2153 // Record source position for debugger.
2331 SetSourcePosition(expr->position()); 2154 SetSourcePosition(expr->position());
2332 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; 2155 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP;
2333 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); 2156 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2378 __ bind(&call); 2201 __ bind(&call);
2379 } 2202 }
2380 2203
2381 EmitCallWithStub(expr); 2204 EmitCallWithStub(expr);
2382 } else if (fun->AsProperty() != NULL) { 2205 } else if (fun->AsProperty() != NULL) {
2383 // Call to an object property. 2206 // Call to an object property.
2384 Property* prop = fun->AsProperty(); 2207 Property* prop = fun->AsProperty();
2385 Literal* key = prop->key()->AsLiteral(); 2208 Literal* key = prop->key()->AsLiteral();
2386 if (key != NULL && key->handle()->IsSymbol()) { 2209 if (key != NULL && key->handle()->IsSymbol()) {
2387 // Call to a named property, use call IC. 2210 // Call to a named property, use call IC.
2388 VisitForStackValue(prop->obj()); 2211 { PreservePositionScope scope(masm()->positions_recorder());
2212 VisitForStackValue(prop->obj());
2213 }
2389 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); 2214 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET);
2390 } else { 2215 } else {
2391 // Call to a keyed property. 2216 // Call to a keyed property.
2392 // For a synthetic property use keyed load IC followed by function call, 2217 // For a synthetic property use keyed load IC followed by function call,
2393 // for a regular property use keyed EmitCallIC. 2218 // for a regular property use keyed EmitCallIC.
2394 if (prop->is_synthetic()) { 2219 if (prop->is_synthetic()) {
2395 // Do not visit the object and key subexpressions (they are shared 2220 // Do not visit the object and key subexpressions (they are shared
2396 // by all occurrences of the same rewritten parameter). 2221 // by all occurrences of the same rewritten parameter).
2397 ASSERT(prop->obj()->AsVariableProxy() != NULL); 2222 ASSERT(prop->obj()->AsVariableProxy() != NULL);
2398 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL); 2223 ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
(...skipping 821 matching lines...) Expand 10 before | Expand all | Expand 10 after
3220 Label slow_case; 3045 Label slow_case;
3221 Register object = eax; 3046 Register object = eax;
3222 Register index_1 = ebx; 3047 Register index_1 = ebx;
3223 Register index_2 = ecx; 3048 Register index_2 = ecx;
3224 Register elements = edi; 3049 Register elements = edi;
3225 Register temp = edx; 3050 Register temp = edx;
3226 __ mov(object, Operand(esp, 2 * kPointerSize)); 3051 __ mov(object, Operand(esp, 2 * kPointerSize));
3227 // Fetch the map and check if array is in fast case. 3052 // Fetch the map and check if array is in fast case.
3228 // Check that object doesn't require security checks and 3053 // Check that object doesn't require security checks and
3229 // has no indexed interceptor. 3054 // has no indexed interceptor.
3230 __ CmpObjectType(object, FIRST_JS_OBJECT_TYPE, temp); 3055 __ CmpObjectType(object, JS_ARRAY_TYPE, temp);
3231 __ j(below, &slow_case); 3056 __ j(not_equal, &slow_case);
3232 __ test_b(FieldOperand(temp, Map::kBitFieldOffset), 3057 __ test_b(FieldOperand(temp, Map::kBitFieldOffset),
3233 KeyedLoadIC::kSlowCaseBitFieldMask); 3058 KeyedLoadIC::kSlowCaseBitFieldMask);
3234 __ j(not_zero, &slow_case); 3059 __ j(not_zero, &slow_case);
3235 3060
3236 // Check the object's elements are in fast case and writable. 3061 // Check the object's elements are in fast case and writable.
3237 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset)); 3062 __ mov(elements, FieldOperand(object, JSObject::kElementsOffset));
3238 __ cmp(FieldOperand(elements, HeapObject::kMapOffset), 3063 __ cmp(FieldOperand(elements, HeapObject::kMapOffset),
3239 Immediate(Factory::fixed_array_map())); 3064 Immediate(Factory::fixed_array_map()));
3240 __ j(not_equal, &slow_case); 3065 __ j(not_equal, &slow_case);
3241 3066
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
3391 Immediate(String::kContainsCachedArrayIndexMask)); 3216 Immediate(String::kContainsCachedArrayIndexMask));
3392 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3217 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
3393 Split(zero, if_true, if_false, fall_through); 3218 Split(zero, if_true, if_false, fall_through);
3394 3219
3395 context()->Plug(if_true, if_false); 3220 context()->Plug(if_true, if_false);
3396 } 3221 }
3397 3222
3398 3223
3399 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) { 3224 void FullCodeGenerator::EmitGetCachedArrayIndex(ZoneList<Expression*>* args) {
3400 ASSERT(args->length() == 1); 3225 ASSERT(args->length() == 1);
3401
3402 VisitForAccumulatorValue(args->at(0)); 3226 VisitForAccumulatorValue(args->at(0));
3403 3227
3404 if (FLAG_debug_code) { 3228 if (FLAG_debug_code) {
3405 __ AbortIfNotString(eax); 3229 __ AbortIfNotString(eax);
3406 } 3230 }
3407 3231
3408 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset)); 3232 __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
3409 __ IndexFromHash(eax, eax); 3233 __ IndexFromHash(eax, eax);
3410 3234
3411 context()->Plug(eax); 3235 context()->Plug(eax);
3412 } 3236 }
3413 3237
3414 3238
3415 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) { 3239 void FullCodeGenerator::EmitFastAsciiArrayJoin(ZoneList<Expression*>* args) {
3416 Label bailout, done, one_char_separator, long_separator, 3240 Label bailout, done, one_char_separator, long_separator,
3417 non_trivial_array, not_size_one_array, loop, loop_condition, 3241 non_trivial_array, not_size_one_array, loop,
3418 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry; 3242 loop_1, loop_1_condition, loop_2, loop_2_entry, loop_3, loop_3_entry;
3419 3243
3420 ASSERT(args->length() == 2); 3244 ASSERT(args->length() == 2);
3421 // We will leave the separator on the stack until the end of the function. 3245 // We will leave the separator on the stack until the end of the function.
3422 VisitForStackValue(args->at(1)); 3246 VisitForStackValue(args->at(1));
3423 // Load this to eax (= array) 3247 // Load this to eax (= array)
3424 VisitForAccumulatorValue(args->at(0)); 3248 VisitForAccumulatorValue(args->at(0));
3425 // All aliases of the same register have disjoint lifetimes. 3249 // All aliases of the same register have disjoint lifetimes.
3426 Register array = eax; 3250 Register array = eax;
3427 Register elements = no_reg; // Will be eax. 3251 Register elements = no_reg; // Will be eax.
(...skipping 21 matching lines...) Expand all
3449 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch); 3273 __ CmpObjectType(array, JS_ARRAY_TYPE, scratch);
3450 __ j(not_equal, &bailout); 3274 __ j(not_equal, &bailout);
3451 3275
3452 // Check that the array has fast elements. 3276 // Check that the array has fast elements.
3453 __ test_b(FieldOperand(scratch, Map::kBitField2Offset), 3277 __ test_b(FieldOperand(scratch, Map::kBitField2Offset),
3454 1 << Map::kHasFastElements); 3278 1 << Map::kHasFastElements);
3455 __ j(zero, &bailout); 3279 __ j(zero, &bailout);
3456 3280
3457 // If the array has length zero, return the empty string. 3281 // If the array has length zero, return the empty string.
3458 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset)); 3282 __ mov(array_length, FieldOperand(array, JSArray::kLengthOffset));
3459 __ sar(array_length, 1); 3283 __ SmiUntag(array_length);
3460 __ j(not_zero, &non_trivial_array); 3284 __ j(not_zero, &non_trivial_array);
3461 __ mov(result_operand, Factory::empty_string()); 3285 __ mov(result_operand, Factory::empty_string());
3462 __ jmp(&done); 3286 __ jmp(&done);
3463 3287
3464 // Save the array length. 3288 // Save the array length.
3465 __ bind(&non_trivial_array); 3289 __ bind(&non_trivial_array);
3466 __ mov(array_length_operand, array_length); 3290 __ mov(array_length_operand, array_length);
3467 3291
3468 // Save the FixedArray containing array's elements. 3292 // Save the FixedArray containing array's elements.
3469 // End of array's live range. 3293 // End of array's live range.
3470 elements = array; 3294 elements = array;
3471 __ mov(elements, FieldOperand(array, JSArray::kElementsOffset)); 3295 __ mov(elements, FieldOperand(array, JSArray::kElementsOffset));
3472 array = no_reg; 3296 array = no_reg;
3473 3297
3474 3298
3475 // Check that all array elements are sequential ASCII strings, and 3299 // Check that all array elements are sequential ASCII strings, and
3476 // accumulate the sum of their lengths, as a smi-encoded value. 3300 // accumulate the sum of their lengths, as a smi-encoded value.
3477 __ Set(index, Immediate(0)); 3301 __ Set(index, Immediate(0));
3478 __ Set(string_length, Immediate(0)); 3302 __ Set(string_length, Immediate(0));
3479 // Loop condition: while (index < length). 3303 // Loop condition: while (index < length).
3480 // Live loop registers: index, array_length, string, 3304 // Live loop registers: index, array_length, string,
3481 // scratch, string_length, elements. 3305 // scratch, string_length, elements.
3482 __ jmp(&loop_condition); 3306 if (FLAG_debug_code) {
3307 __ cmp(index, Operand(array_length));
3308 __ Assert(less, "No empty arrays here in EmitFastAsciiArrayJoin");
3309 }
3483 __ bind(&loop); 3310 __ bind(&loop);
3484 __ cmp(index, Operand(array_length)); 3311 __ mov(string, FieldOperand(elements,
3485 __ j(greater_equal, &done); 3312 index,
3486 3313 times_pointer_size,
3487 __ mov(string, FieldOperand(elements, index, 3314 FixedArray::kHeaderSize));
3488 times_pointer_size,
3489 FixedArray::kHeaderSize));
3490 __ test(string, Immediate(kSmiTagMask)); 3315 __ test(string, Immediate(kSmiTagMask));
3491 __ j(zero, &bailout); 3316 __ j(zero, &bailout);
3492 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); 3317 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3493 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3318 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3494 __ and_(scratch, Immediate( 3319 __ and_(scratch, Immediate(
3495 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3320 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3496 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 3321 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag);
3497 __ j(not_equal, &bailout); 3322 __ j(not_equal, &bailout);
3498 __ add(string_length, 3323 __ add(string_length,
3499 FieldOperand(string, SeqAsciiString::kLengthOffset)); 3324 FieldOperand(string, SeqAsciiString::kLengthOffset));
3500 __ j(overflow, &bailout); 3325 __ j(overflow, &bailout);
3501 __ add(Operand(index), Immediate(1)); 3326 __ add(Operand(index), Immediate(1));
3502 __ bind(&loop_condition);
3503 __ cmp(index, Operand(array_length)); 3327 __ cmp(index, Operand(array_length));
3504 __ j(less, &loop); 3328 __ j(less, &loop);
3505 3329
3506 // If array_length is 1, return elements[0], a string. 3330 // If array_length is 1, return elements[0], a string.
3507 __ cmp(array_length, 1); 3331 __ cmp(array_length, 1);
3508 __ j(not_equal, &not_size_one_array); 3332 __ j(not_equal, &not_size_one_array);
3509 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize)); 3333 __ mov(scratch, FieldOperand(elements, FixedArray::kHeaderSize));
3510 __ mov(result_operand, scratch); 3334 __ mov(result_operand, scratch);
3511 __ jmp(&done); 3335 __ jmp(&done);
3512 3336
3513 __ bind(&not_size_one_array); 3337 __ bind(&not_size_one_array);
3514 3338
3515 // End of array_length live range. 3339 // End of array_length live range.
3516 result_pos = array_length; 3340 result_pos = array_length;
3517 array_length = no_reg; 3341 array_length = no_reg;
3518 3342
3519 // Live registers: 3343 // Live registers:
3520 // string_length: Sum of string lengths, as a smi. 3344 // string_length: Sum of string lengths, as a smi.
3521 // elements: FixedArray of strings. 3345 // elements: FixedArray of strings.
3522 3346
3523 // Check that the separator is a flat ASCII string. 3347 // Check that the separator is a flat ASCII string.
3524 __ mov(string, separator_operand); 3348 __ mov(string, separator_operand);
3525 __ test(string, Immediate(kSmiTagMask)); 3349 __ test(string, Immediate(kSmiTagMask));
3526 __ j(zero, &bailout); 3350 __ j(zero, &bailout);
3527 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset)); 3351 __ mov(scratch, FieldOperand(string, HeapObject::kMapOffset));
3528 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 3352 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
3529 __ and_(scratch, Immediate( 3353 __ and_(scratch, Immediate(
3530 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask)); 3354 kIsNotStringMask | kStringEncodingMask | kStringRepresentationMask));
3531 __ cmp(scratch, kStringTag | kAsciiStringTag | kSeqStringTag); 3355 __ cmp(scratch, ASCII_STRING_TYPE);
3532 __ j(not_equal, &bailout); 3356 __ j(not_equal, &bailout);
3533 3357
3534 // Add (separator length times array_length) - separator length 3358 // Add (separator length times array_length) - separator length
3535 // to string_length. 3359 // to string_length.
3536 __ mov(scratch, separator_operand); 3360 __ mov(scratch, separator_operand);
3537 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset)); 3361 __ mov(scratch, FieldOperand(scratch, SeqAsciiString::kLengthOffset));
3538 __ sub(string_length, Operand(scratch)); // May be negative, temporarily. 3362 __ sub(string_length, Operand(scratch)); // May be negative, temporarily.
3539 __ imul(scratch, array_length_operand); 3363 __ imul(scratch, array_length_operand);
3540 __ j(overflow, &bailout); 3364 __ j(overflow, &bailout);
3541 __ add(string_length, Operand(scratch)); 3365 __ add(string_length, Operand(scratch));
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
3733 context()->Plug(false); 3557 context()->Plug(false);
3734 } else { 3558 } else {
3735 VisitForStackValue(prop->obj()); 3559 VisitForStackValue(prop->obj());
3736 VisitForStackValue(prop->key()); 3560 VisitForStackValue(prop->key());
3737 __ push(Immediate(Smi::FromInt(strict_mode_flag()))); 3561 __ push(Immediate(Smi::FromInt(strict_mode_flag())));
3738 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3562 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3739 context()->Plug(eax); 3563 context()->Plug(eax);
3740 } 3564 }
3741 } else if (var != NULL) { 3565 } else if (var != NULL) {
3742 // Delete of an unqualified identifier is disallowed in strict mode 3566 // Delete of an unqualified identifier is disallowed in strict mode
3743 // so this code can only be reached in non-strict mode. 3567 // but "delete this" is.
3744 ASSERT(strict_mode_flag() == kNonStrictMode); 3568 ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this());
3745 if (var->is_global()) { 3569 if (var->is_global()) {
3746 __ push(GlobalObjectOperand()); 3570 __ push(GlobalObjectOperand());
3747 __ push(Immediate(var->name())); 3571 __ push(Immediate(var->name()));
3748 __ push(Immediate(Smi::FromInt(kNonStrictMode))); 3572 __ push(Immediate(Smi::FromInt(kNonStrictMode)));
3749 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); 3573 __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION);
3750 context()->Plug(eax); 3574 context()->Plug(eax);
3751 } else if (var->AsSlot() != NULL && 3575 } else if (var->AsSlot() != NULL &&
3752 var->AsSlot()->type() != Slot::LOOKUP) { 3576 var->AsSlot()->type() != Slot::LOOKUP) {
3753 // Result of deleting non-global, non-dynamic variables is false. 3577 // Result of deleting non-global, non-dynamic variables is false.
3754 // The subexpression does not have side effects. 3578 // The subexpression does not have side effects.
(...skipping 17 matching lines...) Expand all
3772 3596
3773 case Token::VOID: { 3597 case Token::VOID: {
3774 Comment cmnt(masm_, "[ UnaryOperation (VOID)"); 3598 Comment cmnt(masm_, "[ UnaryOperation (VOID)");
3775 VisitForEffect(expr->expression()); 3599 VisitForEffect(expr->expression());
3776 context()->Plug(Factory::undefined_value()); 3600 context()->Plug(Factory::undefined_value());
3777 break; 3601 break;
3778 } 3602 }
3779 3603
3780 case Token::NOT: { 3604 case Token::NOT: {
3781 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); 3605 Comment cmnt(masm_, "[ UnaryOperation (NOT)");
3606 if (context()->IsEffect()) {
3607 // Unary NOT has no side effects so it's only necessary to visit the
3608 // subexpression. Match the optimizing compiler by not branching.
3609 VisitForEffect(expr->expression());
3610 } else {
3611 Label materialize_true, materialize_false;
3612 Label* if_true = NULL;
3613 Label* if_false = NULL;
3614 Label* fall_through = NULL;
3782 3615
3783 Label materialize_true, materialize_false; 3616 // Notice that the labels are swapped.
3784 Label* if_true = NULL; 3617 context()->PrepareTest(&materialize_true, &materialize_false,
3785 Label* if_false = NULL; 3618 &if_false, &if_true, &fall_through);
3786 Label* fall_through = NULL; 3619 if (context()->IsTest()) ForwardBailoutToChild(expr);
3787 // Notice that the labels are swapped. 3620 VisitForControl(expr->expression(), if_true, if_false, fall_through);
3788 context()->PrepareTest(&materialize_true, &materialize_false, 3621 context()->Plug(if_false, if_true); // Labels swapped.
3789 &if_false, &if_true, &fall_through); 3622 }
3790 if (context()->IsTest()) ForwardBailoutToChild(expr);
3791 VisitForControl(expr->expression(), if_true, if_false, fall_through);
3792 context()->Plug(if_false, if_true); // Labels swapped.
3793 break; 3623 break;
3794 } 3624 }
3795 3625
3796 case Token::TYPEOF: { 3626 case Token::TYPEOF: {
3797 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); 3627 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)");
3798 { StackValueContext context(this); 3628 { StackValueContext context(this);
3799 VisitForTypeofValue(expr->expression()); 3629 VisitForTypeofValue(expr->expression());
3800 } 3630 }
3801 __ CallRuntime(Runtime::kTypeof, 1); 3631 __ CallRuntime(Runtime::kTypeof, 1);
3802 context()->Plug(eax); 3632 context()->Plug(eax);
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
4008 // Perform the assignment as if via '='. 3838 // Perform the assignment as if via '='.
4009 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 3839 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4010 Token::ASSIGN); 3840 Token::ASSIGN);
4011 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3841 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4012 context()->Plug(eax); 3842 context()->Plug(eax);
4013 } 3843 }
4014 break; 3844 break;
4015 case NAMED_PROPERTY: { 3845 case NAMED_PROPERTY: {
4016 __ mov(ecx, prop->key()->AsLiteral()->handle()); 3846 __ mov(ecx, prop->key()->AsLiteral()->handle());
4017 __ pop(edx); 3847 __ pop(edx);
4018 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize)); 3848 Handle<Code> ic(Builtins::builtin(
3849 is_strict_mode() ? Builtins::StoreIC_Initialize_Strict
3850 : Builtins::StoreIC_Initialize));
4019 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3851 EmitCallIC(ic, RelocInfo::CODE_TARGET);
4020 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3852 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4021 if (expr->is_postfix()) { 3853 if (expr->is_postfix()) {
4022 if (!context()->IsEffect()) { 3854 if (!context()->IsEffect()) {
4023 context()->PlugTOS(); 3855 context()->PlugTOS();
4024 } 3856 }
4025 } else { 3857 } else {
4026 context()->Plug(eax); 3858 context()->Plug(eax);
4027 } 3859 }
4028 break; 3860 break;
4029 } 3861 }
4030 case KEYED_PROPERTY: { 3862 case KEYED_PROPERTY: {
4031 __ pop(ecx); 3863 __ pop(ecx);
4032 __ pop(edx); 3864 __ pop(edx);
4033 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 3865 Handle<Code> ic(Builtins::builtin(
3866 is_strict_mode() ? Builtins::KeyedStoreIC_Initialize_Strict
3867 : Builtins::KeyedStoreIC_Initialize));
4034 EmitCallIC(ic, RelocInfo::CODE_TARGET); 3868 EmitCallIC(ic, RelocInfo::CODE_TARGET);
4035 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 3869 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4036 if (expr->is_postfix()) { 3870 if (expr->is_postfix()) {
4037 // Result is on the stack 3871 // Result is on the stack
4038 if (!context()->IsEffect()) { 3872 if (!context()->IsEffect()) {
4039 context()->PlugTOS(); 3873 context()->PlugTOS();
4040 } 3874 }
4041 } else { 3875 } else {
4042 context()->Plug(eax); 3876 context()->Plug(eax);
4043 } 3877 }
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
4103 UnaryOperation* left_unary = left->AsUnaryOperation(); 3937 UnaryOperation* left_unary = left->AsUnaryOperation();
4104 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false; 3938 if (left_unary == NULL || left_unary->op() != Token::TYPEOF) return false;
4105 Handle<String> check = Handle<String>::cast(right_literal_value); 3939 Handle<String> check = Handle<String>::cast(right_literal_value);
4106 3940
4107 { AccumulatorValueContext context(this); 3941 { AccumulatorValueContext context(this);
4108 VisitForTypeofValue(left_unary->expression()); 3942 VisitForTypeofValue(left_unary->expression());
4109 } 3943 }
4110 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); 3944 PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false);
4111 3945
4112 if (check->Equals(Heap::number_symbol())) { 3946 if (check->Equals(Heap::number_symbol())) {
4113 __ test(eax, Immediate(kSmiTagMask)); 3947 __ JumpIfSmi(eax, if_true);
4114 __ j(zero, if_true);
4115 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3948 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
4116 Factory::heap_number_map()); 3949 Factory::heap_number_map());
4117 Split(equal, if_true, if_false, fall_through); 3950 Split(equal, if_true, if_false, fall_through);
4118 } else if (check->Equals(Heap::string_symbol())) { 3951 } else if (check->Equals(Heap::string_symbol())) {
4119 __ test(eax, Immediate(kSmiTagMask)); 3952 __ JumpIfSmi(eax, if_false);
4120 __ j(zero, if_false); 3953 __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
3954 __ j(above_equal, if_false);
4121 // Check for undetectable objects => false. 3955 // Check for undetectable objects => false.
4122 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 3956 __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
4123 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 3957 1 << Map::kIsUndetectable);
4124 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 3958 Split(zero, if_true, if_false, fall_through);
4125 __ j(not_zero, if_false);
4126 __ CmpInstanceType(edx, FIRST_NONSTRING_TYPE);
4127 Split(below, if_true, if_false, fall_through);
4128 } else if (check->Equals(Heap::boolean_symbol())) { 3959 } else if (check->Equals(Heap::boolean_symbol())) {
4129 __ cmp(eax, Factory::true_value()); 3960 __ cmp(eax, Factory::true_value());
4130 __ j(equal, if_true); 3961 __ j(equal, if_true);
4131 __ cmp(eax, Factory::false_value()); 3962 __ cmp(eax, Factory::false_value());
4132 Split(equal, if_true, if_false, fall_through); 3963 Split(equal, if_true, if_false, fall_through);
4133 } else if (check->Equals(Heap::undefined_symbol())) { 3964 } else if (check->Equals(Heap::undefined_symbol())) {
4134 __ cmp(eax, Factory::undefined_value()); 3965 __ cmp(eax, Factory::undefined_value());
4135 __ j(equal, if_true); 3966 __ j(equal, if_true);
4136 __ test(eax, Immediate(kSmiTagMask)); 3967 __ JumpIfSmi(eax, if_false);
4137 __ j(zero, if_false);
4138 // Check for undetectable objects => true. 3968 // Check for undetectable objects => true.
4139 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset)); 3969 __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
4140 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 3970 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
4141 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 3971 __ test(ecx, Immediate(1 << Map::kIsUndetectable));
4142 Split(not_zero, if_true, if_false, fall_through); 3972 Split(not_zero, if_true, if_false, fall_through);
4143 } else if (check->Equals(Heap::function_symbol())) { 3973 } else if (check->Equals(Heap::function_symbol())) {
4144 __ test(eax, Immediate(kSmiTagMask)); 3974 __ JumpIfSmi(eax, if_false);
4145 __ j(zero, if_false); 3975 __ CmpObjectType(eax, FIRST_FUNCTION_CLASS_TYPE, edx);
4146 __ CmpObjectType(eax, JS_FUNCTION_TYPE, edx); 3976 Split(above_equal, if_true, if_false, fall_through);
4147 __ j(equal, if_true);
4148 // Regular expressions => 'function' (they are callable).
4149 __ CmpInstanceType(edx, JS_REGEXP_TYPE);
4150 Split(equal, if_true, if_false, fall_through);
4151 } else if (check->Equals(Heap::object_symbol())) { 3977 } else if (check->Equals(Heap::object_symbol())) {
4152 __ test(eax, Immediate(kSmiTagMask)); 3978 __ JumpIfSmi(eax, if_false);
4153 __ j(zero, if_false);
4154 __ cmp(eax, Factory::null_value()); 3979 __ cmp(eax, Factory::null_value());
4155 __ j(equal, if_true); 3980 __ j(equal, if_true);
4156 // Regular expressions => 'function', not 'object'. 3981 __ CmpObjectType(eax, FIRST_JS_OBJECT_TYPE, edx);
4157 __ CmpObjectType(eax, JS_REGEXP_TYPE, edx); 3982 __ j(below, if_false);
4158 __ j(equal, if_false); 3983 __ CmpInstanceType(edx, FIRST_FUNCTION_CLASS_TYPE);
3984 __ j(above_equal, if_false);
4159 // Check for undetectable objects => false. 3985 // Check for undetectable objects => false.
4160 __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); 3986 __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
4161 __ test(ecx, Immediate(1 << Map::kIsUndetectable)); 3987 1 << Map::kIsUndetectable);
4162 __ j(not_zero, if_false); 3988 Split(zero, if_true, if_false, fall_through);
4163 // Check for JS objects => true.
4164 __ movzx_b(ecx, FieldOperand(edx, Map::kInstanceTypeOffset));
4165 __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
4166 __ j(less, if_false);
4167 __ cmp(ecx, LAST_JS_OBJECT_TYPE);
4168 Split(less_equal, if_true, if_false, fall_through);
4169 } else { 3989 } else {
4170 if (if_false != fall_through) __ jmp(if_false); 3990 if (if_false != fall_through) __ jmp(if_false);
4171 } 3991 }
4172 3992
4173 return true; 3993 return true;
4174 } 3994 }
4175 3995
4176 3996
4177 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { 3997 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
4178 Comment cmnt(masm_, "[ CompareOperation"); 3998 Comment cmnt(masm_, "[ CompareOperation");
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
4371 __ nop(); // Signals no inlined code. 4191 __ nop(); // Signals no inlined code.
4372 break; 4192 break;
4373 default: 4193 default:
4374 // Do nothing. 4194 // Do nothing.
4375 break; 4195 break;
4376 } 4196 }
4377 } 4197 }
4378 4198
4379 4199
4380 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { 4200 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) {
4201 switch (ic->kind()) {
4202 case Code::LOAD_IC:
4203 __ IncrementCounter(&Counters::named_load_full, 1);
4204 break;
4205 case Code::KEYED_LOAD_IC:
4206 __ IncrementCounter(&Counters::keyed_load_full, 1);
4207 break;
4208 case Code::STORE_IC:
4209 __ IncrementCounter(&Counters::named_store_full, 1);
4210 break;
4211 case Code::KEYED_STORE_IC:
4212 __ IncrementCounter(&Counters::keyed_store_full, 1);
4213 default:
4214 break;
4215 }
4216
4381 __ call(ic, RelocInfo::CODE_TARGET); 4217 __ call(ic, RelocInfo::CODE_TARGET);
4382 if (patch_site != NULL && patch_site->is_bound()) { 4218 if (patch_site != NULL && patch_site->is_bound()) {
4383 patch_site->EmitPatchInfo(); 4219 patch_site->EmitPatchInfo();
4384 } else { 4220 } else {
4385 __ nop(); // Signals no inlined code. 4221 __ nop(); // Signals no inlined code.
4386 } 4222 }
4387 } 4223 }
4388 4224
4389 4225
4390 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { 4226 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
4427 // And return. 4263 // And return.
4428 __ ret(0); 4264 __ ret(0);
4429 } 4265 }
4430 4266
4431 4267
4432 #undef __ 4268 #undef __
4433 4269
4434 } } // namespace v8::internal 4270 } } // namespace v8::internal
4435 4271
4436 #endif // V8_TARGET_ARCH_IA32 4272 #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