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

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

Issue 157543002: A64: Synchronize with r18581. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/a64
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/frames-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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 126
127 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 127 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
128 128
129 #ifdef DEBUG 129 #ifdef DEBUG
130 if (strlen(FLAG_stop_at) > 0 && 130 if (strlen(FLAG_stop_at) > 0 &&
131 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 131 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
132 __ int3(); 132 __ int3();
133 } 133 }
134 #endif 134 #endif
135 135
136 // Strict mode functions and builtins need to replace the receiver 136 // Classic mode functions and builtins need to replace the receiver with the
137 // with undefined when called as functions (without an explicit 137 // global proxy when called as functions (without an explicit receiver
138 // receiver object). ecx is zero for method calls and non-zero for 138 // object).
139 // function calls. 139 if (info->is_classic_mode() && !info->is_native()) {
140 if (!info->is_classic_mode() || info->is_native()) {
141 Label ok; 140 Label ok;
142 __ test(ecx, ecx); 141 __ test(ecx, ecx);
143 __ j(zero, &ok, Label::kNear); 142 __ j(zero, &ok, Label::kNear);
143
144 // +1 for return address. 144 // +1 for return address.
145 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize; 145 int receiver_offset = (info->scope()->num_parameters() + 1) * kPointerSize;
146 __ mov(ecx, Operand(esp, receiver_offset)); 146 __ mov(ecx, Operand(esp, receiver_offset));
147 __ JumpIfSmi(ecx, &ok); 147
148 __ CmpObjectType(ecx, JS_GLOBAL_PROXY_TYPE, ecx); 148 __ cmp(ecx, isolate()->factory()->undefined_value());
149 __ j(not_equal, &ok, Label::kNear); 149 __ j(not_equal, &ok, Label::kNear);
150 __ mov(Operand(esp, receiver_offset), 150
151 Immediate(isolate()->factory()->undefined_value())); 151 __ mov(ecx, GlobalObjectOperand());
152 __ mov(ecx, FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
153
154 __ mov(Operand(esp, receiver_offset), ecx);
155
152 __ bind(&ok); 156 __ bind(&ok);
153 } 157 }
154 158
155 // Open a frame scope to indicate that there is a frame on the stack. The 159 // Open a frame scope to indicate that there is a frame on the stack. The
156 // MANUAL indicates that the scope shouldn't actually generate code to set up 160 // MANUAL indicates that the scope shouldn't actually generate code to set up
157 // the frame (that is done below). 161 // the frame (that is done below).
158 FrameScope frame_scope(masm_, StackFrame::MANUAL); 162 FrameScope frame_scope(masm_, StackFrame::MANUAL);
159 163
160 info->set_prologue_offset(masm_->pc_offset()); 164 info->set_prologue_offset(masm_->pc_offset());
161 __ Prologue(BUILD_FUNCTION_FRAME); 165 __ Prologue(BUILD_FUNCTION_FRAME);
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 if (false_label_ != fall_through_) __ jmp(false_label_); 621 if (false_label_ != fall_through_) __ jmp(false_label_);
618 } 622 }
619 } 623 }
620 624
621 625
622 void FullCodeGenerator::DoTest(Expression* condition, 626 void FullCodeGenerator::DoTest(Expression* condition,
623 Label* if_true, 627 Label* if_true,
624 Label* if_false, 628 Label* if_false,
625 Label* fall_through) { 629 Label* fall_through) {
626 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); 630 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
627 CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); 631 CallIC(ic, NOT_CONTEXTUAL, condition->test_id());
628 __ test(result_register(), result_register()); 632 __ test(result_register(), result_register());
629 // The stub returns nonzero for true. 633 // The stub returns nonzero for true.
630 Split(not_zero, if_true, if_false, fall_through); 634 Split(not_zero, if_true, if_false, fall_through);
631 } 635 }
632 636
633 637
634 void FullCodeGenerator::Split(Condition cc, 638 void FullCodeGenerator::Split(Condition cc,
635 Label* if_true, 639 Label* if_true,
636 Label* if_false, 640 Label* if_false,
637 Label* fall_through) { 641 Label* fall_through) {
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 __ cmp(edx, eax); 972 __ cmp(edx, eax);
969 __ j(not_equal, &next_test); 973 __ j(not_equal, &next_test);
970 __ Drop(1); // Switch value is no longer needed. 974 __ Drop(1); // Switch value is no longer needed.
971 __ jmp(clause->body_target()); 975 __ jmp(clause->body_target());
972 __ bind(&slow_case); 976 __ bind(&slow_case);
973 } 977 }
974 978
975 // Record position before stub call for type feedback. 979 // Record position before stub call for type feedback.
976 SetSourcePosition(clause->position()); 980 SetSourcePosition(clause->position());
977 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); 981 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
978 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); 982 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId());
979 patch_site.EmitPatchInfo(); 983 patch_site.EmitPatchInfo();
980 984
981 Label skip; 985 Label skip;
982 __ jmp(&skip, Label::kNear); 986 __ jmp(&skip, Label::kNear);
983 PrepareForBailout(clause, TOS_REG); 987 PrepareForBailout(clause, TOS_REG);
984 __ cmp(eax, isolate()->factory()->true_value()); 988 __ cmp(eax, isolate()->factory()->true_value());
985 __ j(not_equal, &next_test); 989 __ j(not_equal, &next_test);
986 __ Drop(1); 990 __ Drop(1);
987 __ jmp(clause->body_target()); 991 __ jmp(clause->body_target());
988 __ bind(&skip); 992 __ bind(&skip);
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 // Load next context in chain. 1328 // Load next context in chain.
1325 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); 1329 __ mov(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
1326 __ jmp(&next); 1330 __ jmp(&next);
1327 __ bind(&fast); 1331 __ bind(&fast);
1328 } 1332 }
1329 1333
1330 // All extension objects were empty and it is safe to use a global 1334 // All extension objects were empty and it is safe to use a global
1331 // load IC call. 1335 // load IC call.
1332 __ mov(edx, GlobalObjectOperand()); 1336 __ mov(edx, GlobalObjectOperand());
1333 __ mov(ecx, var->name()); 1337 __ mov(ecx, var->name());
1334 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1338 ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
1335 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 1339 ? NOT_CONTEXTUAL
1336 ? RelocInfo::CODE_TARGET 1340 : CONTEXTUAL;
1337 : RelocInfo::CODE_TARGET_CONTEXT; 1341
1338 CallIC(ic, mode); 1342 CallLoadIC(mode);
1339 } 1343 }
1340 1344
1341 1345
1342 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1346 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1343 Label* slow) { 1347 Label* slow) {
1344 ASSERT(var->IsContextSlot()); 1348 ASSERT(var->IsContextSlot());
1345 Register context = esi; 1349 Register context = esi;
1346 Register temp = ebx; 1350 Register temp = ebx;
1347 1351
1348 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 1352 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1408 1412
1409 // Three cases: global variables, lookup variables, and all other types of 1413 // Three cases: global variables, lookup variables, and all other types of
1410 // variables. 1414 // variables.
1411 switch (var->location()) { 1415 switch (var->location()) {
1412 case Variable::UNALLOCATED: { 1416 case Variable::UNALLOCATED: {
1413 Comment cmnt(masm_, "Global variable"); 1417 Comment cmnt(masm_, "Global variable");
1414 // Use inline caching. Variable name is passed in ecx and the global 1418 // Use inline caching. Variable name is passed in ecx and the global
1415 // object in eax. 1419 // object in eax.
1416 __ mov(edx, GlobalObjectOperand()); 1420 __ mov(edx, GlobalObjectOperand());
1417 __ mov(ecx, var->name()); 1421 __ mov(ecx, var->name());
1418 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1422 CallLoadIC(CONTEXTUAL);
1419 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
1420 context()->Plug(eax); 1423 context()->Plug(eax);
1421 break; 1424 break;
1422 } 1425 }
1423 1426
1424 case Variable::PARAMETER: 1427 case Variable::PARAMETER:
1425 case Variable::LOCAL: 1428 case Variable::LOCAL:
1426 case Variable::CONTEXT: { 1429 case Variable::CONTEXT: {
1427 Comment cmnt(masm_, var->IsContextSlot() 1430 Comment cmnt(masm_, var->IsContextSlot()
1428 ? "Context variable" 1431 ? "Context variable"
1429 : "Stack variable"); 1432 : "Stack variable");
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 UNREACHABLE(); 1628 UNREACHABLE();
1626 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1629 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1627 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1630 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1628 // Fall through. 1631 // Fall through.
1629 case ObjectLiteral::Property::COMPUTED: 1632 case ObjectLiteral::Property::COMPUTED:
1630 if (key->value()->IsInternalizedString()) { 1633 if (key->value()->IsInternalizedString()) {
1631 if (property->emit_store()) { 1634 if (property->emit_store()) {
1632 VisitForAccumulatorValue(value); 1635 VisitForAccumulatorValue(value);
1633 __ mov(ecx, Immediate(key->value())); 1636 __ mov(ecx, Immediate(key->value()));
1634 __ mov(edx, Operand(esp, 0)); 1637 __ mov(edx, Operand(esp, 0));
1635 Handle<Code> ic = is_classic_mode() 1638 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId());
1636 ? isolate()->builtins()->StoreIC_Initialize()
1637 : isolate()->builtins()->StoreIC_Initialize_Strict();
1638 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId());
1639 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1639 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1640 } else { 1640 } else {
1641 VisitForEffect(value); 1641 VisitForEffect(value);
1642 } 1642 }
1643 break; 1643 break;
1644 } 1644 }
1645 __ push(Operand(esp, 0)); // Duplicate receiver. 1645 __ push(Operand(esp, 0)); // Duplicate receiver.
1646 VisitForStackValue(key); 1646 VisitForStackValue(key);
1647 VisitForStackValue(value); 1647 VisitForStackValue(value);
1648 if (property->emit_store()) { 1648 if (property->emit_store()) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1709 int length = subexprs->length(); 1709 int length = subexprs->length();
1710 Handle<FixedArray> constant_elements = expr->constant_elements(); 1710 Handle<FixedArray> constant_elements = expr->constant_elements();
1711 ASSERT_EQ(2, constant_elements->length()); 1711 ASSERT_EQ(2, constant_elements->length());
1712 ElementsKind constant_elements_kind = 1712 ElementsKind constant_elements_kind =
1713 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 1713 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1714 bool has_constant_fast_elements = 1714 bool has_constant_fast_elements =
1715 IsFastObjectElementsKind(constant_elements_kind); 1715 IsFastObjectElementsKind(constant_elements_kind);
1716 Handle<FixedArrayBase> constant_elements_values( 1716 Handle<FixedArrayBase> constant_elements_values(
1717 FixedArrayBase::cast(constant_elements->get(1))); 1717 FixedArrayBase::cast(constant_elements->get(1)));
1718 1718
1719 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites 1719 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1720 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE;
1721 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { 1720 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1722 // If the only customer of allocation sites is transitioning, then 1721 // If the only customer of allocation sites is transitioning, then
1723 // we can turn it off if we don't have anywhere else to transition to. 1722 // we can turn it off if we don't have anywhere else to transition to.
1724 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; 1723 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1725 } 1724 }
1726 1725
1727 Heap* heap = isolate()->heap(); 1726 Heap* heap = isolate()->heap();
1728 if (has_constant_fast_elements && 1727 if (has_constant_fast_elements &&
1729 constant_elements_values->map() == heap->fixed_cow_array_map()) { 1728 constant_elements_values->map() == heap->fixed_cow_array_map()) {
1730 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot 1729 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
2051 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); 2050 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1);
2052 CallIC(ic); 2051 CallIC(ic);
2053 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2052 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2054 __ Drop(1); // The key is still on the stack; drop it. 2053 __ Drop(1); // The key is still on the stack; drop it.
2055 2054
2056 // if (!result.done) goto l_try; 2055 // if (!result.done) goto l_try;
2057 __ bind(&l_loop); 2056 __ bind(&l_loop);
2058 __ push(eax); // save result 2057 __ push(eax); // save result
2059 __ mov(edx, eax); // result 2058 __ mov(edx, eax); // result
2060 __ mov(ecx, isolate()->factory()->done_string()); // "done" 2059 __ mov(ecx, isolate()->factory()->done_string()); // "done"
2061 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); 2060 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
2062 CallIC(done_ic); // result.done in eax
2063 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2061 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2064 CallIC(bool_ic); 2062 CallIC(bool_ic);
2065 __ test(eax, eax); 2063 __ test(eax, eax);
2066 __ j(zero, &l_try); 2064 __ j(zero, &l_try);
2067 2065
2068 // result.value 2066 // result.value
2069 __ pop(edx); // result 2067 __ pop(edx); // result
2070 __ mov(ecx, isolate()->factory()->value_string()); // "value" 2068 __ mov(ecx, isolate()->factory()->value_string()); // "value"
2071 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); 2069 CallLoadIC(NOT_CONTEXTUAL); // result.value in eax
2072 CallIC(value_ic); // result.value in eax 2070 context()->DropAndPlug(2, eax); // drop iter and g
2073 context()->DropAndPlug(2, eax); // drop iter and g
2074 break; 2071 break;
2075 } 2072 }
2076 } 2073 }
2077 } 2074 }
2078 2075
2079 2076
2080 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, 2077 void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2081 Expression *value, 2078 Expression *value,
2082 JSGeneratorObject::ResumeMode resume_mode) { 2079 JSGeneratorObject::ResumeMode resume_mode) {
2083 // The value stays in eax, and is ultimately read by the resumed generator, as 2080 // The value stays in eax, and is ultimately read by the resumed generator, as
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
2206 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset, 2203 __ RecordWriteField(eax, JSGeneratorObject::kResultValuePropertyOffset,
2207 ecx, edx, kDontSaveFPRegs); 2204 ecx, edx, kDontSaveFPRegs);
2208 } 2205 }
2209 2206
2210 2207
2211 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2208 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2212 SetSourcePosition(prop->position()); 2209 SetSourcePosition(prop->position());
2213 Literal* key = prop->key()->AsLiteral(); 2210 Literal* key = prop->key()->AsLiteral();
2214 ASSERT(!key->value()->IsSmi()); 2211 ASSERT(!key->value()->IsSmi());
2215 __ mov(ecx, Immediate(key->value())); 2212 __ mov(ecx, Immediate(key->value()));
2216 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2213 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2217 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
2218 } 2214 }
2219 2215
2220 2216
2221 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 2217 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2222 SetSourcePosition(prop->position()); 2218 SetSourcePosition(prop->position());
2223 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2219 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2224 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); 2220 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2225 } 2221 }
2226 2222
2227 2223
2228 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2224 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2229 Token::Value op, 2225 Token::Value op,
2230 OverwriteMode mode, 2226 OverwriteMode mode,
2231 Expression* left, 2227 Expression* left,
2232 Expression* right) { 2228 Expression* right) {
2233 // Do combined smi check of the operands. Left operand is on the 2229 // Do combined smi check of the operands. Left operand is on the
2234 // stack. Right operand is in eax. 2230 // stack. Right operand is in eax.
2235 Label smi_case, done, stub_call; 2231 Label smi_case, done, stub_call;
2236 __ pop(edx); 2232 __ pop(edx);
2237 __ mov(ecx, eax); 2233 __ mov(ecx, eax);
2238 __ or_(eax, edx); 2234 __ or_(eax, edx);
2239 JumpPatchSite patch_site(masm_); 2235 JumpPatchSite patch_site(masm_);
2240 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); 2236 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
2241 2237
2242 __ bind(&stub_call); 2238 __ bind(&stub_call);
2243 __ mov(eax, ecx); 2239 __ mov(eax, ecx);
2244 BinaryOpICStub stub(op, mode); 2240 BinaryOpICStub stub(op, mode);
2245 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2241 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
2246 expr->BinaryOperationFeedbackId()); 2242 expr->BinaryOperationFeedbackId());
2247 patch_site.EmitPatchInfo(); 2243 patch_site.EmitPatchInfo();
2248 __ jmp(&done, Label::kNear); 2244 __ jmp(&done, Label::kNear);
2249 2245
2250 // Smi case. 2246 // Smi case.
2251 __ bind(&smi_case); 2247 __ bind(&smi_case);
2252 __ mov(eax, edx); // Copy left operand in case of a stub call. 2248 __ mov(eax, edx); // Copy left operand in case of a stub call.
2253 2249
2254 switch (op) { 2250 switch (op) {
2255 case Token::SAR: 2251 case Token::SAR:
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2321 context()->Plug(eax); 2317 context()->Plug(eax);
2322 } 2318 }
2323 2319
2324 2320
2325 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2321 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2326 Token::Value op, 2322 Token::Value op,
2327 OverwriteMode mode) { 2323 OverwriteMode mode) {
2328 __ pop(edx); 2324 __ pop(edx);
2329 BinaryOpICStub stub(op, mode); 2325 BinaryOpICStub stub(op, mode);
2330 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2326 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
2331 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2327 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
2332 expr->BinaryOperationFeedbackId()); 2328 expr->BinaryOperationFeedbackId());
2333 patch_site.EmitPatchInfo(); 2329 patch_site.EmitPatchInfo();
2334 context()->Plug(eax); 2330 context()->Plug(eax);
2335 } 2331 }
2336 2332
2337 2333
2338 void FullCodeGenerator::EmitAssignment(Expression* expr) { 2334 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2339 // Invalid left-hand sides are rewritten by the parser to have a 'throw 2335 // Invalid left-hand sides are rewritten by the parser to have a 'throw
2340 // ReferenceError' on the left-hand side. 2336 // ReferenceError' on the left-hand side.
2341 if (!expr->IsValidLeftHandSide()) { 2337 if (!expr->IsValidLeftHandSide()) {
(...skipping 18 matching lines...) Expand all
2360 EffectContext context(this); 2356 EffectContext context(this);
2361 EmitVariableAssignment(var, Token::ASSIGN); 2357 EmitVariableAssignment(var, Token::ASSIGN);
2362 break; 2358 break;
2363 } 2359 }
2364 case NAMED_PROPERTY: { 2360 case NAMED_PROPERTY: {
2365 __ push(eax); // Preserve value. 2361 __ push(eax); // Preserve value.
2366 VisitForAccumulatorValue(prop->obj()); 2362 VisitForAccumulatorValue(prop->obj());
2367 __ mov(edx, eax); 2363 __ mov(edx, eax);
2368 __ pop(eax); // Restore value. 2364 __ pop(eax); // Restore value.
2369 __ mov(ecx, prop->key()->AsLiteral()->value()); 2365 __ mov(ecx, prop->key()->AsLiteral()->value());
2370 Handle<Code> ic = is_classic_mode() 2366 CallStoreIC(NOT_CONTEXTUAL);
2371 ? isolate()->builtins()->StoreIC_Initialize()
2372 : isolate()->builtins()->StoreIC_Initialize_Strict();
2373 CallIC(ic);
2374 break; 2367 break;
2375 } 2368 }
2376 case KEYED_PROPERTY: { 2369 case KEYED_PROPERTY: {
2377 __ push(eax); // Preserve value. 2370 __ push(eax); // Preserve value.
2378 VisitForStackValue(prop->obj()); 2371 VisitForStackValue(prop->obj());
2379 VisitForAccumulatorValue(prop->key()); 2372 VisitForAccumulatorValue(prop->key());
2380 __ mov(ecx, eax); 2373 __ mov(ecx, eax);
2381 __ pop(edx); // Receiver. 2374 __ pop(edx); // Receiver.
2382 __ pop(eax); // Restore value. 2375 __ pop(eax); // Restore value.
2383 Handle<Code> ic = is_classic_mode() 2376 Handle<Code> ic = is_classic_mode()
2384 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2377 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2385 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2378 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2386 CallIC(ic); 2379 CallIC(ic);
2387 break; 2380 break;
2388 } 2381 }
2389 } 2382 }
2390 context()->Plug(eax); 2383 context()->Plug(eax);
2391 } 2384 }
2392 2385
2393 2386
2394 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2387 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2395 Token::Value op) { 2388 Token::Value op) {
2396 if (var->IsUnallocated()) { 2389 if (var->IsUnallocated()) {
2397 // Global var, const, or let. 2390 // Global var, const, or let.
2398 __ mov(ecx, var->name()); 2391 __ mov(ecx, var->name());
2399 __ mov(edx, GlobalObjectOperand()); 2392 __ mov(edx, GlobalObjectOperand());
2400 Handle<Code> ic = is_classic_mode() 2393 CallStoreIC(CONTEXTUAL);
2401 ? isolate()->builtins()->StoreIC_Initialize()
2402 : isolate()->builtins()->StoreIC_Initialize_Strict();
2403 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
2404
2405 } else if (op == Token::INIT_CONST) { 2394 } else if (op == Token::INIT_CONST) {
2406 // Const initializers need a write barrier. 2395 // Const initializers need a write barrier.
2407 ASSERT(!var->IsParameter()); // No const parameters. 2396 ASSERT(!var->IsParameter()); // No const parameters.
2408 if (var->IsStackLocal()) { 2397 if (var->IsStackLocal()) {
2409 Label skip; 2398 Label skip;
2410 __ mov(edx, StackOperand(var)); 2399 __ mov(edx, StackOperand(var));
2411 __ cmp(edx, isolate()->factory()->the_hole_value()); 2400 __ cmp(edx, isolate()->factory()->the_hole_value());
2412 __ j(not_equal, &skip); 2401 __ j(not_equal, &skip);
2413 __ mov(StackOperand(var), eax); 2402 __ mov(StackOperand(var), eax);
2414 __ bind(&skip); 2403 __ bind(&skip);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2488 // esp[0] : receiver 2477 // esp[0] : receiver
2489 2478
2490 Property* prop = expr->target()->AsProperty(); 2479 Property* prop = expr->target()->AsProperty();
2491 ASSERT(prop != NULL); 2480 ASSERT(prop != NULL);
2492 ASSERT(prop->key()->AsLiteral() != NULL); 2481 ASSERT(prop->key()->AsLiteral() != NULL);
2493 2482
2494 // Record source code position before IC call. 2483 // Record source code position before IC call.
2495 SetSourcePosition(expr->position()); 2484 SetSourcePosition(expr->position());
2496 __ mov(ecx, prop->key()->AsLiteral()->value()); 2485 __ mov(ecx, prop->key()->AsLiteral()->value());
2497 __ pop(edx); 2486 __ pop(edx);
2498 Handle<Code> ic = is_classic_mode() 2487 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
2499 ? isolate()->builtins()->StoreIC_Initialize()
2500 : isolate()->builtins()->StoreIC_Initialize_Strict();
2501 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
2502
2503 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2488 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2504 context()->Plug(eax); 2489 context()->Plug(eax);
2505 } 2490 }
2506 2491
2507 2492
2508 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2493 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2509 // Assignment to a property, using a keyed store IC. 2494 // Assignment to a property, using a keyed store IC.
2510 // eax : value 2495 // eax : value
2511 // esp[0] : key 2496 // esp[0] : key
2512 // esp[kPointerSize] : receiver 2497 // esp[kPointerSize] : receiver
2513 2498
2514 __ pop(ecx); // Key. 2499 __ pop(ecx); // Key.
2515 __ pop(edx); 2500 __ pop(edx);
2516 // Record source code position before IC call. 2501 // Record source code position before IC call.
2517 SetSourcePosition(expr->position()); 2502 SetSourcePosition(expr->position());
2518 Handle<Code> ic = is_classic_mode() 2503 Handle<Code> ic = is_classic_mode()
2519 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2504 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2520 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2505 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2521 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); 2506 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
2522 2507
2523 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2508 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2524 context()->Plug(eax); 2509 context()->Plug(eax);
2525 } 2510 }
2526 2511
2527 2512
2528 void FullCodeGenerator::VisitProperty(Property* expr) { 2513 void FullCodeGenerator::VisitProperty(Property* expr) {
2529 Comment cmnt(masm_, "[ Property"); 2514 Comment cmnt(masm_, "[ Property");
2530 Expression* key = expr->key(); 2515 Expression* key = expr->key();
2531 2516
2532 if (key->IsPropertyName()) { 2517 if (key->IsPropertyName()) {
2533 VisitForAccumulatorValue(expr->obj()); 2518 VisitForAccumulatorValue(expr->obj());
2534 __ mov(edx, result_register()); 2519 __ mov(edx, result_register());
2535 EmitNamedPropertyLoad(expr); 2520 EmitNamedPropertyLoad(expr);
2536 PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2521 PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2537 context()->Plug(eax); 2522 context()->Plug(eax);
2538 } else { 2523 } else {
2539 VisitForStackValue(expr->obj()); 2524 VisitForStackValue(expr->obj());
2540 VisitForAccumulatorValue(expr->key()); 2525 VisitForAccumulatorValue(expr->key());
2541 __ pop(edx); // Object. 2526 __ pop(edx); // Object.
2542 __ mov(ecx, result_register()); // Key. 2527 __ mov(ecx, result_register()); // Key.
2543 EmitKeyedPropertyLoad(expr); 2528 EmitKeyedPropertyLoad(expr);
2544 context()->Plug(eax); 2529 context()->Plug(eax);
2545 } 2530 }
2546 } 2531 }
2547 2532
2548 2533
2549 void FullCodeGenerator::CallIC(Handle<Code> code, 2534 void FullCodeGenerator::CallIC(Handle<Code> code,
2550 RelocInfo::Mode rmode, 2535 ContextualMode mode,
2551 TypeFeedbackId ast_id) { 2536 TypeFeedbackId ast_id) {
2552 ic_total_count_++; 2537 ic_total_count_++;
2553 __ call(code, rmode, ast_id); 2538 ASSERT(mode != CONTEXTUAL || ast_id.IsNone());
2539 __ call(code, RelocInfo::CODE_TARGET, ast_id);
2554 } 2540 }
2555 2541
2556 2542
2557 2543
2558 2544
2559 void FullCodeGenerator::EmitCallWithIC(Call* expr, 2545 void FullCodeGenerator::EmitCallWithIC(Call* expr,
2560 Handle<Object> name, 2546 Handle<Object> name,
2561 RelocInfo::Mode mode) { 2547 ContextualMode mode) {
2562 // Code common for calls using the IC. 2548 // Code common for calls using the IC.
2563 ZoneList<Expression*>* args = expr->arguments(); 2549 ZoneList<Expression*>* args = expr->arguments();
2564 int arg_count = args->length(); 2550 int arg_count = args->length();
2565 { PreservePositionScope scope(masm()->positions_recorder()); 2551 { PreservePositionScope scope(masm()->positions_recorder());
2566 for (int i = 0; i < arg_count; i++) { 2552 for (int i = 0; i < arg_count; i++) {
2567 VisitForStackValue(args->at(i)); 2553 VisitForStackValue(args->at(i));
2568 } 2554 }
2569 __ Set(ecx, Immediate(name)); 2555 __ Set(ecx, Immediate(name));
2570 } 2556 }
2571 // Record source position of the IC call. 2557 // Record source position of the IC call.
2572 SetSourcePosition(expr->position()); 2558 SetSourcePosition(expr->position());
2573 Handle<Code> ic = 2559 Handle<Code> ic =
2574 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); 2560 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
2575 CallIC(ic, mode, expr->CallFeedbackId()); 2561 TypeFeedbackId ast_id = mode == CONTEXTUAL
2562 ? TypeFeedbackId::None()
2563 : expr->CallFeedbackId();
2564 CallIC(ic, mode, ast_id);
2576 RecordJSReturnSite(expr); 2565 RecordJSReturnSite(expr);
2577 // Restore context register. 2566 // Restore context register.
2578 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2567 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2579 context()->Plug(eax); 2568 context()->Plug(eax);
2580 } 2569 }
2581 2570
2582 2571
2583 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2572 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2584 Expression* key) { 2573 Expression* key) {
2585 // Load the key. 2574 // Load the key.
(...skipping 11 matching lines...) Expand all
2597 { PreservePositionScope scope(masm()->positions_recorder()); 2586 { PreservePositionScope scope(masm()->positions_recorder());
2598 for (int i = 0; i < arg_count; i++) { 2587 for (int i = 0; i < arg_count; i++) {
2599 VisitForStackValue(args->at(i)); 2588 VisitForStackValue(args->at(i));
2600 } 2589 }
2601 } 2590 }
2602 // Record source position of the IC call. 2591 // Record source position of the IC call.
2603 SetSourcePosition(expr->position()); 2592 SetSourcePosition(expr->position());
2604 Handle<Code> ic = 2593 Handle<Code> ic =
2605 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); 2594 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
2606 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. 2595 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key.
2607 CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); 2596 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId());
2608 RecordJSReturnSite(expr); 2597 RecordJSReturnSite(expr);
2609 // Restore context register. 2598 // Restore context register.
2610 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2599 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2611 context()->DropAndPlug(1, eax); // Drop the key still on the stack. 2600 context()->DropAndPlug(1, eax); // Drop the key still on the stack.
2612 } 2601 }
2613 2602
2614 2603
2615 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { 2604 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2616 // Code common for calls using the call stub. 2605 // Code common for calls using the call stub.
2617 ZoneList<Expression*>* args = expr->arguments(); 2606 ZoneList<Expression*>* args = expr->arguments();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2696 __ push(Operand(esp, (arg_count + 1) * kPointerSize)); 2685 __ push(Operand(esp, (arg_count + 1) * kPointerSize));
2697 EmitResolvePossiblyDirectEval(arg_count); 2686 EmitResolvePossiblyDirectEval(arg_count);
2698 2687
2699 // The runtime call returns a pair of values in eax (function) and 2688 // The runtime call returns a pair of values in eax (function) and
2700 // edx (receiver). Touch up the stack with the right values. 2689 // edx (receiver). Touch up the stack with the right values.
2701 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx); 2690 __ mov(Operand(esp, (arg_count + 0) * kPointerSize), edx);
2702 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax); 2691 __ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
2703 } 2692 }
2704 // Record source position for debugger. 2693 // Record source position for debugger.
2705 SetSourcePosition(expr->position()); 2694 SetSourcePosition(expr->position());
2706 CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT); 2695 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
2707 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2696 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2708 __ CallStub(&stub); 2697 __ CallStub(&stub);
2709 RecordJSReturnSite(expr); 2698 RecordJSReturnSite(expr);
2710 // Restore context register. 2699 // Restore context register.
2711 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2700 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2712 context()->DropAndPlug(1, eax); 2701 context()->DropAndPlug(1, eax);
2713 2702
2714 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { 2703 } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
2715 // Push global object as receiver for the call IC. 2704 // Push global object as receiver for the call IC.
2716 __ push(GlobalObjectOperand()); 2705 __ push(GlobalObjectOperand());
2717 EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); 2706 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
2718
2719 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 2707 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
2720 // Call to a lookup slot (dynamically introduced variable). 2708 // Call to a lookup slot (dynamically introduced variable).
2721 Label slow, done; 2709 Label slow, done;
2722 { PreservePositionScope scope(masm()->positions_recorder()); 2710 { PreservePositionScope scope(masm()->positions_recorder());
2723 // Generate code for loading from variables potentially shadowed by 2711 // Generate code for loading from variables potentially shadowed by
2724 // eval-introduced variables. 2712 // eval-introduced variables.
2725 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2713 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2726 } 2714 }
2727 __ bind(&slow); 2715 __ bind(&slow);
2728 // Call the runtime to find the function to call (returned in eax) and 2716 // Call the runtime to find the function to call (returned in eax) and
2729 // the object holding it (returned in edx). 2717 // the object holding it (returned in edx).
2730 __ push(context_register()); 2718 __ push(context_register());
2731 __ push(Immediate(proxy->name())); 2719 __ push(Immediate(proxy->name()));
2732 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2720 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2733 __ push(eax); // Function. 2721 __ push(eax); // Function.
2734 __ push(edx); // Receiver. 2722 __ push(edx); // Receiver.
2735 2723
2736 // If fast case code has been generated, emit code to push the function 2724 // If fast case code has been generated, emit code to push the function
2737 // and receiver and have the slow path jump around this code. 2725 // and receiver and have the slow path jump around this code.
2738 if (done.is_linked()) { 2726 if (done.is_linked()) {
2739 Label call; 2727 Label call;
2740 __ jmp(&call, Label::kNear); 2728 __ jmp(&call, Label::kNear);
2741 __ bind(&done); 2729 __ bind(&done);
2742 // Push function. 2730 // Push function.
2743 __ push(eax); 2731 __ push(eax);
2744 // The receiver is implicitly the global receiver. Indicate this by 2732 // The receiver is implicitly the global receiver. Indicate this by
2745 // passing the hole to the call function stub. 2733 // passing the hole to the call function stub.
2746 __ push(Immediate(isolate()->factory()->the_hole_value())); 2734 __ push(Immediate(isolate()->factory()->undefined_value()));
2747 __ bind(&call); 2735 __ bind(&call);
2748 } 2736 }
2749 2737
2750 // The receiver is either the global receiver or an object found by 2738 // The receiver is either the global receiver or an object found by
2751 // LoadContextSlot. That object could be the hole if the receiver is 2739 // LoadContextSlot.
2752 // implicitly the global object. 2740 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2753 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
2754 2741
2755 } else if (property != NULL) { 2742 } else if (property != NULL) {
2756 { PreservePositionScope scope(masm()->positions_recorder()); 2743 { PreservePositionScope scope(masm()->positions_recorder());
2757 VisitForStackValue(property->obj()); 2744 VisitForStackValue(property->obj());
2758 } 2745 }
2759 if (property->key()->IsPropertyName()) { 2746 if (property->key()->IsPropertyName()) {
2760 EmitCallWithIC(expr, 2747 EmitCallWithIC(expr,
2761 property->key()->AsLiteral()->value(), 2748 property->key()->AsLiteral()->value(),
2762 RelocInfo::CODE_TARGET); 2749 NOT_CONTEXTUAL);
2763 } else { 2750 } else {
2764 EmitKeyedCallWithIC(expr, property->key()); 2751 EmitKeyedCallWithIC(expr, property->key());
2765 } 2752 }
2766 2753
2767 } else { 2754 } else {
2768 // Call to an arbitrary expression not handled specially above. 2755 // Call to an arbitrary expression not handled specially above.
2769 { PreservePositionScope scope(masm()->positions_recorder()); 2756 { PreservePositionScope scope(masm()->positions_recorder());
2770 VisitForStackValue(callee); 2757 VisitForStackValue(callee);
2771 } 2758 }
2772 // Load global receiver object. 2759 __ push(Immediate(isolate()->factory()->undefined_value()));
2773 __ mov(ebx, GlobalObjectOperand());
2774 __ push(FieldOperand(ebx, GlobalObject::kGlobalReceiverOffset));
2775 // Emit function call. 2760 // Emit function call.
2776 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); 2761 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2777 } 2762 }
2778 2763
2779 #ifdef DEBUG 2764 #ifdef DEBUG
2780 // RecordJSReturnSite should have been called. 2765 // RecordJSReturnSite should have been called.
2781 ASSERT(expr->return_is_recorded_); 2766 ASSERT(expr->return_is_recorded_);
2782 #endif 2767 #endif
2783 } 2768 }
2784 2769
(...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after
3702 Label runtime, done; 3687 Label runtime, done;
3703 // Check for non-function argument (including proxy). 3688 // Check for non-function argument (including proxy).
3704 __ JumpIfSmi(eax, &runtime); 3689 __ JumpIfSmi(eax, &runtime);
3705 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 3690 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
3706 __ j(not_equal, &runtime); 3691 __ j(not_equal, &runtime);
3707 3692
3708 // InvokeFunction requires the function in edi. Move it in there. 3693 // InvokeFunction requires the function in edi. Move it in there.
3709 __ mov(edi, result_register()); 3694 __ mov(edi, result_register());
3710 ParameterCount count(arg_count); 3695 ParameterCount count(arg_count);
3711 __ InvokeFunction(edi, count, CALL_FUNCTION, 3696 __ InvokeFunction(edi, count, CALL_FUNCTION,
3712 NullCallWrapper(), CALL_AS_METHOD); 3697 NullCallWrapper(), CALL_AS_FUNCTION);
3713 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3698 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3714 __ jmp(&done); 3699 __ jmp(&done);
3715 3700
3716 __ bind(&runtime); 3701 __ bind(&runtime);
3717 __ push(eax); 3702 __ push(eax);
3718 __ CallRuntime(Runtime::kCall, args->length()); 3703 __ CallRuntime(Runtime::kCall, args->length());
3719 __ bind(&done); 3704 __ bind(&done);
3720 3705
3721 context()->Plug(eax); 3706 context()->Plug(eax);
3722 } 3707 }
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
4143 4128
4144 // Push the arguments ("left-to-right"). 4129 // Push the arguments ("left-to-right").
4145 int arg_count = args->length(); 4130 int arg_count = args->length();
4146 for (int i = 0; i < arg_count; i++) { 4131 for (int i = 0; i < arg_count; i++) {
4147 VisitForStackValue(args->at(i)); 4132 VisitForStackValue(args->at(i));
4148 } 4133 }
4149 4134
4150 if (expr->is_jsruntime()) { 4135 if (expr->is_jsruntime()) {
4151 // Call the JS runtime function via a call IC. 4136 // Call the JS runtime function via a call IC.
4152 __ Set(ecx, Immediate(expr->name())); 4137 __ Set(ecx, Immediate(expr->name()));
4153 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 4138 ContextualMode mode = NOT_CONTEXTUAL;
4154 Handle<Code> ic = 4139 Handle<Code> ic =
4155 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); 4140 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
4156 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); 4141 CallIC(ic, mode, expr->CallRuntimeFeedbackId());
4157 // Restore context register. 4142 // Restore context register.
4158 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4143 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4159 } else { 4144 } else {
4160 // Call the C runtime function. 4145 // Call the C runtime function.
4161 __ CallRuntime(expr->function(), arg_count); 4146 __ CallRuntime(expr->function(), arg_count);
4162 } 4147 }
4163 context()->Plug(eax); 4148 context()->Plug(eax);
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
4403 4388
4404 // Record position before stub call. 4389 // Record position before stub call.
4405 SetSourcePosition(expr->position()); 4390 SetSourcePosition(expr->position());
4406 4391
4407 // Call stub for +1/-1. 4392 // Call stub for +1/-1.
4408 __ bind(&stub_call); 4393 __ bind(&stub_call);
4409 __ mov(edx, eax); 4394 __ mov(edx, eax);
4410 __ mov(eax, Immediate(Smi::FromInt(1))); 4395 __ mov(eax, Immediate(Smi::FromInt(1)));
4411 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); 4396 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
4412 CallIC(stub.GetCode(isolate()), 4397 CallIC(stub.GetCode(isolate()),
4413 RelocInfo::CODE_TARGET, 4398 NOT_CONTEXTUAL,
4414 expr->CountBinOpFeedbackId()); 4399 expr->CountBinOpFeedbackId());
4415 patch_site.EmitPatchInfo(); 4400 patch_site.EmitPatchInfo();
4416 __ bind(&done); 4401 __ bind(&done);
4417 4402
4418 // Store the value returned in eax. 4403 // Store the value returned in eax.
4419 switch (assign_type) { 4404 switch (assign_type) {
4420 case VARIABLE: 4405 case VARIABLE:
4421 if (expr->is_postfix()) { 4406 if (expr->is_postfix()) {
4422 // Perform the assignment as if via '='. 4407 // Perform the assignment as if via '='.
4423 { EffectContext context(this); 4408 { EffectContext context(this);
(...skipping 11 matching lines...) Expand all
4435 // Perform the assignment as if via '='. 4420 // Perform the assignment as if via '='.
4436 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4421 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4437 Token::ASSIGN); 4422 Token::ASSIGN);
4438 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4423 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4439 context()->Plug(eax); 4424 context()->Plug(eax);
4440 } 4425 }
4441 break; 4426 break;
4442 case NAMED_PROPERTY: { 4427 case NAMED_PROPERTY: {
4443 __ mov(ecx, prop->key()->AsLiteral()->value()); 4428 __ mov(ecx, prop->key()->AsLiteral()->value());
4444 __ pop(edx); 4429 __ pop(edx);
4445 Handle<Code> ic = is_classic_mode() 4430 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
4446 ? isolate()->builtins()->StoreIC_Initialize()
4447 : isolate()->builtins()->StoreIC_Initialize_Strict();
4448 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
4449 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4431 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4450 if (expr->is_postfix()) { 4432 if (expr->is_postfix()) {
4451 if (!context()->IsEffect()) { 4433 if (!context()->IsEffect()) {
4452 context()->PlugTOS(); 4434 context()->PlugTOS();
4453 } 4435 }
4454 } else { 4436 } else {
4455 context()->Plug(eax); 4437 context()->Plug(eax);
4456 } 4438 }
4457 break; 4439 break;
4458 } 4440 }
4459 case KEYED_PROPERTY: { 4441 case KEYED_PROPERTY: {
4460 __ pop(ecx); 4442 __ pop(ecx);
4461 __ pop(edx); 4443 __ pop(edx);
4462 Handle<Code> ic = is_classic_mode() 4444 Handle<Code> ic = is_classic_mode()
4463 ? isolate()->builtins()->KeyedStoreIC_Initialize() 4445 ? isolate()->builtins()->KeyedStoreIC_Initialize()
4464 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 4446 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4465 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); 4447 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
4466 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4448 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4467 if (expr->is_postfix()) { 4449 if (expr->is_postfix()) {
4468 // Result is on the stack 4450 // Result is on the stack
4469 if (!context()->IsEffect()) { 4451 if (!context()->IsEffect()) {
4470 context()->PlugTOS(); 4452 context()->PlugTOS();
4471 } 4453 }
4472 } else { 4454 } else {
4473 context()->Plug(eax); 4455 context()->Plug(eax);
4474 } 4456 }
4475 break; 4457 break;
4476 } 4458 }
4477 } 4459 }
4478 } 4460 }
4479 4461
4480 4462
4481 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4463 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4482 VariableProxy* proxy = expr->AsVariableProxy(); 4464 VariableProxy* proxy = expr->AsVariableProxy();
4483 ASSERT(!context()->IsEffect()); 4465 ASSERT(!context()->IsEffect());
4484 ASSERT(!context()->IsTest()); 4466 ASSERT(!context()->IsTest());
4485 4467
4486 if (proxy != NULL && proxy->var()->IsUnallocated()) { 4468 if (proxy != NULL && proxy->var()->IsUnallocated()) {
4487 Comment cmnt(masm_, "Global variable"); 4469 Comment cmnt(masm_, "Global variable");
4488 __ mov(edx, GlobalObjectOperand()); 4470 __ mov(edx, GlobalObjectOperand());
4489 __ mov(ecx, Immediate(proxy->name())); 4471 __ mov(ecx, Immediate(proxy->name()));
4490 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
4491 // Use a regular load, not a contextual load, to avoid a reference 4472 // Use a regular load, not a contextual load, to avoid a reference
4492 // error. 4473 // error.
4493 CallIC(ic); 4474 CallLoadIC(NOT_CONTEXTUAL);
4494 PrepareForBailout(expr, TOS_REG); 4475 PrepareForBailout(expr, TOS_REG);
4495 context()->Plug(eax); 4476 context()->Plug(eax);
4496 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4477 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4497 Label done, slow; 4478 Label done, slow;
4498 4479
4499 // Generate code for loading from variables potentially shadowed 4480 // Generate code for loading from variables potentially shadowed
4500 // by eval-introduced variables. 4481 // by eval-introduced variables.
4501 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); 4482 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
4502 4483
4503 __ bind(&slow); 4484 __ bind(&slow);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
4645 __ or_(ecx, eax); 4626 __ or_(ecx, eax);
4646 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); 4627 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
4647 __ cmp(edx, eax); 4628 __ cmp(edx, eax);
4648 Split(cc, if_true, if_false, NULL); 4629 Split(cc, if_true, if_false, NULL);
4649 __ bind(&slow_case); 4630 __ bind(&slow_case);
4650 } 4631 }
4651 4632
4652 // Record position and call the compare IC. 4633 // Record position and call the compare IC.
4653 SetSourcePosition(expr->position()); 4634 SetSourcePosition(expr->position());
4654 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 4635 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
4655 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); 4636 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
4656 patch_site.EmitPatchInfo(); 4637 patch_site.EmitPatchInfo();
4657 4638
4658 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4639 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4659 __ test(eax, eax); 4640 __ test(eax, eax);
4660 Split(cc, if_true, if_false, fall_through); 4641 Split(cc, if_true, if_false, fall_through);
4661 } 4642 }
4662 } 4643 }
4663 4644
4664 // Convert the result of the comparison into one expected for this 4645 // Convert the result of the comparison into one expected for this
4665 // expression's context. 4646 // expression's context.
(...skipping 15 matching lines...) Expand all
4681 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4662 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4682 4663
4683 Handle<Object> nil_value = nil == kNullValue 4664 Handle<Object> nil_value = nil == kNullValue
4684 ? isolate()->factory()->null_value() 4665 ? isolate()->factory()->null_value()
4685 : isolate()->factory()->undefined_value(); 4666 : isolate()->factory()->undefined_value();
4686 if (expr->op() == Token::EQ_STRICT) { 4667 if (expr->op() == Token::EQ_STRICT) {
4687 __ cmp(eax, nil_value); 4668 __ cmp(eax, nil_value);
4688 Split(equal, if_true, if_false, fall_through); 4669 Split(equal, if_true, if_false, fall_through);
4689 } else { 4670 } else {
4690 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4671 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4691 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); 4672 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
4692 __ test(eax, eax); 4673 __ test(eax, eax);
4693 Split(not_zero, if_true, if_false, fall_through); 4674 Split(not_zero, if_true, if_false, fall_through);
4694 } 4675 }
4695 context()->Plug(if_true, if_false); 4676 context()->Plug(if_true, if_false);
4696 } 4677 }
4697 4678
4698 4679
4699 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4680 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4700 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4681 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4701 context()->Plug(eax); 4682 context()->Plug(eax);
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
4909 4890
4910 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4891 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4911 Assembler::target_address_at(call_target_address)); 4892 Assembler::target_address_at(call_target_address));
4912 return OSR_AFTER_STACK_CHECK; 4893 return OSR_AFTER_STACK_CHECK;
4913 } 4894 }
4914 4895
4915 4896
4916 } } // namespace v8::internal 4897 } } // namespace v8::internal
4917 4898
4918 #endif // V8_TARGET_ARCH_IA32 4899 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/frames-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698