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

Side by Side Diff: src/x64/full-codegen-x64.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/x64/frames-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 125
126 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 126 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
127 127
128 #ifdef DEBUG 128 #ifdef DEBUG
129 if (strlen(FLAG_stop_at) > 0 && 129 if (strlen(FLAG_stop_at) > 0 &&
130 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 130 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
131 __ int3(); 131 __ int3();
132 } 132 }
133 #endif 133 #endif
134 134
135 // Strict mode functions and builtins need to replace the receiver 135 // Classic mode functions and builtins need to replace the receiver with the
136 // with undefined when called as functions (without an explicit 136 // global proxy when called as functions (without an explicit receiver
137 // receiver object). rcx is zero for method calls and non-zero for 137 // object).
138 // function calls. 138 if (info->is_classic_mode() && !info->is_native()) {
139 if (!info->is_classic_mode() || info->is_native()) {
140 Label ok; 139 Label ok;
141 __ testq(rcx, rcx); 140 __ testq(rcx, rcx);
142 __ j(zero, &ok, Label::kNear); 141 __ j(zero, &ok, Label::kNear);
142
143 // +1 for return address.
143 StackArgumentsAccessor args(rsp, info->scope()->num_parameters()); 144 StackArgumentsAccessor args(rsp, info->scope()->num_parameters());
144 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); 145 __ movq(rcx, args.GetReceiverOperand());
145 __ movq(args.GetReceiverOperand(), kScratchRegister); 146
147 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
148 __ j(not_equal, &ok, Label::kNear);
149
150 __ movq(rcx, GlobalObjectOperand());
151 __ movq(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
152
153 __ movq(args.GetReceiverOperand(), rcx);
154
146 __ bind(&ok); 155 __ bind(&ok);
147 } 156 }
148 157
149 // Open a frame scope to indicate that there is a frame on the stack. The 158 // Open a frame scope to indicate that there is a frame on the stack. The
150 // MANUAL indicates that the scope shouldn't actually generate code to set up 159 // MANUAL indicates that the scope shouldn't actually generate code to set up
151 // the frame (that is done below). 160 // the frame (that is done below).
152 FrameScope frame_scope(masm_, StackFrame::MANUAL); 161 FrameScope frame_scope(masm_, StackFrame::MANUAL);
153 162
154 info->set_prologue_offset(masm_->pc_offset()); 163 info->set_prologue_offset(masm_->pc_offset());
155 __ Prologue(BUILD_FUNCTION_FRAME); 164 __ Prologue(BUILD_FUNCTION_FRAME);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 } 304 }
296 } 305 }
297 306
298 307
299 void FullCodeGenerator::ClearAccumulator() { 308 void FullCodeGenerator::ClearAccumulator() {
300 __ Set(rax, 0); 309 __ Set(rax, 0);
301 } 310 }
302 311
303 312
304 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) { 313 void FullCodeGenerator::EmitProfilingCounterDecrement(int delta) {
305 __ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 314 __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
306 __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset), 315 __ SmiAddConstant(FieldOperand(rbx, Cell::kValueOffset),
307 Smi::FromInt(-delta)); 316 Smi::FromInt(-delta));
308 } 317 }
309 318
310 319
311 void FullCodeGenerator::EmitProfilingCounterReset() { 320 void FullCodeGenerator::EmitProfilingCounterReset() {
312 int reset_value = FLAG_interrupt_budget; 321 int reset_value = FLAG_interrupt_budget;
313 __ movq(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT); 322 __ Move(rbx, profiling_counter_, RelocInfo::EMBEDDED_OBJECT);
314 __ Move(kScratchRegister, Smi::FromInt(reset_value)); 323 __ Move(kScratchRegister, Smi::FromInt(reset_value));
315 __ movq(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister); 324 __ movq(FieldOperand(rbx, Cell::kValueOffset), kScratchRegister);
316 } 325 }
317 326
318 327
319 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt, 328 void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
320 Label* back_edge_target) { 329 Label* back_edge_target) {
321 Comment cmnt(masm_, "[ Back edge bookkeeping"); 330 Comment cmnt(masm_, "[ Back edge bookkeeping");
322 Label ok; 331 Label ok;
323 332
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 if (false_label_ != fall_through_) __ jmp(false_label_); 632 if (false_label_ != fall_through_) __ jmp(false_label_);
624 } 633 }
625 } 634 }
626 635
627 636
628 void FullCodeGenerator::DoTest(Expression* condition, 637 void FullCodeGenerator::DoTest(Expression* condition,
629 Label* if_true, 638 Label* if_true,
630 Label* if_false, 639 Label* if_false,
631 Label* fall_through) { 640 Label* fall_through) {
632 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); 641 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
633 CallIC(ic, RelocInfo::CODE_TARGET, condition->test_id()); 642 CallIC(ic, NOT_CONTEXTUAL, condition->test_id());
634 __ testq(result_register(), result_register()); 643 __ testq(result_register(), result_register());
635 // The stub returns nonzero for true. 644 // The stub returns nonzero for true.
636 Split(not_zero, if_true, if_false, fall_through); 645 Split(not_zero, if_true, if_false, fall_through);
637 } 646 }
638 647
639 648
640 void FullCodeGenerator::Split(Condition cc, 649 void FullCodeGenerator::Split(Condition cc,
641 Label* if_true, 650 Label* if_true,
642 Label* if_false, 651 Label* if_false,
643 Label* fall_through) { 652 Label* fall_through) {
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 __ cmpq(rdx, rax); 985 __ cmpq(rdx, rax);
977 __ j(not_equal, &next_test); 986 __ j(not_equal, &next_test);
978 __ Drop(1); // Switch value is no longer needed. 987 __ Drop(1); // Switch value is no longer needed.
979 __ jmp(clause->body_target()); 988 __ jmp(clause->body_target());
980 __ bind(&slow_case); 989 __ bind(&slow_case);
981 } 990 }
982 991
983 // Record position before stub call for type feedback. 992 // Record position before stub call for type feedback.
984 SetSourcePosition(clause->position()); 993 SetSourcePosition(clause->position());
985 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); 994 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
986 CallIC(ic, RelocInfo::CODE_TARGET, clause->CompareId()); 995 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId());
987 patch_site.EmitPatchInfo(); 996 patch_site.EmitPatchInfo();
988 997
989 Label skip; 998 Label skip;
990 __ jmp(&skip, Label::kNear); 999 __ jmp(&skip, Label::kNear);
991 PrepareForBailout(clause, TOS_REG); 1000 PrepareForBailout(clause, TOS_REG);
992 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 1001 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
993 __ j(not_equal, &next_test); 1002 __ j(not_equal, &next_test);
994 __ Drop(1); 1003 __ Drop(1);
995 __ jmp(clause->body_target()); 1004 __ jmp(clause->body_target());
996 __ bind(&skip); 1005 __ bind(&skip);
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 // Load next context in chain. 1355 // Load next context in chain.
1347 __ movq(temp, ContextOperand(temp, Context::PREVIOUS_INDEX)); 1356 __ movq(temp, ContextOperand(temp, Context::PREVIOUS_INDEX));
1348 __ jmp(&next); 1357 __ jmp(&next);
1349 __ bind(&fast); 1358 __ bind(&fast);
1350 } 1359 }
1351 1360
1352 // All extension objects were empty and it is safe to use a global 1361 // All extension objects were empty and it is safe to use a global
1353 // load IC call. 1362 // load IC call.
1354 __ movq(rax, GlobalObjectOperand()); 1363 __ movq(rax, GlobalObjectOperand());
1355 __ Move(rcx, var->name()); 1364 __ Move(rcx, var->name());
1356 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1365 ContextualMode mode = (typeof_state == INSIDE_TYPEOF)
1357 RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) 1366 ? NOT_CONTEXTUAL
1358 ? RelocInfo::CODE_TARGET 1367 : CONTEXTUAL;
1359 : RelocInfo::CODE_TARGET_CONTEXT; 1368 CallLoadIC(mode);
1360 CallIC(ic, mode);
1361 } 1369 }
1362 1370
1363 1371
1364 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var, 1372 MemOperand FullCodeGenerator::ContextSlotOperandCheckExtensions(Variable* var,
1365 Label* slow) { 1373 Label* slow) {
1366 ASSERT(var->IsContextSlot()); 1374 ASSERT(var->IsContextSlot());
1367 Register context = rsi; 1375 Register context = rsi;
1368 Register temp = rbx; 1376 Register temp = rbx;
1369 1377
1370 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) { 1378 for (Scope* s = scope(); s != var->scope(); s = s->outer_scope()) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 1438
1431 // Three cases: global variables, lookup variables, and all other types of 1439 // Three cases: global variables, lookup variables, and all other types of
1432 // variables. 1440 // variables.
1433 switch (var->location()) { 1441 switch (var->location()) {
1434 case Variable::UNALLOCATED: { 1442 case Variable::UNALLOCATED: {
1435 Comment cmnt(masm_, "Global variable"); 1443 Comment cmnt(masm_, "Global variable");
1436 // Use inline caching. Variable name is passed in rcx and the global 1444 // Use inline caching. Variable name is passed in rcx and the global
1437 // object on the stack. 1445 // object on the stack.
1438 __ Move(rcx, var->name()); 1446 __ Move(rcx, var->name());
1439 __ movq(rax, GlobalObjectOperand()); 1447 __ movq(rax, GlobalObjectOperand());
1440 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 1448 CallLoadIC(CONTEXTUAL);
1441 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
1442 context()->Plug(rax); 1449 context()->Plug(rax);
1443 break; 1450 break;
1444 } 1451 }
1445 1452
1446 case Variable::PARAMETER: 1453 case Variable::PARAMETER:
1447 case Variable::LOCAL: 1454 case Variable::LOCAL:
1448 case Variable::CONTEXT: { 1455 case Variable::CONTEXT: {
1449 Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot"); 1456 Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot");
1450 if (var->binding_needs_init()) { 1457 if (var->binding_needs_init()) {
1451 // var->scope() may be NULL when the proxy is located in eval code and 1458 // var->scope() may be NULL when the proxy is located in eval code and
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
1645 UNREACHABLE(); 1652 UNREACHABLE();
1646 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1653 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1647 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1654 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1648 // Fall through. 1655 // Fall through.
1649 case ObjectLiteral::Property::COMPUTED: 1656 case ObjectLiteral::Property::COMPUTED:
1650 if (key->value()->IsInternalizedString()) { 1657 if (key->value()->IsInternalizedString()) {
1651 if (property->emit_store()) { 1658 if (property->emit_store()) {
1652 VisitForAccumulatorValue(value); 1659 VisitForAccumulatorValue(value);
1653 __ Move(rcx, key->value()); 1660 __ Move(rcx, key->value());
1654 __ movq(rdx, Operand(rsp, 0)); 1661 __ movq(rdx, Operand(rsp, 0));
1655 Handle<Code> ic = is_classic_mode() 1662 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId());
1656 ? isolate()->builtins()->StoreIC_Initialize()
1657 : isolate()->builtins()->StoreIC_Initialize_Strict();
1658 CallIC(ic, RelocInfo::CODE_TARGET, key->LiteralFeedbackId());
1659 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1663 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1660 } else { 1664 } else {
1661 VisitForEffect(value); 1665 VisitForEffect(value);
1662 } 1666 }
1663 break; 1667 break;
1664 } 1668 }
1665 __ push(Operand(rsp, 0)); // Duplicate receiver. 1669 __ push(Operand(rsp, 0)); // Duplicate receiver.
1666 VisitForStackValue(key); 1670 VisitForStackValue(key);
1667 VisitForStackValue(value); 1671 VisitForStackValue(value);
1668 if (property->emit_store()) { 1672 if (property->emit_store()) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1729 int length = subexprs->length(); 1733 int length = subexprs->length();
1730 Handle<FixedArray> constant_elements = expr->constant_elements(); 1734 Handle<FixedArray> constant_elements = expr->constant_elements();
1731 ASSERT_EQ(2, constant_elements->length()); 1735 ASSERT_EQ(2, constant_elements->length());
1732 ElementsKind constant_elements_kind = 1736 ElementsKind constant_elements_kind =
1733 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); 1737 static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
1734 bool has_constant_fast_elements = 1738 bool has_constant_fast_elements =
1735 IsFastObjectElementsKind(constant_elements_kind); 1739 IsFastObjectElementsKind(constant_elements_kind);
1736 Handle<FixedArrayBase> constant_elements_values( 1740 Handle<FixedArrayBase> constant_elements_values(
1737 FixedArrayBase::cast(constant_elements->get(1))); 1741 FixedArrayBase::cast(constant_elements->get(1)));
1738 1742
1739 AllocationSiteMode allocation_site_mode = FLAG_track_allocation_sites 1743 AllocationSiteMode allocation_site_mode = TRACK_ALLOCATION_SITE;
1740 ? TRACK_ALLOCATION_SITE : DONT_TRACK_ALLOCATION_SITE;
1741 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) { 1744 if (has_constant_fast_elements && !FLAG_allocation_site_pretenuring) {
1742 // If the only customer of allocation sites is transitioning, then 1745 // If the only customer of allocation sites is transitioning, then
1743 // we can turn it off if we don't have anywhere else to transition to. 1746 // we can turn it off if we don't have anywhere else to transition to.
1744 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE; 1747 allocation_site_mode = DONT_TRACK_ALLOCATION_SITE;
1745 } 1748 }
1746 1749
1747 Heap* heap = isolate()->heap(); 1750 Heap* heap = isolate()->heap();
1748 if (has_constant_fast_elements && 1751 if (has_constant_fast_elements &&
1749 constant_elements_values->map() == heap->fixed_cow_array_map()) { 1752 constant_elements_values->map() == heap->fixed_cow_array_map()) {
1750 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot 1753 // If the elements are already FAST_*_ELEMENTS, the boilerplate cannot
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
2070 __ bind(&l_call); 2073 __ bind(&l_call);
2071 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); 2074 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1);
2072 CallIC(ic); 2075 CallIC(ic);
2073 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2076 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2074 __ Drop(1); // The key is still on the stack; drop it. 2077 __ Drop(1); // The key is still on the stack; drop it.
2075 2078
2076 // if (!result.done) goto l_try; 2079 // if (!result.done) goto l_try;
2077 __ bind(&l_loop); 2080 __ bind(&l_loop);
2078 __ push(rax); // save result 2081 __ push(rax); // save result
2079 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done" 2082 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
2080 Handle<Code> done_ic = isolate()->builtins()->LoadIC_Initialize(); 2083 CallLoadIC(NOT_CONTEXTUAL); // result.done in rax
2081 CallIC(done_ic); // result.done in rax
2082 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2084 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2083 CallIC(bool_ic); 2085 CallIC(bool_ic);
2084 __ testq(result_register(), result_register()); 2086 __ testq(result_register(), result_register());
2085 __ j(zero, &l_try); 2087 __ j(zero, &l_try);
2086 2088
2087 // result.value 2089 // result.value
2088 __ pop(rax); // result 2090 __ pop(rax); // result
2089 __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value" 2091 __ LoadRoot(rcx, Heap::kvalue_stringRootIndex); // "value"
2090 Handle<Code> value_ic = isolate()->builtins()->LoadIC_Initialize(); 2092 CallLoadIC(NOT_CONTEXTUAL); // result.value in rax
2091 CallIC(value_ic); // result.value in rax
2092 context()->DropAndPlug(2, rax); // drop iter and g 2093 context()->DropAndPlug(2, rax); // drop iter and g
2093 break; 2094 break;
2094 } 2095 }
2095 } 2096 }
2096 } 2097 }
2097 2098
2098 2099
2099 void FullCodeGenerator::EmitGeneratorResume(Expression *generator, 2100 void FullCodeGenerator::EmitGeneratorResume(Expression *generator,
2100 Expression *value, 2101 Expression *value,
2101 JSGeneratorObject::ResumeMode resume_mode) { 2102 JSGeneratorObject::ResumeMode resume_mode) {
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
2227 // root set. 2228 // root set.
2228 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset, 2229 __ RecordWriteField(rax, JSGeneratorObject::kResultValuePropertyOffset,
2229 rcx, rdx, kDontSaveFPRegs); 2230 rcx, rdx, kDontSaveFPRegs);
2230 } 2231 }
2231 2232
2232 2233
2233 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { 2234 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
2234 SetSourcePosition(prop->position()); 2235 SetSourcePosition(prop->position());
2235 Literal* key = prop->key()->AsLiteral(); 2236 Literal* key = prop->key()->AsLiteral();
2236 __ Move(rcx, key->value()); 2237 __ Move(rcx, key->value());
2237 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); 2238 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2238 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId());
2239 } 2239 }
2240 2240
2241 2241
2242 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 2242 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2243 SetSourcePosition(prop->position()); 2243 SetSourcePosition(prop->position());
2244 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2244 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2245 CallIC(ic, RelocInfo::CODE_TARGET, prop->PropertyFeedbackId()); 2245 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2246 } 2246 }
2247 2247
2248 2248
2249 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2249 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2250 Token::Value op, 2250 Token::Value op,
2251 OverwriteMode mode, 2251 OverwriteMode mode,
2252 Expression* left, 2252 Expression* left,
2253 Expression* right) { 2253 Expression* right) {
2254 // Do combined smi check of the operands. Left operand is on the 2254 // Do combined smi check of the operands. Left operand is on the
2255 // stack (popped into rdx). Right operand is in rax but moved into 2255 // stack (popped into rdx). Right operand is in rax but moved into
2256 // rcx to make the shifts easier. 2256 // rcx to make the shifts easier.
2257 Label done, stub_call, smi_case; 2257 Label done, stub_call, smi_case;
2258 __ pop(rdx); 2258 __ pop(rdx);
2259 __ movq(rcx, rax); 2259 __ movq(rcx, rax);
2260 __ or_(rax, rdx); 2260 __ or_(rax, rdx);
2261 JumpPatchSite patch_site(masm_); 2261 JumpPatchSite patch_site(masm_);
2262 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear); 2262 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
2263 2263
2264 __ bind(&stub_call); 2264 __ bind(&stub_call);
2265 __ movq(rax, rcx); 2265 __ movq(rax, rcx);
2266 BinaryOpICStub stub(op, mode); 2266 BinaryOpICStub stub(op, mode);
2267 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2267 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
2268 expr->BinaryOperationFeedbackId()); 2268 expr->BinaryOperationFeedbackId());
2269 patch_site.EmitPatchInfo(); 2269 patch_site.EmitPatchInfo();
2270 __ jmp(&done, Label::kNear); 2270 __ jmp(&done, Label::kNear);
2271 2271
2272 __ bind(&smi_case); 2272 __ bind(&smi_case);
2273 switch (op) { 2273 switch (op) {
2274 case Token::SAR: 2274 case Token::SAR:
2275 __ SmiShiftArithmeticRight(rax, rdx, rcx); 2275 __ SmiShiftArithmeticRight(rax, rdx, rcx);
2276 break; 2276 break;
2277 case Token::SHL: 2277 case Token::SHL:
(...skipping 29 matching lines...) Expand all
2307 context()->Plug(rax); 2307 context()->Plug(rax);
2308 } 2308 }
2309 2309
2310 2310
2311 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2311 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2312 Token::Value op, 2312 Token::Value op,
2313 OverwriteMode mode) { 2313 OverwriteMode mode) {
2314 __ pop(rdx); 2314 __ pop(rdx);
2315 BinaryOpICStub stub(op, mode); 2315 BinaryOpICStub stub(op, mode);
2316 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2316 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
2317 CallIC(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2317 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL,
2318 expr->BinaryOperationFeedbackId()); 2318 expr->BinaryOperationFeedbackId());
2319 patch_site.EmitPatchInfo(); 2319 patch_site.EmitPatchInfo();
2320 context()->Plug(rax); 2320 context()->Plug(rax);
2321 } 2321 }
2322 2322
2323 2323
2324 void FullCodeGenerator::EmitAssignment(Expression* expr) { 2324 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2325 // Invalid left-hand sides are rewritten by the parser to have a 'throw 2325 // Invalid left-hand sides are rewritten by the parser to have a 'throw
2326 // ReferenceError' on the left-hand side. 2326 // ReferenceError' on the left-hand side.
2327 if (!expr->IsValidLeftHandSide()) { 2327 if (!expr->IsValidLeftHandSide()) {
(...skipping 18 matching lines...) Expand all
2346 EffectContext context(this); 2346 EffectContext context(this);
2347 EmitVariableAssignment(var, Token::ASSIGN); 2347 EmitVariableAssignment(var, Token::ASSIGN);
2348 break; 2348 break;
2349 } 2349 }
2350 case NAMED_PROPERTY: { 2350 case NAMED_PROPERTY: {
2351 __ push(rax); // Preserve value. 2351 __ push(rax); // Preserve value.
2352 VisitForAccumulatorValue(prop->obj()); 2352 VisitForAccumulatorValue(prop->obj());
2353 __ movq(rdx, rax); 2353 __ movq(rdx, rax);
2354 __ pop(rax); // Restore value. 2354 __ pop(rax); // Restore value.
2355 __ Move(rcx, prop->key()->AsLiteral()->value()); 2355 __ Move(rcx, prop->key()->AsLiteral()->value());
2356 Handle<Code> ic = is_classic_mode() 2356 CallStoreIC(NOT_CONTEXTUAL);
2357 ? isolate()->builtins()->StoreIC_Initialize()
2358 : isolate()->builtins()->StoreIC_Initialize_Strict();
2359 CallIC(ic);
2360 break; 2357 break;
2361 } 2358 }
2362 case KEYED_PROPERTY: { 2359 case KEYED_PROPERTY: {
2363 __ push(rax); // Preserve value. 2360 __ push(rax); // Preserve value.
2364 VisitForStackValue(prop->obj()); 2361 VisitForStackValue(prop->obj());
2365 VisitForAccumulatorValue(prop->key()); 2362 VisitForAccumulatorValue(prop->key());
2366 __ movq(rcx, rax); 2363 __ movq(rcx, rax);
2367 __ pop(rdx); 2364 __ pop(rdx);
2368 __ pop(rax); // Restore value. 2365 __ pop(rax); // Restore value.
2369 Handle<Code> ic = is_classic_mode() 2366 Handle<Code> ic = is_classic_mode()
2370 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2367 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2371 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2368 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2372 CallIC(ic); 2369 CallIC(ic);
2373 break; 2370 break;
2374 } 2371 }
2375 } 2372 }
2376 context()->Plug(rax); 2373 context()->Plug(rax);
2377 } 2374 }
2378 2375
2379 2376
2380 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2377 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2381 Token::Value op) { 2378 Token::Value op) {
2382 if (var->IsUnallocated()) { 2379 if (var->IsUnallocated()) {
2383 // Global var, const, or let. 2380 // Global var, const, or let.
2384 __ Move(rcx, var->name()); 2381 __ Move(rcx, var->name());
2385 __ movq(rdx, GlobalObjectOperand()); 2382 __ movq(rdx, GlobalObjectOperand());
2386 Handle<Code> ic = is_classic_mode() 2383 CallStoreIC(CONTEXTUAL);
2387 ? isolate()->builtins()->StoreIC_Initialize()
2388 : isolate()->builtins()->StoreIC_Initialize_Strict();
2389 CallIC(ic, RelocInfo::CODE_TARGET_CONTEXT);
2390 } else if (op == Token::INIT_CONST) { 2384 } else if (op == Token::INIT_CONST) {
2391 // Const initializers need a write barrier. 2385 // Const initializers need a write barrier.
2392 ASSERT(!var->IsParameter()); // No const parameters. 2386 ASSERT(!var->IsParameter()); // No const parameters.
2393 if (var->IsStackLocal()) { 2387 if (var->IsStackLocal()) {
2394 Label skip; 2388 Label skip;
2395 __ movq(rdx, StackOperand(var)); 2389 __ movq(rdx, StackOperand(var));
2396 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2390 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2397 __ j(not_equal, &skip); 2391 __ j(not_equal, &skip);
2398 __ movq(StackOperand(var), rax); 2392 __ movq(StackOperand(var), rax);
2399 __ bind(&skip); 2393 __ bind(&skip);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
2470 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2464 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2471 // Assignment to a property, using a named store IC. 2465 // Assignment to a property, using a named store IC.
2472 Property* prop = expr->target()->AsProperty(); 2466 Property* prop = expr->target()->AsProperty();
2473 ASSERT(prop != NULL); 2467 ASSERT(prop != NULL);
2474 ASSERT(prop->key()->AsLiteral() != NULL); 2468 ASSERT(prop->key()->AsLiteral() != NULL);
2475 2469
2476 // Record source code position before IC call. 2470 // Record source code position before IC call.
2477 SetSourcePosition(expr->position()); 2471 SetSourcePosition(expr->position());
2478 __ Move(rcx, prop->key()->AsLiteral()->value()); 2472 __ Move(rcx, prop->key()->AsLiteral()->value());
2479 __ pop(rdx); 2473 __ pop(rdx);
2480 Handle<Code> ic = is_classic_mode() 2474 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
2481 ? isolate()->builtins()->StoreIC_Initialize()
2482 : isolate()->builtins()->StoreIC_Initialize_Strict();
2483 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId());
2484 2475
2485 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2476 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2486 context()->Plug(rax); 2477 context()->Plug(rax);
2487 } 2478 }
2488 2479
2489 2480
2490 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2481 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2491 // Assignment to a property, using a keyed store IC. 2482 // Assignment to a property, using a keyed store IC.
2492 2483
2493 __ pop(rcx); 2484 __ pop(rcx);
2494 __ pop(rdx); 2485 __ pop(rdx);
2495 // Record source code position before IC call. 2486 // Record source code position before IC call.
2496 SetSourcePosition(expr->position()); 2487 SetSourcePosition(expr->position());
2497 Handle<Code> ic = is_classic_mode() 2488 Handle<Code> ic = is_classic_mode()
2498 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2489 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2499 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2490 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2500 CallIC(ic, RelocInfo::CODE_TARGET, expr->AssignmentFeedbackId()); 2491 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId());
2501 2492
2502 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2493 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2503 context()->Plug(rax); 2494 context()->Plug(rax);
2504 } 2495 }
2505 2496
2506 2497
2507 void FullCodeGenerator::VisitProperty(Property* expr) { 2498 void FullCodeGenerator::VisitProperty(Property* expr) {
2508 Comment cmnt(masm_, "[ Property"); 2499 Comment cmnt(masm_, "[ Property");
2509 Expression* key = expr->key(); 2500 Expression* key = expr->key();
2510 2501
2511 if (key->IsPropertyName()) { 2502 if (key->IsPropertyName()) {
2512 VisitForAccumulatorValue(expr->obj()); 2503 VisitForAccumulatorValue(expr->obj());
2513 EmitNamedPropertyLoad(expr); 2504 EmitNamedPropertyLoad(expr);
2514 PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2505 PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2515 context()->Plug(rax); 2506 context()->Plug(rax);
2516 } else { 2507 } else {
2517 VisitForStackValue(expr->obj()); 2508 VisitForStackValue(expr->obj());
2518 VisitForAccumulatorValue(expr->key()); 2509 VisitForAccumulatorValue(expr->key());
2519 __ pop(rdx); 2510 __ pop(rdx);
2520 EmitKeyedPropertyLoad(expr); 2511 EmitKeyedPropertyLoad(expr);
2521 context()->Plug(rax); 2512 context()->Plug(rax);
2522 } 2513 }
2523 } 2514 }
2524 2515
2525 2516
2526 void FullCodeGenerator::CallIC(Handle<Code> code, 2517 void FullCodeGenerator::CallIC(Handle<Code> code,
2527 RelocInfo::Mode rmode, 2518 ContextualMode mode,
2528 TypeFeedbackId ast_id) { 2519 TypeFeedbackId ast_id) {
2529 ic_total_count_++; 2520 ic_total_count_++;
2530 __ call(code, rmode, ast_id); 2521 ASSERT(mode != CONTEXTUAL || ast_id.IsNone());
2522 __ call(code, RelocInfo::CODE_TARGET, ast_id);
2531 } 2523 }
2532 2524
2533 2525
2534 void FullCodeGenerator::EmitCallWithIC(Call* expr, 2526 void FullCodeGenerator::EmitCallWithIC(Call* expr,
2535 Handle<Object> name, 2527 Handle<Object> name,
2536 RelocInfo::Mode mode) { 2528 ContextualMode mode) {
2537 // Code common for calls using the IC. 2529 // Code common for calls using the IC.
2538 ZoneList<Expression*>* args = expr->arguments(); 2530 ZoneList<Expression*>* args = expr->arguments();
2539 int arg_count = args->length(); 2531 int arg_count = args->length();
2540 { PreservePositionScope scope(masm()->positions_recorder()); 2532 { PreservePositionScope scope(masm()->positions_recorder());
2541 for (int i = 0; i < arg_count; i++) { 2533 for (int i = 0; i < arg_count; i++) {
2542 VisitForStackValue(args->at(i)); 2534 VisitForStackValue(args->at(i));
2543 } 2535 }
2544 __ Move(rcx, name); 2536 __ Move(rcx, name);
2545 } 2537 }
2546 // Record source position for debugger. 2538 // Record source position for debugger.
2547 SetSourcePosition(expr->position()); 2539 SetSourcePosition(expr->position());
2548 // Call the IC initialization code. 2540 // Call the IC initialization code.
2549 Handle<Code> ic = 2541 Handle<Code> ic =
2550 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); 2542 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
2551 CallIC(ic, mode, expr->CallFeedbackId()); 2543 TypeFeedbackId ast_id = mode == CONTEXTUAL
2544 ? TypeFeedbackId::None()
2545 : expr->CallFeedbackId();
2546 CallIC(ic, mode, ast_id);
2552 RecordJSReturnSite(expr); 2547 RecordJSReturnSite(expr);
2553 // Restore context register. 2548 // Restore context register.
2554 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2549 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2555 context()->Plug(rax); 2550 context()->Plug(rax);
2556 } 2551 }
2557 2552
2558 2553
2559 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2554 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2560 Expression* key) { 2555 Expression* key) {
2561 // Load the key. 2556 // Load the key.
(...skipping 12 matching lines...) Expand all
2574 for (int i = 0; i < arg_count; i++) { 2569 for (int i = 0; i < arg_count; i++) {
2575 VisitForStackValue(args->at(i)); 2570 VisitForStackValue(args->at(i));
2576 } 2571 }
2577 } 2572 }
2578 // Record source position for debugger. 2573 // Record source position for debugger.
2579 SetSourcePosition(expr->position()); 2574 SetSourcePosition(expr->position());
2580 // Call the IC initialization code. 2575 // Call the IC initialization code.
2581 Handle<Code> ic = 2576 Handle<Code> ic =
2582 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); 2577 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count);
2583 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. 2578 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key.
2584 CallIC(ic, RelocInfo::CODE_TARGET, expr->CallFeedbackId()); 2579 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId());
2585 RecordJSReturnSite(expr); 2580 RecordJSReturnSite(expr);
2586 // Restore context register. 2581 // Restore context register.
2587 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2582 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2588 context()->DropAndPlug(1, rax); // Drop the key still on the stack. 2583 context()->DropAndPlug(1, rax); // Drop the key still on the stack.
2589 } 2584 }
2590 2585
2591 2586
2592 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) { 2587 void FullCodeGenerator::EmitCallWithStub(Call* expr, CallFunctionFlags flags) {
2593 // Code common for calls using the call stub. 2588 // Code common for calls using the call stub.
2594 ZoneList<Expression*>* args = expr->arguments(); 2589 ZoneList<Expression*>* args = expr->arguments();
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2675 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); 2670 __ push(Operand(rsp, (arg_count + 1) * kPointerSize));
2676 EmitResolvePossiblyDirectEval(arg_count); 2671 EmitResolvePossiblyDirectEval(arg_count);
2677 2672
2678 // The runtime call returns a pair of values in rax (function) and 2673 // The runtime call returns a pair of values in rax (function) and
2679 // rdx (receiver). Touch up the stack with the right values. 2674 // rdx (receiver). Touch up the stack with the right values.
2680 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); 2675 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx);
2681 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); 2676 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
2682 } 2677 }
2683 // Record source position for debugger. 2678 // Record source position for debugger.
2684 SetSourcePosition(expr->position()); 2679 SetSourcePosition(expr->position());
2685 CallFunctionStub stub(arg_count, RECEIVER_MIGHT_BE_IMPLICIT); 2680 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
2686 __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2681 __ movq(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2687 __ CallStub(&stub); 2682 __ CallStub(&stub);
2688 RecordJSReturnSite(expr); 2683 RecordJSReturnSite(expr);
2689 // Restore context register. 2684 // Restore context register.
2690 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2685 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2691 context()->DropAndPlug(1, rax); 2686 context()->DropAndPlug(1, rax);
2692 } else if (proxy != NULL && proxy->var()->IsUnallocated()) { 2687 } else if (proxy != NULL && proxy->var()->IsUnallocated()) {
2693 // Call to a global variable. Push global object as receiver for the 2688 // Call to a global variable. Push global object as receiver for the
2694 // call IC lookup. 2689 // call IC lookup.
2695 __ push(GlobalObjectOperand()); 2690 __ push(GlobalObjectOperand());
2696 EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); 2691 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
2697 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 2692 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
2698 // Call to a lookup slot (dynamically introduced variable). 2693 // Call to a lookup slot (dynamically introduced variable).
2699 Label slow, done; 2694 Label slow, done;
2700 2695
2701 { PreservePositionScope scope(masm()->positions_recorder()); 2696 { PreservePositionScope scope(masm()->positions_recorder());
2702 // Generate code for loading from variables potentially shadowed by 2697 // Generate code for loading from variables potentially shadowed by
2703 // eval-introduced variables. 2698 // eval-introduced variables.
2704 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2699 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2705 } 2700 }
2706 __ bind(&slow); 2701 __ bind(&slow);
2707 // Call the runtime to find the function to call (returned in rax) and 2702 // Call the runtime to find the function to call (returned in rax) and
2708 // the object holding it (returned in rdx). 2703 // the object holding it (returned in rdx).
2709 __ push(context_register()); 2704 __ push(context_register());
2710 __ Push(proxy->name()); 2705 __ Push(proxy->name());
2711 __ CallRuntime(Runtime::kLoadContextSlot, 2); 2706 __ CallRuntime(Runtime::kLoadContextSlot, 2);
2712 __ push(rax); // Function. 2707 __ push(rax); // Function.
2713 __ push(rdx); // Receiver. 2708 __ push(rdx); // Receiver.
2714 2709
2715 // If fast case code has been generated, emit code to push the function 2710 // If fast case code has been generated, emit code to push the function
2716 // and receiver and have the slow path jump around this code. 2711 // and receiver and have the slow path jump around this code.
2717 if (done.is_linked()) { 2712 if (done.is_linked()) {
2718 Label call; 2713 Label call;
2719 __ jmp(&call, Label::kNear); 2714 __ jmp(&call, Label::kNear);
2720 __ bind(&done); 2715 __ bind(&done);
2721 // Push function. 2716 // Push function.
2722 __ push(rax); 2717 __ push(rax);
2723 // The receiver is implicitly the global receiver. Indicate this by 2718 // The receiver is implicitly the global receiver. Indicate this by
2724 // passing the hole to the call function stub. 2719 // passing the hole to the call function stub.
2725 __ PushRoot(Heap::kTheHoleValueRootIndex); 2720 __ PushRoot(Heap::kUndefinedValueRootIndex);
2726 __ bind(&call); 2721 __ bind(&call);
2727 } 2722 }
2728 2723
2729 // The receiver is either the global receiver or an object found by 2724 // The receiver is either the global receiver or an object found by
2730 // LoadContextSlot. That object could be the hole if the receiver is 2725 // LoadContextSlot.
2731 // implicitly the global object. 2726 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2732 EmitCallWithStub(expr, RECEIVER_MIGHT_BE_IMPLICIT);
2733 } else if (property != NULL) { 2727 } else if (property != NULL) {
2734 { PreservePositionScope scope(masm()->positions_recorder()); 2728 { PreservePositionScope scope(masm()->positions_recorder());
2735 VisitForStackValue(property->obj()); 2729 VisitForStackValue(property->obj());
2736 } 2730 }
2737 if (property->key()->IsPropertyName()) { 2731 if (property->key()->IsPropertyName()) {
2738 EmitCallWithIC(expr, 2732 EmitCallWithIC(expr,
2739 property->key()->AsLiteral()->value(), 2733 property->key()->AsLiteral()->value(),
2740 RelocInfo::CODE_TARGET); 2734 NOT_CONTEXTUAL);
2741 } else { 2735 } else {
2742 EmitKeyedCallWithIC(expr, property->key()); 2736 EmitKeyedCallWithIC(expr, property->key());
2743 } 2737 }
2744 } else { 2738 } else {
2745 // Call to an arbitrary expression not handled specially above. 2739 // Call to an arbitrary expression not handled specially above.
2746 { PreservePositionScope scope(masm()->positions_recorder()); 2740 { PreservePositionScope scope(masm()->positions_recorder());
2747 VisitForStackValue(callee); 2741 VisitForStackValue(callee);
2748 } 2742 }
2749 // Load global receiver object. 2743 __ PushRoot(Heap::kUndefinedValueRootIndex);
2750 __ movq(rbx, GlobalObjectOperand());
2751 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
2752 // Emit function call. 2744 // Emit function call.
2753 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS); 2745 EmitCallWithStub(expr, NO_CALL_FUNCTION_FLAGS);
2754 } 2746 }
2755 2747
2756 #ifdef DEBUG 2748 #ifdef DEBUG
2757 // RecordJSReturnSite should have been called. 2749 // RecordJSReturnSite should have been called.
2758 ASSERT(expr->return_is_recorded_); 2750 ASSERT(expr->return_is_recorded_);
2759 #endif 2751 #endif
2760 } 2752 }
2761 2753
(...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after
3349 __ movq(scratch, stamp_operand); 3341 __ movq(scratch, stamp_operand);
3350 __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 3342 __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
3351 __ j(not_equal, &runtime, Label::kNear); 3343 __ j(not_equal, &runtime, Label::kNear);
3352 __ movq(result, FieldOperand(object, JSDate::kValueOffset + 3344 __ movq(result, FieldOperand(object, JSDate::kValueOffset +
3353 kPointerSize * index->value())); 3345 kPointerSize * index->value()));
3354 __ jmp(&done); 3346 __ jmp(&done);
3355 } 3347 }
3356 __ bind(&runtime); 3348 __ bind(&runtime);
3357 __ PrepareCallCFunction(2); 3349 __ PrepareCallCFunction(2);
3358 __ movq(arg_reg_1, object); 3350 __ movq(arg_reg_1, object);
3359 __ movq(arg_reg_2, index, RelocInfo::NONE64); 3351 __ Move(arg_reg_2, index, RelocInfo::NONE64);
3360 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 3352 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3361 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3353 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3362 __ jmp(&done); 3354 __ jmp(&done);
3363 } 3355 }
3364 3356
3365 __ bind(&not_date_object); 3357 __ bind(&not_date_object);
3366 __ CallRuntime(Runtime::kThrowNotDateError, 0); 3358 __ CallRuntime(Runtime::kThrowNotDateError, 0);
3367 __ bind(&done); 3359 __ bind(&done);
3368 context()->Plug(rax); 3360 context()->Plug(rax);
3369 } 3361 }
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
3669 Label runtime, done; 3661 Label runtime, done;
3670 // Check for non-function argument (including proxy). 3662 // Check for non-function argument (including proxy).
3671 __ JumpIfSmi(rax, &runtime); 3663 __ JumpIfSmi(rax, &runtime);
3672 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 3664 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
3673 __ j(not_equal, &runtime); 3665 __ j(not_equal, &runtime);
3674 3666
3675 // InvokeFunction requires the function in rdi. Move it in there. 3667 // InvokeFunction requires the function in rdi. Move it in there.
3676 __ movq(rdi, result_register()); 3668 __ movq(rdi, result_register());
3677 ParameterCount count(arg_count); 3669 ParameterCount count(arg_count);
3678 __ InvokeFunction(rdi, count, CALL_FUNCTION, 3670 __ InvokeFunction(rdi, count, CALL_FUNCTION,
3679 NullCallWrapper(), CALL_AS_METHOD); 3671 NullCallWrapper(), CALL_AS_FUNCTION);
3680 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3672 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3681 __ jmp(&done); 3673 __ jmp(&done);
3682 3674
3683 __ bind(&runtime); 3675 __ bind(&runtime);
3684 __ push(rax); 3676 __ push(rax);
3685 __ CallRuntime(Runtime::kCall, args->length()); 3677 __ CallRuntime(Runtime::kCall, args->length());
3686 __ bind(&done); 3678 __ bind(&done);
3687 3679
3688 context()->Plug(rax); 3680 context()->Plug(rax);
3689 } 3681 }
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
4139 4131
4140 // Push the arguments ("left-to-right"). 4132 // Push the arguments ("left-to-right").
4141 int arg_count = args->length(); 4133 int arg_count = args->length();
4142 for (int i = 0; i < arg_count; i++) { 4134 for (int i = 0; i < arg_count; i++) {
4143 VisitForStackValue(args->at(i)); 4135 VisitForStackValue(args->at(i));
4144 } 4136 }
4145 4137
4146 if (expr->is_jsruntime()) { 4138 if (expr->is_jsruntime()) {
4147 // Call the JS runtime function using a call IC. 4139 // Call the JS runtime function using a call IC.
4148 __ Move(rcx, expr->name()); 4140 __ Move(rcx, expr->name());
4149 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; 4141 ContextualMode mode = NOT_CONTEXTUAL;
4150 Handle<Code> ic = 4142 Handle<Code> ic =
4151 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode); 4143 isolate()->stub_cache()->ComputeCallInitialize(arg_count, mode);
4152 CallIC(ic, mode, expr->CallRuntimeFeedbackId()); 4144 CallIC(ic, mode, expr->CallRuntimeFeedbackId());
4153 // Restore context register. 4145 // Restore context register.
4154 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4146 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4155 } else { 4147 } else {
4156 __ CallRuntime(expr->function(), arg_count); 4148 __ CallRuntime(expr->function(), arg_count);
4157 } 4149 }
4158 context()->Plug(rax); 4150 context()->Plug(rax);
4159 } 4151 }
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
4393 4385
4394 // Record position before stub call. 4386 // Record position before stub call.
4395 SetSourcePosition(expr->position()); 4387 SetSourcePosition(expr->position());
4396 4388
4397 // Call stub for +1/-1. 4389 // Call stub for +1/-1.
4398 __ bind(&stub_call); 4390 __ bind(&stub_call);
4399 __ movq(rdx, rax); 4391 __ movq(rdx, rax);
4400 __ Move(rax, Smi::FromInt(1)); 4392 __ Move(rax, Smi::FromInt(1));
4401 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); 4393 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
4402 CallIC(stub.GetCode(isolate()), 4394 CallIC(stub.GetCode(isolate()),
4403 RelocInfo::CODE_TARGET, 4395 NOT_CONTEXTUAL,
4404 expr->CountBinOpFeedbackId()); 4396 expr->CountBinOpFeedbackId());
4405 patch_site.EmitPatchInfo(); 4397 patch_site.EmitPatchInfo();
4406 __ bind(&done); 4398 __ bind(&done);
4407 4399
4408 // Store the value returned in rax. 4400 // Store the value returned in rax.
4409 switch (assign_type) { 4401 switch (assign_type) {
4410 case VARIABLE: 4402 case VARIABLE:
4411 if (expr->is_postfix()) { 4403 if (expr->is_postfix()) {
4412 // Perform the assignment as if via '='. 4404 // Perform the assignment as if via '='.
4413 { EffectContext context(this); 4405 { EffectContext context(this);
(...skipping 11 matching lines...) Expand all
4425 // Perform the assignment as if via '='. 4417 // Perform the assignment as if via '='.
4426 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4418 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4427 Token::ASSIGN); 4419 Token::ASSIGN);
4428 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4420 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4429 context()->Plug(rax); 4421 context()->Plug(rax);
4430 } 4422 }
4431 break; 4423 break;
4432 case NAMED_PROPERTY: { 4424 case NAMED_PROPERTY: {
4433 __ Move(rcx, prop->key()->AsLiteral()->value()); 4425 __ Move(rcx, prop->key()->AsLiteral()->value());
4434 __ pop(rdx); 4426 __ pop(rdx);
4435 Handle<Code> ic = is_classic_mode() 4427 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
4436 ? isolate()->builtins()->StoreIC_Initialize()
4437 : isolate()->builtins()->StoreIC_Initialize_Strict();
4438 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId());
4439 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4428 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4440 if (expr->is_postfix()) { 4429 if (expr->is_postfix()) {
4441 if (!context()->IsEffect()) { 4430 if (!context()->IsEffect()) {
4442 context()->PlugTOS(); 4431 context()->PlugTOS();
4443 } 4432 }
4444 } else { 4433 } else {
4445 context()->Plug(rax); 4434 context()->Plug(rax);
4446 } 4435 }
4447 break; 4436 break;
4448 } 4437 }
4449 case KEYED_PROPERTY: { 4438 case KEYED_PROPERTY: {
4450 __ pop(rcx); 4439 __ pop(rcx);
4451 __ pop(rdx); 4440 __ pop(rdx);
4452 Handle<Code> ic = is_classic_mode() 4441 Handle<Code> ic = is_classic_mode()
4453 ? isolate()->builtins()->KeyedStoreIC_Initialize() 4442 ? isolate()->builtins()->KeyedStoreIC_Initialize()
4454 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 4443 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4455 CallIC(ic, RelocInfo::CODE_TARGET, expr->CountStoreFeedbackId()); 4444 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId());
4456 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4445 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4457 if (expr->is_postfix()) { 4446 if (expr->is_postfix()) {
4458 if (!context()->IsEffect()) { 4447 if (!context()->IsEffect()) {
4459 context()->PlugTOS(); 4448 context()->PlugTOS();
4460 } 4449 }
4461 } else { 4450 } else {
4462 context()->Plug(rax); 4451 context()->Plug(rax);
4463 } 4452 }
4464 break; 4453 break;
4465 } 4454 }
4466 } 4455 }
4467 } 4456 }
4468 4457
4469 4458
4470 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4459 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4471 VariableProxy* proxy = expr->AsVariableProxy(); 4460 VariableProxy* proxy = expr->AsVariableProxy();
4472 ASSERT(!context()->IsEffect()); 4461 ASSERT(!context()->IsEffect());
4473 ASSERT(!context()->IsTest()); 4462 ASSERT(!context()->IsTest());
4474 4463
4475 if (proxy != NULL && proxy->var()->IsUnallocated()) { 4464 if (proxy != NULL && proxy->var()->IsUnallocated()) {
4476 Comment cmnt(masm_, "Global variable"); 4465 Comment cmnt(masm_, "Global variable");
4477 __ Move(rcx, proxy->name()); 4466 __ Move(rcx, proxy->name());
4478 __ movq(rax, GlobalObjectOperand()); 4467 __ movq(rax, GlobalObjectOperand());
4479 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
4480 // Use a regular load, not a contextual load, to avoid a reference 4468 // Use a regular load, not a contextual load, to avoid a reference
4481 // error. 4469 // error.
4482 CallIC(ic); 4470 CallLoadIC(NOT_CONTEXTUAL);
4483 PrepareForBailout(expr, TOS_REG); 4471 PrepareForBailout(expr, TOS_REG);
4484 context()->Plug(rax); 4472 context()->Plug(rax);
4485 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4473 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4486 Label done, slow; 4474 Label done, slow;
4487 4475
4488 // Generate code for loading from variables potentially shadowed 4476 // Generate code for loading from variables potentially shadowed
4489 // by eval-introduced variables. 4477 // by eval-introduced variables.
4490 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); 4478 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
4491 4479
4492 __ bind(&slow); 4480 __ bind(&slow);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
4634 __ or_(rcx, rax); 4622 __ or_(rcx, rax);
4635 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 4623 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
4636 __ cmpq(rdx, rax); 4624 __ cmpq(rdx, rax);
4637 Split(cc, if_true, if_false, NULL); 4625 Split(cc, if_true, if_false, NULL);
4638 __ bind(&slow_case); 4626 __ bind(&slow_case);
4639 } 4627 }
4640 4628
4641 // Record position and call the compare IC. 4629 // Record position and call the compare IC.
4642 SetSourcePosition(expr->position()); 4630 SetSourcePosition(expr->position());
4643 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 4631 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
4644 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); 4632 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
4645 patch_site.EmitPatchInfo(); 4633 patch_site.EmitPatchInfo();
4646 4634
4647 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4635 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4648 __ testq(rax, rax); 4636 __ testq(rax, rax);
4649 Split(cc, if_true, if_false, fall_through); 4637 Split(cc, if_true, if_false, fall_through);
4650 } 4638 }
4651 } 4639 }
4652 4640
4653 // Convert the result of the comparison into one expected for this 4641 // Convert the result of the comparison into one expected for this
4654 // expression's context. 4642 // expression's context.
(...skipping 14 matching lines...) Expand all
4669 VisitForAccumulatorValue(sub_expr); 4657 VisitForAccumulatorValue(sub_expr);
4670 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4658 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4671 if (expr->op() == Token::EQ_STRICT) { 4659 if (expr->op() == Token::EQ_STRICT) {
4672 Heap::RootListIndex nil_value = nil == kNullValue ? 4660 Heap::RootListIndex nil_value = nil == kNullValue ?
4673 Heap::kNullValueRootIndex : 4661 Heap::kNullValueRootIndex :
4674 Heap::kUndefinedValueRootIndex; 4662 Heap::kUndefinedValueRootIndex;
4675 __ CompareRoot(rax, nil_value); 4663 __ CompareRoot(rax, nil_value);
4676 Split(equal, if_true, if_false, fall_through); 4664 Split(equal, if_true, if_false, fall_through);
4677 } else { 4665 } else {
4678 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4666 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4679 CallIC(ic, RelocInfo::CODE_TARGET, expr->CompareOperationFeedbackId()); 4667 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId());
4680 __ testq(rax, rax); 4668 __ testq(rax, rax);
4681 Split(not_zero, if_true, if_false, fall_through); 4669 Split(not_zero, if_true, if_false, fall_through);
4682 } 4670 }
4683 context()->Plug(if_true, if_false); 4671 context()->Plug(if_true, if_false);
4684 } 4672 }
4685 4673
4686 4674
4687 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4675 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4688 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 4676 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4689 context()->Plug(rax); 4677 context()->Plug(rax);
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
4901 4889
4902 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4890 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4903 Assembler::target_address_at(call_target_address)); 4891 Assembler::target_address_at(call_target_address));
4904 return OSR_AFTER_STACK_CHECK; 4892 return OSR_AFTER_STACK_CHECK;
4905 } 4893 }
4906 4894
4907 4895
4908 } } // namespace v8::internal 4896 } } // namespace v8::internal
4909 4897
4910 #endif // V8_TARGET_ARCH_X64 4898 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/frames-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698