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

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

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/disasm-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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 // o rsi: our context 111 // o rsi: our context
112 // o rbp: our caller's frame pointer 112 // o rbp: our caller's frame pointer
113 // o rsp: stack pointer (pointing to return address) 113 // o rsp: stack pointer (pointing to return address)
114 // 114 //
115 // The function builds a JS frame. Please see JavaScriptFrameConstants in 115 // The function builds a JS frame. Please see JavaScriptFrameConstants in
116 // frames-x64.h for its layout. 116 // frames-x64.h for its layout.
117 void FullCodeGenerator::Generate() { 117 void FullCodeGenerator::Generate() {
118 CompilationInfo* info = info_; 118 CompilationInfo* info = info_;
119 handler_table_ = 119 handler_table_ =
120 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 120 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
121
122 InitializeFeedbackVector();
123
121 profiling_counter_ = isolate()->factory()->NewCell( 124 profiling_counter_ = isolate()->factory()->NewCell(
122 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 125 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
123 SetFunctionPosition(function()); 126 SetFunctionPosition(function());
124 Comment cmnt(masm_, "[ function compiled by full code generator"); 127 Comment cmnt(masm_, "[ function compiled by full code generator");
125 128
126 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 129 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
127 130
128 #ifdef DEBUG 131 #ifdef DEBUG
129 if (strlen(FLAG_stop_at) > 0 && 132 if (strlen(FLAG_stop_at) > 0 &&
130 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 133 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 } 178 }
176 } 179 }
177 180
178 bool function_in_register = true; 181 bool function_in_register = true;
179 182
180 // Possibly allocate a local context. 183 // Possibly allocate a local context.
181 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 184 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
182 if (heap_slots > 0) { 185 if (heap_slots > 0) {
183 Comment cmnt(masm_, "[ Allocate context"); 186 Comment cmnt(masm_, "[ Allocate context");
184 // Argument to NewContext is the function, which is still in rdi. 187 // Argument to NewContext is the function, which is still in rdi.
185 __ push(rdi);
186 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { 188 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
189 __ push(rdi);
187 __ Push(info->scope()->GetScopeInfo()); 190 __ Push(info->scope()->GetScopeInfo());
188 __ CallRuntime(Runtime::kNewGlobalContext, 2); 191 __ CallRuntime(Runtime::kNewGlobalContext, 2);
189 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { 192 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
190 FastNewContextStub stub(heap_slots); 193 FastNewContextStub stub(heap_slots);
191 __ CallStub(&stub); 194 __ CallStub(&stub);
192 } else { 195 } else {
196 __ push(rdi);
193 __ CallRuntime(Runtime::kNewFunctionContext, 1); 197 __ CallRuntime(Runtime::kNewFunctionContext, 1);
194 } 198 }
195 function_in_register = false; 199 function_in_register = false;
196 // Context is returned in both rax and rsi. It replaces the context 200 // Context is returned in rax. It replaces the context passed to us.
197 // passed to us. It's saved in the stack and kept live in rsi. 201 // It's saved in the stack and kept live in rsi.
198 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rsi); 202 __ movp(rsi, rax);
203 __ movp(Operand(rbp, StandardFrameConstants::kContextOffset), rax);
199 204
200 // Copy any necessary parameters into the context. 205 // Copy any necessary parameters into the context.
201 int num_parameters = info->scope()->num_parameters(); 206 int num_parameters = info->scope()->num_parameters();
202 for (int i = 0; i < num_parameters; i++) { 207 for (int i = 0; i < num_parameters; i++) {
203 Variable* var = scope()->parameter(i); 208 Variable* var = scope()->parameter(i);
204 if (var->IsContextSlot()) { 209 if (var->IsContextSlot()) {
205 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 210 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
206 (num_parameters - 1 - i) * kPointerSize; 211 (num_parameters - 1 - i) * kPointerSize;
207 // Load parameter from stack. 212 // Load parameter from stack.
208 __ movp(rax, Operand(rbp, parameter_offset)); 213 __ movp(rax, Operand(rbp, parameter_offset));
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
629 if (false_label_ != fall_through_) __ jmp(false_label_); 634 if (false_label_ != fall_through_) __ jmp(false_label_);
630 } 635 }
631 } 636 }
632 637
633 638
634 void FullCodeGenerator::DoTest(Expression* condition, 639 void FullCodeGenerator::DoTest(Expression* condition,
635 Label* if_true, 640 Label* if_true,
636 Label* if_false, 641 Label* if_false,
637 Label* fall_through) { 642 Label* fall_through) {
638 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); 643 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
639 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); 644 CallIC(ic, condition->test_id());
640 __ testq(result_register(), result_register()); 645 __ testq(result_register(), result_register());
641 // The stub returns nonzero for true. 646 // The stub returns nonzero for true.
642 Split(not_zero, if_true, if_false, fall_through); 647 Split(not_zero, if_true, if_false, fall_through);
643 } 648 }
644 649
645 650
646 void FullCodeGenerator::Split(Condition cc, 651 void FullCodeGenerator::Split(Condition cc,
647 Label* if_true, 652 Label* if_true,
648 Label* if_false, 653 Label* if_false,
649 Label* fall_through) { 654 Label* fall_through) {
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 __ cmpq(rdx, rax); 987 __ cmpq(rdx, rax);
983 __ j(not_equal, &next_test); 988 __ j(not_equal, &next_test);
984 __ Drop(1); // Switch value is no longer needed. 989 __ Drop(1); // Switch value is no longer needed.
985 __ jmp(clause->body_target()); 990 __ jmp(clause->body_target());
986 __ bind(&slow_case); 991 __ bind(&slow_case);
987 } 992 }
988 993
989 // Record position before stub call for type feedback. 994 // Record position before stub call for type feedback.
990 SetSourcePosition(clause->position()); 995 SetSourcePosition(clause->position());
991 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); 996 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
992 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); 997 CallIC(ic, clause->CompareId());
993 patch_site.EmitPatchInfo(); 998 patch_site.EmitPatchInfo();
994 999
995 Label skip; 1000 Label skip;
996 __ jmp(&skip, Label::kNear); 1001 __ jmp(&skip, Label::kNear);
997 PrepareForBailout(clause, TOS_REG); 1002 PrepareForBailout(clause, TOS_REG);
998 __ CompareRoot(rax, Heap::kTrueValueRootIndex); 1003 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
999 __ j(not_equal, &next_test); 1004 __ j(not_equal, &next_test);
1000 __ Drop(1); 1005 __ Drop(1);
1001 __ jmp(clause->body_target()); 1006 __ jmp(clause->body_target());
1002 __ bind(&skip); 1007 __ bind(&skip);
(...skipping 23 matching lines...) Expand all
1026 VisitStatements(clause->statements()); 1031 VisitStatements(clause->statements());
1027 } 1032 }
1028 1033
1029 __ bind(nested_statement.break_label()); 1034 __ bind(nested_statement.break_label());
1030 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1035 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1031 } 1036 }
1032 1037
1033 1038
1034 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 1039 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1035 Comment cmnt(masm_, "[ ForInStatement"); 1040 Comment cmnt(masm_, "[ ForInStatement");
1041 int slot = stmt->ForInFeedbackSlot();
1036 SetStatementPosition(stmt); 1042 SetStatementPosition(stmt);
1037 1043
1038 Label loop, exit; 1044 Label loop, exit;
1039 ForIn loop_statement(this, stmt); 1045 ForIn loop_statement(this, stmt);
1040 increment_loop_depth(); 1046 increment_loop_depth();
1041 1047
1042 // Get the object to enumerate over. If the object is null or undefined, skip 1048 // Get the object to enumerate over. If the object is null or undefined, skip
1043 // over the loop. See ECMA-262 version 5, section 12.6.4. 1049 // over the loop. See ECMA-262 version 5, section 12.6.4.
1044 VisitForAccumulatorValue(stmt->enumerable()); 1050 VisitForAccumulatorValue(stmt->enumerable());
1045 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 1051 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1114 __ jmp(&loop); 1120 __ jmp(&loop);
1115 1121
1116 __ bind(&no_descriptors); 1122 __ bind(&no_descriptors);
1117 __ addq(rsp, Immediate(kPointerSize)); 1123 __ addq(rsp, Immediate(kPointerSize));
1118 __ jmp(&exit); 1124 __ jmp(&exit);
1119 1125
1120 // We got a fixed array in register rax. Iterate through that. 1126 // We got a fixed array in register rax. Iterate through that.
1121 Label non_proxy; 1127 Label non_proxy;
1122 __ bind(&fixed_array); 1128 __ bind(&fixed_array);
1123 1129
1124 Handle<Cell> cell = isolate()->factory()->NewCell( 1130 Handle<Object> feedback = Handle<Object>(
1125 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker), 1131 Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
1126 isolate())); 1132 isolate());
1127 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); 1133 StoreFeedbackVectorSlot(slot, feedback);
1128 __ Move(rbx, cell);
1129 __ Move(FieldOperand(rbx, Cell::kValueOffset),
1130 Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker));
1131 1134
1135 // No need for a write barrier, we are storing a Smi in the feedback vector.
1136 __ Move(rbx, FeedbackVector());
1137 __ Move(FieldOperand(rbx, FixedArray::OffsetOfElementAt(slot)),
1138 Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker));
1132 __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check 1139 __ Move(rbx, Smi::FromInt(1)); // Smi indicates slow check
1133 __ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object 1140 __ movp(rcx, Operand(rsp, 0 * kPointerSize)); // Get enumerated object
1134 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1141 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1135 __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx); 1142 __ CmpObjectType(rcx, LAST_JS_PROXY_TYPE, rcx);
1136 __ j(above, &non_proxy); 1143 __ j(above, &non_proxy);
1137 __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy 1144 __ Move(rbx, Smi::FromInt(0)); // Zero indicates proxy
1138 __ bind(&non_proxy); 1145 __ bind(&non_proxy);
1139 __ push(rbx); // Smi 1146 __ push(rbx); // Smi
1140 __ push(rax); // Array 1147 __ push(rax); // Array
1141 __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset)); 1148 __ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 1437
1431 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1438 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1432 // Record position before possible IC call. 1439 // Record position before possible IC call.
1433 SetSourcePosition(proxy->position()); 1440 SetSourcePosition(proxy->position());
1434 Variable* var = proxy->var(); 1441 Variable* var = proxy->var();
1435 1442
1436 // Three cases: global variables, lookup variables, and all other types of 1443 // Three cases: global variables, lookup variables, and all other types of
1437 // variables. 1444 // variables.
1438 switch (var->location()) { 1445 switch (var->location()) {
1439 case Variable::UNALLOCATED: { 1446 case Variable::UNALLOCATED: {
1440 Comment cmnt(masm_, "Global variable"); 1447 Comment cmnt(masm_, "[ Global variable");
1441 // Use inline caching. Variable name is passed in rcx and the global 1448 // Use inline caching. Variable name is passed in rcx and the global
1442 // object on the stack. 1449 // object on the stack.
1443 __ Move(rcx, var->name()); 1450 __ Move(rcx, var->name());
1444 __ movp(rax, GlobalObjectOperand()); 1451 __ movp(rax, GlobalObjectOperand());
1445 CallLoadIC(CONTEXTUAL); 1452 CallLoadIC(CONTEXTUAL);
1446 context()->Plug(rax); 1453 context()->Plug(rax);
1447 break; 1454 break;
1448 } 1455 }
1449 1456
1450 case Variable::PARAMETER: 1457 case Variable::PARAMETER:
1451 case Variable::LOCAL: 1458 case Variable::LOCAL:
1452 case Variable::CONTEXT: { 1459 case Variable::CONTEXT: {
1453 Comment cmnt(masm_, var->IsContextSlot() ? "Context slot" : "Stack slot"); 1460 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot"
1461 : "[ Stack slot");
1454 if (var->binding_needs_init()) { 1462 if (var->binding_needs_init()) {
1455 // var->scope() may be NULL when the proxy is located in eval code and 1463 // var->scope() may be NULL when the proxy is located in eval code and
1456 // refers to a potential outside binding. Currently those bindings are 1464 // refers to a potential outside binding. Currently those bindings are
1457 // always looked up dynamically, i.e. in that case 1465 // always looked up dynamically, i.e. in that case
1458 // var->location() == LOOKUP. 1466 // var->location() == LOOKUP.
1459 // always holds. 1467 // always holds.
1460 ASSERT(var->scope() != NULL); 1468 ASSERT(var->scope() != NULL);
1461 1469
1462 // Check if the binding really needs an initialization check. The check 1470 // Check if the binding really needs an initialization check. The check
1463 // can be skipped in the following situation: we have a LET or CONST 1471 // can be skipped in the following situation: we have a LET or CONST
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1505 __ bind(&done); 1513 __ bind(&done);
1506 context()->Plug(rax); 1514 context()->Plug(rax);
1507 break; 1515 break;
1508 } 1516 }
1509 } 1517 }
1510 context()->Plug(var); 1518 context()->Plug(var);
1511 break; 1519 break;
1512 } 1520 }
1513 1521
1514 case Variable::LOOKUP: { 1522 case Variable::LOOKUP: {
1523 Comment cmnt(masm_, "[ Lookup slot");
1515 Label done, slow; 1524 Label done, slow;
1516 // Generate code for loading from variables potentially shadowed 1525 // Generate code for loading from variables potentially shadowed
1517 // by eval-introduced variables. 1526 // by eval-introduced variables.
1518 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); 1527 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1519 __ bind(&slow); 1528 __ bind(&slow);
1520 Comment cmnt(masm_, "Lookup slot");
1521 __ push(rsi); // Context. 1529 __ push(rsi); // Context.
1522 __ Push(var->name()); 1530 __ Push(var->name());
1523 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1531 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1524 __ bind(&done); 1532 __ bind(&done);
1525 context()->Plug(rax); 1533 context()->Plug(rax);
1526 break; 1534 break;
1527 } 1535 }
1528 } 1536 }
1529 } 1537 }
1530 1538
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1649 UNREACHABLE(); 1657 UNREACHABLE();
1650 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1658 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1651 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1659 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1652 // Fall through. 1660 // Fall through.
1653 case ObjectLiteral::Property::COMPUTED: 1661 case ObjectLiteral::Property::COMPUTED:
1654 if (key->value()->IsInternalizedString()) { 1662 if (key->value()->IsInternalizedString()) {
1655 if (property->emit_store()) { 1663 if (property->emit_store()) {
1656 VisitForAccumulatorValue(value); 1664 VisitForAccumulatorValue(value);
1657 __ Move(rcx, key->value()); 1665 __ Move(rcx, key->value());
1658 __ movp(rdx, Operand(rsp, 0)); 1666 __ movp(rdx, Operand(rsp, 0));
1659 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); 1667 CallStoreIC(key->LiteralFeedbackId());
1660 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1668 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1661 } else { 1669 } else {
1662 VisitForEffect(value); 1670 VisitForEffect(value);
1663 } 1671 }
1664 break; 1672 break;
1665 } 1673 }
1666 __ push(Operand(rsp, 0)); // Duplicate receiver. 1674 __ push(Operand(rsp, 0)); // Duplicate receiver.
1667 VisitForStackValue(key); 1675 VisitForStackValue(key);
1668 VisitForStackValue(value); 1676 VisitForStackValue(value);
1669 if (property->emit_store()) { 1677 if (property->emit_store()) {
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
2061 2069
2062 // receiver = iter; f = 'next'; arg = received; 2070 // receiver = iter; f = 'next'; arg = received;
2063 __ bind(&l_next); 2071 __ bind(&l_next);
2064 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next" 2072 __ LoadRoot(rcx, Heap::knext_stringRootIndex); // "next"
2065 __ push(rcx); 2073 __ push(rcx);
2066 __ push(Operand(rsp, 2 * kPointerSize)); // iter 2074 __ push(Operand(rsp, 2 * kPointerSize)); // iter
2067 __ push(rax); // received 2075 __ push(rax); // received
2068 2076
2069 // result = receiver[f](arg); 2077 // result = receiver[f](arg);
2070 __ bind(&l_call); 2078 __ bind(&l_call);
2071 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); 2079 __ movp(rdx, Operand(rsp, kPointerSize));
2072 CallIC(ic); 2080 __ movp(rax, Operand(rsp, 2 * kPointerSize));
2081 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2082 CallIC(ic, TypeFeedbackId::None());
2083 __ movp(rdi, rax);
2084 __ movp(Operand(rsp, 2 * kPointerSize), rdi);
2085 CallFunctionStub stub(1, CALL_AS_METHOD);
2086 __ CallStub(&stub);
2087
2073 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2088 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2074 __ Drop(1); // The key is still on the stack; drop it. 2089 __ Drop(1); // The function is still on the stack; drop it.
2075 2090
2076 // if (!result.done) goto l_try; 2091 // if (!result.done) goto l_try;
2077 __ bind(&l_loop); 2092 __ bind(&l_loop);
2078 __ push(rax); // save result 2093 __ push(rax); // save result
2079 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done" 2094 __ LoadRoot(rcx, Heap::kdone_stringRootIndex); // "done"
2080 CallLoadIC(NOT_CONTEXTUAL); // result.done in rax 2095 CallLoadIC(NOT_CONTEXTUAL); // result.done in rax
2081 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2096 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2082 CallIC(bool_ic); 2097 CallIC(bool_ic);
2083 __ testq(result_register(), result_register()); 2098 __ testq(result_register(), result_register());
2084 __ j(zero, &l_try); 2099 __ j(zero, &l_try);
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
2248 SetSourcePosition(prop->position()); 2263 SetSourcePosition(prop->position());
2249 Literal* key = prop->key()->AsLiteral(); 2264 Literal* key = prop->key()->AsLiteral();
2250 __ Move(rcx, key->value()); 2265 __ Move(rcx, key->value());
2251 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2266 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2252 } 2267 }
2253 2268
2254 2269
2255 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 2270 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2256 SetSourcePosition(prop->position()); 2271 SetSourcePosition(prop->position());
2257 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2272 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2258 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2273 CallIC(ic, prop->PropertyFeedbackId());
2259 } 2274 }
2260 2275
2261 2276
2262 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2277 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2263 Token::Value op, 2278 Token::Value op,
2264 OverwriteMode mode, 2279 OverwriteMode mode,
2265 Expression* left, 2280 Expression* left,
2266 Expression* right) { 2281 Expression* right) {
2267 // Do combined smi check of the operands. Left operand is on the 2282 // Do combined smi check of the operands. Left operand is on the
2268 // stack (popped into rdx). Right operand is in rax but moved into 2283 // stack (popped into rdx). Right operand is in rax but moved into
2269 // rcx to make the shifts easier. 2284 // rcx to make the shifts easier.
2270 Label done, stub_call, smi_case; 2285 Label done, stub_call, smi_case;
2271 __ pop(rdx); 2286 __ pop(rdx);
2272 __ movp(rcx, rax); 2287 __ movp(rcx, rax);
2273 __ or_(rax, rdx); 2288 __ or_(rax, rdx);
2274 JumpPatchSite patch_site(masm_); 2289 JumpPatchSite patch_site(masm_);
2275 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear); 2290 patch_site.EmitJumpIfSmi(rax, &smi_case, Label::kNear);
2276 2291
2277 __ bind(&stub_call); 2292 __ bind(&stub_call);
2278 __ movp(rax, rcx); 2293 __ movp(rax, rcx);
2279 BinaryOpICStub stub(op, mode); 2294 BinaryOpICStub stub(op, mode);
2280 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, 2295 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId());
2281 expr->BinaryOperationFeedbackId());
2282 patch_site.EmitPatchInfo(); 2296 patch_site.EmitPatchInfo();
2283 __ jmp(&done, Label::kNear); 2297 __ jmp(&done, Label::kNear);
2284 2298
2285 __ bind(&smi_case); 2299 __ bind(&smi_case);
2286 switch (op) { 2300 switch (op) {
2287 case Token::SAR: 2301 case Token::SAR:
2288 __ SmiShiftArithmeticRight(rax, rdx, rcx); 2302 __ SmiShiftArithmeticRight(rax, rdx, rcx);
2289 break; 2303 break;
2290 case Token::SHL: 2304 case Token::SHL:
2291 __ SmiShiftLeft(rax, rdx, rcx); 2305 __ SmiShiftLeft(rax, rdx, rcx);
(...skipping 28 matching lines...) Expand all
2320 context()->Plug(rax); 2334 context()->Plug(rax);
2321 } 2335 }
2322 2336
2323 2337
2324 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2338 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2325 Token::Value op, 2339 Token::Value op,
2326 OverwriteMode mode) { 2340 OverwriteMode mode) {
2327 __ pop(rdx); 2341 __ pop(rdx);
2328 BinaryOpICStub stub(op, mode); 2342 BinaryOpICStub stub(op, mode);
2329 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2343 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
2330 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, 2344 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId());
2331 expr->BinaryOperationFeedbackId());
2332 patch_site.EmitPatchInfo(); 2345 patch_site.EmitPatchInfo();
2333 context()->Plug(rax); 2346 context()->Plug(rax);
2334 } 2347 }
2335 2348
2336 2349
2337 void FullCodeGenerator::EmitAssignment(Expression* expr) { 2350 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2338 // Invalid left-hand sides are rewritten by the parser to have a 'throw 2351 // Invalid left-hand sides are rewritten by the parser to have a 'throw
2339 // ReferenceError' on the left-hand side. 2352 // ReferenceError' on the left-hand side.
2340 if (!expr->IsValidLeftHandSide()) { 2353 if (!expr->IsValidLeftHandSide()) {
2341 VisitForEffect(expr); 2354 VisitForEffect(expr);
(...skipping 17 matching lines...) Expand all
2359 EffectContext context(this); 2372 EffectContext context(this);
2360 EmitVariableAssignment(var, Token::ASSIGN); 2373 EmitVariableAssignment(var, Token::ASSIGN);
2361 break; 2374 break;
2362 } 2375 }
2363 case NAMED_PROPERTY: { 2376 case NAMED_PROPERTY: {
2364 __ push(rax); // Preserve value. 2377 __ push(rax); // Preserve value.
2365 VisitForAccumulatorValue(prop->obj()); 2378 VisitForAccumulatorValue(prop->obj());
2366 __ movp(rdx, rax); 2379 __ movp(rdx, rax);
2367 __ pop(rax); // Restore value. 2380 __ pop(rax); // Restore value.
2368 __ Move(rcx, prop->key()->AsLiteral()->value()); 2381 __ Move(rcx, prop->key()->AsLiteral()->value());
2369 CallStoreIC(NOT_CONTEXTUAL); 2382 CallStoreIC();
2370 break; 2383 break;
2371 } 2384 }
2372 case KEYED_PROPERTY: { 2385 case KEYED_PROPERTY: {
2373 __ push(rax); // Preserve value. 2386 __ push(rax); // Preserve value.
2374 VisitForStackValue(prop->obj()); 2387 VisitForStackValue(prop->obj());
2375 VisitForAccumulatorValue(prop->key()); 2388 VisitForAccumulatorValue(prop->key());
2376 __ movp(rcx, rax); 2389 __ movp(rcx, rax);
2377 __ pop(rdx); 2390 __ pop(rdx);
2378 __ pop(rax); // Restore value. 2391 __ pop(rax); // Restore value.
2379 Handle<Code> ic = is_classic_mode() 2392 Handle<Code> ic = is_classic_mode()
2380 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2393 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2381 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2394 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2382 CallIC(ic); 2395 CallIC(ic);
2383 break; 2396 break;
2384 } 2397 }
2385 } 2398 }
2386 context()->Plug(rax); 2399 context()->Plug(rax);
2387 } 2400 }
2388 2401
2389 2402
2403 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2404 Variable* var, MemOperand location) {
2405 __ movp(location, rax);
2406 if (var->IsContextSlot()) {
2407 __ movp(rdx, rax);
2408 __ RecordWriteContextSlot(
2409 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2410 }
2411 }
2412
2413
2414 void FullCodeGenerator::EmitCallStoreContextSlot(
2415 Handle<String> name, LanguageMode mode) {
2416 __ push(rax); // Value.
2417 __ push(rsi); // Context.
2418 __ Push(name);
2419 __ Push(Smi::FromInt(mode));
2420 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2421 }
2422
2423
2390 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2424 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2391 Token::Value op) { 2425 Token::Value op) {
2392 if (var->IsUnallocated()) { 2426 if (var->IsUnallocated()) {
2393 // Global var, const, or let. 2427 // Global var, const, or let.
2394 __ Move(rcx, var->name()); 2428 __ Move(rcx, var->name());
2395 __ movp(rdx, GlobalObjectOperand()); 2429 __ movp(rdx, GlobalObjectOperand());
2396 CallStoreIC(CONTEXTUAL); 2430 CallStoreIC();
2431
2397 } else if (op == Token::INIT_CONST) { 2432 } else if (op == Token::INIT_CONST) {
2398 // Const initializers need a write barrier. 2433 // Const initializers need a write barrier.
2399 ASSERT(!var->IsParameter()); // No const parameters. 2434 ASSERT(!var->IsParameter()); // No const parameters.
2400 if (var->IsStackLocal()) { 2435 if (var->IsLookupSlot()) {
2401 Label skip;
2402 __ movp(rdx, StackOperand(var));
2403 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2404 __ j(not_equal, &skip);
2405 __ movp(StackOperand(var), rax);
2406 __ bind(&skip);
2407 } else {
2408 ASSERT(var->IsContextSlot() || var->IsLookupSlot());
2409 // Like var declarations, const declarations are hoisted to function
2410 // scope. However, unlike var initializers, const initializers are
2411 // able to drill a hole to that function context, even from inside a
2412 // 'with' context. We thus bypass the normal static scope lookup for
2413 // var->IsContextSlot().
2414 __ push(rax); 2436 __ push(rax);
2415 __ push(rsi); 2437 __ push(rsi);
2416 __ Push(var->name()); 2438 __ Push(var->name());
2417 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2439 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2440 } else {
2441 ASSERT(var->IsStackLocal() || var->IsContextSlot());
2442 Label skip;
2443 MemOperand location = VarOperand(var, rcx);
2444 __ movp(rdx, location);
2445 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2446 __ j(not_equal, &skip);
2447 EmitStoreToStackLocalOrContextSlot(var, location);
2448 __ bind(&skip);
2418 } 2449 }
2419 2450
2420 } else if (var->mode() == LET && op != Token::INIT_LET) { 2451 } else if (var->mode() == LET && op != Token::INIT_LET) {
2421 // Non-initializing assignment to let variable needs a write barrier. 2452 // Non-initializing assignment to let variable needs a write barrier.
2422 if (var->IsLookupSlot()) { 2453 if (var->IsLookupSlot()) {
2423 __ push(rax); // Value. 2454 EmitCallStoreContextSlot(var->name(), language_mode());
2424 __ push(rsi); // Context.
2425 __ Push(var->name());
2426 __ Push(Smi::FromInt(language_mode()));
2427 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2428 } else { 2455 } else {
2429 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2456 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2430 Label assign; 2457 Label assign;
2431 MemOperand location = VarOperand(var, rcx); 2458 MemOperand location = VarOperand(var, rcx);
2432 __ movp(rdx, location); 2459 __ movp(rdx, location);
2433 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2460 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2434 __ j(not_equal, &assign, Label::kNear); 2461 __ j(not_equal, &assign, Label::kNear);
2435 __ Push(var->name()); 2462 __ Push(var->name());
2436 __ CallRuntime(Runtime::kThrowReferenceError, 1); 2463 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2437 __ bind(&assign); 2464 __ bind(&assign);
2438 __ movp(location, rax); 2465 EmitStoreToStackLocalOrContextSlot(var, location);
2439 if (var->IsContextSlot()) {
2440 __ movp(rdx, rax);
2441 __ RecordWriteContextSlot(
2442 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2443 }
2444 } 2466 }
2445 2467
2446 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { 2468 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
2447 // Assignment to var or initializing assignment to let/const 2469 // Assignment to var or initializing assignment to let/const
2448 // in harmony mode. 2470 // in harmony mode.
2449 if (var->IsStackAllocated() || var->IsContextSlot()) { 2471 if (var->IsLookupSlot()) {
2472 EmitCallStoreContextSlot(var->name(), language_mode());
2473 } else {
2474 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2450 MemOperand location = VarOperand(var, rcx); 2475 MemOperand location = VarOperand(var, rcx);
2451 if (generate_debug_code_ && op == Token::INIT_LET) { 2476 if (generate_debug_code_ && op == Token::INIT_LET) {
2452 // Check for an uninitialized let binding. 2477 // Check for an uninitialized let binding.
2453 __ movp(rdx, location); 2478 __ movp(rdx, location);
2454 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); 2479 __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex);
2455 __ Check(equal, kLetBindingReInitialization); 2480 __ Check(equal, kLetBindingReInitialization);
2456 } 2481 }
2457 // Perform the assignment. 2482 EmitStoreToStackLocalOrContextSlot(var, location);
2458 __ movp(location, rax);
2459 if (var->IsContextSlot()) {
2460 __ movp(rdx, rax);
2461 __ RecordWriteContextSlot(
2462 rcx, Context::SlotOffset(var->index()), rdx, rbx, kDontSaveFPRegs);
2463 }
2464 } else {
2465 ASSERT(var->IsLookupSlot());
2466 __ push(rax); // Value.
2467 __ push(rsi); // Context.
2468 __ Push(var->name());
2469 __ Push(Smi::FromInt(language_mode()));
2470 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2471 } 2483 }
2472 } 2484 }
2473 // Non-initializing assignments to consts are ignored. 2485 // Non-initializing assignments to consts are ignored.
2474 } 2486 }
2475 2487
2476 2488
2477 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2489 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2478 // Assignment to a property, using a named store IC. 2490 // Assignment to a property, using a named store IC.
2479 Property* prop = expr->target()->AsProperty(); 2491 Property* prop = expr->target()->AsProperty();
2480 ASSERT(prop != NULL); 2492 ASSERT(prop != NULL);
2481 ASSERT(prop->key()->AsLiteral() != NULL); 2493 ASSERT(prop->key()->AsLiteral() != NULL);
2482 2494
2483 // Record source code position before IC call. 2495 // Record source code position before IC call.
2484 SetSourcePosition(expr->position()); 2496 SetSourcePosition(expr->position());
2485 __ Move(rcx, prop->key()->AsLiteral()->value()); 2497 __ Move(rcx, prop->key()->AsLiteral()->value());
2486 __ pop(rdx); 2498 __ pop(rdx);
2487 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); 2499 CallStoreIC(expr->AssignmentFeedbackId());
2488 2500
2489 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2501 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2490 context()->Plug(rax); 2502 context()->Plug(rax);
2491 } 2503 }
2492 2504
2493 2505
2494 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2506 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2495 // Assignment to a property, using a keyed store IC. 2507 // Assignment to a property, using a keyed store IC.
2496 2508
2497 __ pop(rcx); 2509 __ pop(rcx);
2498 __ pop(rdx); 2510 __ pop(rdx);
2499 // Record source code position before IC call. 2511 // Record source code position before IC call.
2500 SetSourcePosition(expr->position()); 2512 SetSourcePosition(expr->position());
2501 Handle<Code> ic = is_classic_mode() 2513 Handle<Code> ic = is_classic_mode()
2502 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2514 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2503 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2515 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2504 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); 2516 CallIC(ic, expr->AssignmentFeedbackId());
2505 2517
2506 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2518 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2507 context()->Plug(rax); 2519 context()->Plug(rax);
2508 } 2520 }
2509 2521
2510 2522
2511 void FullCodeGenerator::VisitProperty(Property* expr) { 2523 void FullCodeGenerator::VisitProperty(Property* expr) {
2512 Comment cmnt(masm_, "[ Property"); 2524 Comment cmnt(masm_, "[ Property");
2513 Expression* key = expr->key(); 2525 Expression* key = expr->key();
2514 2526
2515 if (key->IsPropertyName()) { 2527 if (key->IsPropertyName()) {
2516 VisitForAccumulatorValue(expr->obj()); 2528 VisitForAccumulatorValue(expr->obj());
2517 EmitNamedPropertyLoad(expr); 2529 EmitNamedPropertyLoad(expr);
2518 PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2530 PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2519 context()->Plug(rax); 2531 context()->Plug(rax);
2520 } else { 2532 } else {
2521 VisitForStackValue(expr->obj()); 2533 VisitForStackValue(expr->obj());
2522 VisitForAccumulatorValue(expr->key()); 2534 VisitForAccumulatorValue(expr->key());
2523 __ pop(rdx); 2535 __ pop(rdx);
2524 EmitKeyedPropertyLoad(expr); 2536 EmitKeyedPropertyLoad(expr);
2525 context()->Plug(rax); 2537 context()->Plug(rax);
2526 } 2538 }
2527 } 2539 }
2528 2540
2529 2541
2530 void FullCodeGenerator::CallIC(Handle<Code> code, 2542 void FullCodeGenerator::CallIC(Handle<Code> code,
2531 ContextualMode mode,
2532 TypeFeedbackId ast_id) { 2543 TypeFeedbackId ast_id) {
2533 ic_total_count_++; 2544 ic_total_count_++;
2534 ASSERT(mode != CONTEXTUAL || ast_id.IsNone());
2535 __ call(code, RelocInfo::CODE_TARGET, ast_id); 2545 __ call(code, RelocInfo::CODE_TARGET, ast_id);
2536 } 2546 }
2537 2547
2538 2548
2539 void FullCodeGenerator::EmitCallWithIC(Call* expr, 2549 // Code common for calls using the IC.
2540 Handle<Object> name, 2550 void FullCodeGenerator::EmitCallWithIC(Call* expr) {
2541 ContextualMode mode) { 2551 Expression* callee = expr->expression();
2542 // Code common for calls using the IC.
2543 ZoneList<Expression*>* args = expr->arguments(); 2552 ZoneList<Expression*>* args = expr->arguments();
2544 int arg_count = args->length(); 2553 int arg_count = args->length();
2554
2555 CallFunctionFlags flags;
2556 // Get the target function;
2557 if (callee->IsVariableProxy()) {
2558 { StackValueContext context(this);
2559 EmitVariableLoad(callee->AsVariableProxy());
2560 PrepareForBailout(callee, NO_REGISTERS);
2561 }
2562 // Push undefined as receiver. This is patched in the method prologue if it
2563 // is a classic mode method.
2564 __ Push(isolate()->factory()->undefined_value());
2565 flags = NO_CALL_FUNCTION_FLAGS;
2566 } else {
2567 // Load the function from the receiver.
2568 ASSERT(callee->IsProperty());
2569 __ movp(rax, Operand(rsp, 0));
2570 EmitNamedPropertyLoad(callee->AsProperty());
2571 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2572 // Push the target function under the receiver.
2573 __ push(Operand(rsp, 0));
2574 __ movp(Operand(rsp, kPointerSize), rax);
2575 flags = CALL_AS_METHOD;
2576 }
2577
2578 // Load the arguments.
2545 { PreservePositionScope scope(masm()->positions_recorder()); 2579 { PreservePositionScope scope(masm()->positions_recorder());
2546 for (int i = 0; i < arg_count; i++) { 2580 for (int i = 0; i < arg_count; i++) {
2547 VisitForStackValue(args->at(i)); 2581 VisitForStackValue(args->at(i));
2548 } 2582 }
2549 __ Move(rcx, name);
2550 } 2583 }
2584
2551 // Record source position for debugger. 2585 // Record source position for debugger.
2552 SetSourcePosition(expr->position()); 2586 SetSourcePosition(expr->position());
2553 // Call the IC initialization code. 2587 CallFunctionStub stub(arg_count, flags);
2554 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); 2588 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2555 TypeFeedbackId ast_id = mode == CONTEXTUAL 2589 __ CallStub(&stub);
2556 ? TypeFeedbackId::None() 2590
2557 : expr->CallFeedbackId();
2558 CallIC(ic, mode, ast_id);
2559 RecordJSReturnSite(expr); 2591 RecordJSReturnSite(expr);
2592
2560 // Restore context register. 2593 // Restore context register.
2561 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2594 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2562 context()->Plug(rax); 2595
2596 context()->DropAndPlug(1, rax);
2563 } 2597 }
2564 2598
2565 2599
2600 // Common code for calls using the IC.
2566 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2601 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2567 Expression* key) { 2602 Expression* key) {
2568 // Load the key. 2603 // Load the key.
2569 VisitForAccumulatorValue(key); 2604 VisitForAccumulatorValue(key);
2570 2605
2571 // Swap the name of the function and the receiver on the stack to follow 2606 Expression* callee = expr->expression();
2572 // the calling convention for call ICs. 2607 ZoneList<Expression*>* args = expr->arguments();
2573 __ pop(rcx); 2608 int arg_count = args->length();
2574 __ push(rax); 2609
2575 __ push(rcx); 2610 // Load the function from the receiver.
2611 ASSERT(callee->IsProperty());
2612 __ movp(rdx, Operand(rsp, 0));
2613 EmitKeyedPropertyLoad(callee->AsProperty());
2614 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2615
2616 // Push the target function under the receiver.
2617 __ push(Operand(rsp, 0));
2618 __ movp(Operand(rsp, kPointerSize), rax);
2576 2619
2577 // Load the arguments. 2620 // Load the arguments.
2578 ZoneList<Expression*>* args = expr->arguments();
2579 int arg_count = args->length();
2580 { PreservePositionScope scope(masm()->positions_recorder()); 2621 { PreservePositionScope scope(masm()->positions_recorder());
2581 for (int i = 0; i < arg_count; i++) { 2622 for (int i = 0; i < arg_count; i++) {
2582 VisitForStackValue(args->at(i)); 2623 VisitForStackValue(args->at(i));
2583 } 2624 }
2584 } 2625 }
2626
2585 // Record source position for debugger. 2627 // Record source position for debugger.
2586 SetSourcePosition(expr->position()); 2628 SetSourcePosition(expr->position());
2587 // Call the IC initialization code. 2629 CallFunctionStub stub(arg_count, CALL_AS_METHOD);
2588 Handle<Code> ic = 2630 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2589 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); 2631 __ CallStub(&stub);
2590 __ movp(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. 2632
2591 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId());
2592 RecordJSReturnSite(expr); 2633 RecordJSReturnSite(expr);
2593 // Restore context register. 2634 // Restore context register.
2594 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2635 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2595 context()->DropAndPlug(1, rax); // Drop the key still on the stack. 2636
2637 context()->DropAndPlug(1, rax);
2596 } 2638 }
2597 2639
2598 2640
2599 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 2641 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
2600 // Code common for calls using the call stub. 2642 // Code common for calls using the call stub.
2601 ZoneList<Expression*>* args = expr->arguments(); 2643 ZoneList<Expression*>* args = expr->arguments();
2602 int arg_count = args->length(); 2644 int arg_count = args->length();
2603 { PreservePositionScope scope(masm()->positions_recorder()); 2645 { PreservePositionScope scope(masm()->positions_recorder());
2604 for (int i = 0; i < arg_count; i++) { 2646 for (int i = 0; i < arg_count; i++) {
2605 VisitForStackValue(args->at(i)); 2647 VisitForStackValue(args->at(i));
2606 } 2648 }
2607 } 2649 }
2608 // Record source position for debugger. 2650 // Record source position for debugger.
2609 SetSourcePosition(expr->position()); 2651 SetSourcePosition(expr->position());
2610 2652
2611 Handle<Object> uninitialized = 2653 Handle<Object> uninitialized =
2612 TypeFeedbackCells::UninitializedSentinel(isolate()); 2654 TypeFeedbackInfo::UninitializedSentinel(isolate());
2613 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); 2655 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
2614 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell); 2656 __ Move(rbx, FeedbackVector());
2615 __ Move(rbx, cell); 2657 __ Move(rdx, Smi::FromInt(expr->CallFeedbackSlot()));
2616 2658
2617 // Record call targets in unoptimized code. 2659 // Record call targets in unoptimized code.
2618 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); 2660 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
2619 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2661 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2620 __ CallStub(&stub, expr->CallFeedbackId()); 2662 __ CallStub(&stub);
2621 RecordJSReturnSite(expr); 2663 RecordJSReturnSite(expr);
2622 // Restore context register. 2664 // Restore context register.
2623 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2665 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2624 // Discard the function left on TOS. 2666 // Discard the function left on TOS.
2625 context()->DropAndPlug(1, rax); 2667 context()->DropAndPlug(1, rax);
2626 } 2668 }
2627 2669
2628 2670
2629 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2671 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2630 // Push copy of the first argument or undefined if it doesn't exist. 2672 // Push copy of the first argument or undefined if it doesn't exist.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2688 // Record source position for debugger. 2730 // Record source position for debugger.
2689 SetSourcePosition(expr->position()); 2731 SetSourcePosition(expr->position());
2690 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); 2732 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
2691 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize)); 2733 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
2692 __ CallStub(&stub); 2734 __ CallStub(&stub);
2693 RecordJSReturnSite(expr); 2735 RecordJSReturnSite(expr);
2694 // Restore context register. 2736 // Restore context register.
2695 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 2737 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
2696 context()->DropAndPlug(1, rax); 2738 context()->DropAndPlug(1, rax);
2697 } else if (call_type == Call::GLOBAL_CALL) { 2739 } else if (call_type == Call::GLOBAL_CALL) {
2698 // Call to a global variable. Push global object as receiver for the 2740 EmitCallWithIC(expr);
2699 // call IC lookup. 2741
2700 __ push(GlobalObjectOperand());
2701 VariableProxy* proxy = callee->AsVariableProxy();
2702 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
2703 } else if (call_type == Call::LOOKUP_SLOT_CALL) { 2742 } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2704 // Call to a lookup slot (dynamically introduced variable). 2743 // Call to a lookup slot (dynamically introduced variable).
2705 VariableProxy* proxy = callee->AsVariableProxy(); 2744 VariableProxy* proxy = callee->AsVariableProxy();
2706 Label slow, done; 2745 Label slow, done;
2707 2746
2708 { PreservePositionScope scope(masm()->positions_recorder()); 2747 { PreservePositionScope scope(masm()->positions_recorder());
2709 // Generate code for loading from variables potentially shadowed by 2748 // Generate code for loading from variables potentially shadowed by
2710 // eval-introduced variables. 2749 // eval-introduced variables.
2711 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2750 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2712 } 2751 }
(...skipping 22 matching lines...) Expand all
2735 2774
2736 // The receiver is either the global receiver or an object found by 2775 // The receiver is either the global receiver or an object found by
2737 // LoadContextSlot. 2776 // LoadContextSlot.
2738 EmitCallWithStub(expr); 2777 EmitCallWithStub(expr);
2739 } else if (call_type == Call::PROPERTY_CALL) { 2778 } else if (call_type == Call::PROPERTY_CALL) {
2740 Property* property = callee->AsProperty(); 2779 Property* property = callee->AsProperty();
2741 { PreservePositionScope scope(masm()->positions_recorder()); 2780 { PreservePositionScope scope(masm()->positions_recorder());
2742 VisitForStackValue(property->obj()); 2781 VisitForStackValue(property->obj());
2743 } 2782 }
2744 if (property->key()->IsPropertyName()) { 2783 if (property->key()->IsPropertyName()) {
2745 EmitCallWithIC(expr, 2784 EmitCallWithIC(expr);
2746 property->key()->AsLiteral()->value(),
2747 NOT_CONTEXTUAL);
2748 } else { 2785 } else {
2749 EmitKeyedCallWithIC(expr, property->key()); 2786 EmitKeyedCallWithIC(expr, property->key());
2750 } 2787 }
2751 } else { 2788 } else {
2752 ASSERT(call_type == Call::OTHER_CALL); 2789 ASSERT(call_type == Call::OTHER_CALL);
2753 // Call to an arbitrary expression not handled specially above. 2790 // Call to an arbitrary expression not handled specially above.
2754 { PreservePositionScope scope(masm()->positions_recorder()); 2791 { PreservePositionScope scope(masm()->positions_recorder());
2755 VisitForStackValue(callee); 2792 VisitForStackValue(callee);
2756 } 2793 }
2757 __ PushRoot(Heap::kUndefinedValueRootIndex); 2794 __ PushRoot(Heap::kUndefinedValueRootIndex);
(...skipping 29 matching lines...) Expand all
2787 // Call the construct call builtin that handles allocation and 2824 // Call the construct call builtin that handles allocation and
2788 // constructor invocation. 2825 // constructor invocation.
2789 SetSourcePosition(expr->position()); 2826 SetSourcePosition(expr->position());
2790 2827
2791 // Load function and argument count into rdi and rax. 2828 // Load function and argument count into rdi and rax.
2792 __ Set(rax, arg_count); 2829 __ Set(rax, arg_count);
2793 __ movp(rdi, Operand(rsp, arg_count * kPointerSize)); 2830 __ movp(rdi, Operand(rsp, arg_count * kPointerSize));
2794 2831
2795 // Record call targets in unoptimized code, but not in the snapshot. 2832 // Record call targets in unoptimized code, but not in the snapshot.
2796 Handle<Object> uninitialized = 2833 Handle<Object> uninitialized =
2797 TypeFeedbackCells::UninitializedSentinel(isolate()); 2834 TypeFeedbackInfo::UninitializedSentinel(isolate());
2798 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); 2835 StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
2799 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell); 2836 __ Move(rbx, FeedbackVector());
2800 __ Move(rbx, cell); 2837 __ Move(rdx, Smi::FromInt(expr->CallNewFeedbackSlot()));
2801 2838
2802 CallConstructStub stub(RECORD_CALL_TARGET); 2839 CallConstructStub stub(RECORD_CALL_TARGET);
2803 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); 2840 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
2804 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2841 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2805 context()->Plug(rax); 2842 context()->Plug(rax);
2806 } 2843 }
2807 2844
2808 2845
2809 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 2846 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2810 ZoneList<Expression*>* args = expr->arguments(); 2847 ZoneList<Expression*>* args = expr->arguments();
(...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after
3355 __ movp(scratch, stamp_operand); 3392 __ movp(scratch, stamp_operand);
3356 __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); 3393 __ cmpq(scratch, FieldOperand(object, JSDate::kCacheStampOffset));
3357 __ j(not_equal, &runtime, Label::kNear); 3394 __ j(not_equal, &runtime, Label::kNear);
3358 __ movp(result, FieldOperand(object, JSDate::kValueOffset + 3395 __ movp(result, FieldOperand(object, JSDate::kValueOffset +
3359 kPointerSize * index->value())); 3396 kPointerSize * index->value()));
3360 __ jmp(&done); 3397 __ jmp(&done);
3361 } 3398 }
3362 __ bind(&runtime); 3399 __ bind(&runtime);
3363 __ PrepareCallCFunction(2); 3400 __ PrepareCallCFunction(2);
3364 __ movp(arg_reg_1, object); 3401 __ movp(arg_reg_1, object);
3365 __ Move(arg_reg_2, index, RelocInfo::NONE64); 3402 __ Move(arg_reg_2, index, Assembler::RelocInfoNone());
3366 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2); 3403 __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
3367 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 3404 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
3368 __ jmp(&done); 3405 __ jmp(&done);
3369 } 3406 }
3370 3407
3371 __ bind(&not_date_object); 3408 __ bind(&not_date_object);
3372 __ CallRuntime(Runtime::kThrowNotDateError, 0); 3409 __ CallRuntime(Runtime::kThrowNotDateError, 0);
3373 __ bind(&done); 3410 __ bind(&done);
3374 context()->Plug(rax); 3411 context()->Plug(rax);
3375 } 3412 }
3376 3413
3377 3414
3378 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) { 3415 void FullCodeGenerator::EmitOneByteSeqStringSetChar(CallRuntime* expr) {
3379 ZoneList<Expression*>* args = expr->arguments(); 3416 ZoneList<Expression*>* args = expr->arguments();
3380 ASSERT_EQ(3, args->length()); 3417 ASSERT_EQ(3, args->length());
3381 3418
3382 Register string = rax; 3419 Register string = rax;
3383 Register index = rbx; 3420 Register index = rbx;
3384 Register value = rcx; 3421 Register value = rcx;
3385 3422
3386 VisitForStackValue(args->at(1)); // index 3423 VisitForStackValue(args->at(1)); // index
3387 VisitForStackValue(args->at(2)); // value 3424 VisitForStackValue(args->at(2)); // value
3388 VisitForAccumulatorValue(args->at(0)); // string 3425 VisitForAccumulatorValue(args->at(0)); // string
3389 __ pop(value); 3426 __ pop(value);
3390 __ pop(index); 3427 __ pop(index);
3391 3428
3392 if (FLAG_debug_code) { 3429 if (FLAG_debug_code) {
3393 __ ThrowIf(NegateCondition(__ CheckSmi(value)), kNonSmiValue); 3430 __ Check(__ CheckSmi(value), kNonSmiValue);
3394 __ ThrowIf(NegateCondition(__ CheckSmi(index)), kNonSmiValue); 3431 __ Check(__ CheckSmi(index), kNonSmiValue);
3395 } 3432 }
3396 3433
3397 __ SmiToInteger32(value, value); 3434 __ SmiToInteger32(value, value);
3398 __ SmiToInteger32(index, index); 3435 __ SmiToInteger32(index, index);
3399 3436
3400 if (FLAG_debug_code) { 3437 if (FLAG_debug_code) {
3401 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 3438 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3402 __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); 3439 __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
3403 } 3440 }
3404 3441
(...skipping 11 matching lines...) Expand all
3416 Register index = rbx; 3453 Register index = rbx;
3417 Register value = rcx; 3454 Register value = rcx;
3418 3455
3419 VisitForStackValue(args->at(1)); // index 3456 VisitForStackValue(args->at(1)); // index
3420 VisitForStackValue(args->at(2)); // value 3457 VisitForStackValue(args->at(2)); // value
3421 VisitForAccumulatorValue(args->at(0)); // string 3458 VisitForAccumulatorValue(args->at(0)); // string
3422 __ pop(value); 3459 __ pop(value);
3423 __ pop(index); 3460 __ pop(index);
3424 3461
3425 if (FLAG_debug_code) { 3462 if (FLAG_debug_code) {
3426 __ ThrowIf(NegateCondition(__ CheckSmi(value)), kNonSmiValue); 3463 __ Check(__ CheckSmi(value), kNonSmiValue);
3427 __ ThrowIf(NegateCondition(__ CheckSmi(index)), kNonSmiValue); 3464 __ Check(__ CheckSmi(index), kNonSmiValue);
3428 } 3465 }
3429 3466
3430 __ SmiToInteger32(value, value); 3467 __ SmiToInteger32(value, value);
3431 __ SmiToInteger32(index, index); 3468 __ SmiToInteger32(index, index);
3432 3469
3433 if (FLAG_debug_code) { 3470 if (FLAG_debug_code) {
3434 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 3471 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3435 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); 3472 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
3436 } 3473 }
3437 3474
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
3603 generator.GenerateSlow(masm_, call_helper); 3640 generator.GenerateSlow(masm_, call_helper);
3604 3641
3605 __ bind(&done); 3642 __ bind(&done);
3606 context()->Plug(result); 3643 context()->Plug(result);
3607 } 3644 }
3608 3645
3609 3646
3610 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 3647 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3611 ZoneList<Expression*>* args = expr->arguments(); 3648 ZoneList<Expression*>* args = expr->arguments();
3612 ASSERT_EQ(2, args->length()); 3649 ASSERT_EQ(2, args->length());
3650 VisitForStackValue(args->at(0));
3651 VisitForAccumulatorValue(args->at(1));
3613 3652
3614 if (FLAG_new_string_add) { 3653 __ pop(rdx);
3615 VisitForStackValue(args->at(0)); 3654 StringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED);
3616 VisitForAccumulatorValue(args->at(1)); 3655 __ CallStub(&stub);
3617
3618 __ pop(rdx);
3619 NewStringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED);
3620 __ CallStub(&stub);
3621 } else {
3622 VisitForStackValue(args->at(0));
3623 VisitForStackValue(args->at(1));
3624
3625 StringAddStub stub(STRING_ADD_CHECK_BOTH);
3626 __ CallStub(&stub);
3627 }
3628 context()->Plug(rax); 3656 context()->Plug(rax);
3629 } 3657 }
3630 3658
3631 3659
3632 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 3660 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3633 ZoneList<Expression*>* args = expr->arguments(); 3661 ZoneList<Expression*>* args = expr->arguments();
3634 ASSERT_EQ(2, args->length()); 3662 ASSERT_EQ(2, args->length());
3635 3663
3636 VisitForStackValue(args->at(0)); 3664 VisitForStackValue(args->at(0));
3637 VisitForStackValue(args->at(1)); 3665 VisitForStackValue(args->at(1));
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
3693 context()->Plug(rax); 3721 context()->Plug(rax);
3694 } 3722 }
3695 3723
3696 3724
3697 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3725 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3698 RegExpConstructResultStub stub; 3726 RegExpConstructResultStub stub;
3699 ZoneList<Expression*>* args = expr->arguments(); 3727 ZoneList<Expression*>* args = expr->arguments();
3700 ASSERT(args->length() == 3); 3728 ASSERT(args->length() == 3);
3701 VisitForStackValue(args->at(0)); 3729 VisitForStackValue(args->at(0));
3702 VisitForStackValue(args->at(1)); 3730 VisitForStackValue(args->at(1));
3703 VisitForStackValue(args->at(2)); 3731 VisitForAccumulatorValue(args->at(2));
3732 __ pop(rbx);
3733 __ pop(rcx);
3704 __ CallStub(&stub); 3734 __ CallStub(&stub);
3705 context()->Plug(rax); 3735 context()->Plug(rax);
3706 } 3736 }
3707 3737
3708 3738
3709 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 3739 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3710 ZoneList<Expression*>* args = expr->arguments(); 3740 ZoneList<Expression*>* args = expr->arguments();
3711 ASSERT_EQ(2, args->length()); 3741 ASSERT_EQ(2, args->length());
3712 3742
3713 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3743 ASSERT_NE(NULL, args->at(0)->AsLiteral());
(...skipping 15 matching lines...) Expand all
3729 Register tmp = rcx; 3759 Register tmp = rcx;
3730 __ movp(cache, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX)); 3760 __ movp(cache, ContextOperand(rsi, Context::GLOBAL_OBJECT_INDEX));
3731 __ movp(cache, 3761 __ movp(cache,
3732 FieldOperand(cache, GlobalObject::kNativeContextOffset)); 3762 FieldOperand(cache, GlobalObject::kNativeContextOffset));
3733 __ movp(cache, 3763 __ movp(cache,
3734 ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 3764 ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3735 __ movp(cache, 3765 __ movp(cache,
3736 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3766 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3737 3767
3738 Label done, not_found; 3768 Label done, not_found;
3739 // tmp now holds finger offset as a smi.
3740 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3769 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3741 __ movp(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 3770 __ movp(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3771 // tmp now holds finger offset as a smi.
3742 SmiIndex index = 3772 SmiIndex index =
3743 __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2); 3773 __ SmiToIndex(kScratchRegister, tmp, kPointerSizeLog2);
3744 __ cmpq(key, FieldOperand(cache, 3774 __ cmpq(key, FieldOperand(cache,
3745 index.reg, 3775 index.reg,
3746 index.scale, 3776 index.scale,
3747 FixedArray::kHeaderSize)); 3777 FixedArray::kHeaderSize));
3748 __ j(not_equal, &not_found, Label::kNear); 3778 __ j(not_equal, &not_found, Label::kNear);
3749 __ movp(rax, FieldOperand(cache, 3779 __ movp(rax, FieldOperand(cache,
3750 index.reg, 3780 index.reg,
3751 index.scale, 3781 index.scale,
3752 FixedArray::kHeaderSize + kPointerSize)); 3782 FixedArray::kHeaderSize + kPointerSize));
3753 __ jmp(&done, Label::kNear); 3783 __ jmp(&done, Label::kNear);
3754 3784
3755 __ bind(&not_found); 3785 __ bind(&not_found);
3756 // Call runtime to perform the lookup. 3786 // Call runtime to perform the lookup.
3757 __ push(cache); 3787 __ push(cache);
3758 __ push(key); 3788 __ push(key);
3759 __ CallRuntime(Runtime::kGetFromCache, 2); 3789 __ CallRuntime(Runtime::kGetFromCache, 2);
3760 3790
3761 __ bind(&done); 3791 __ bind(&done);
3762 context()->Plug(rax); 3792 context()->Plug(rax);
3763 } 3793 }
3764 3794
3765 3795
3766 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
3767 ZoneList<Expression*>* args = expr->arguments();
3768 ASSERT_EQ(2, args->length());
3769
3770 Register right = rax;
3771 Register left = rbx;
3772 Register tmp = rcx;
3773
3774 VisitForStackValue(args->at(0));
3775 VisitForAccumulatorValue(args->at(1));
3776 __ pop(left);
3777
3778 Label done, fail, ok;
3779 __ cmpq(left, right);
3780 __ j(equal, &ok, Label::kNear);
3781 // Fail if either is a non-HeapObject.
3782 Condition either_smi = masm()->CheckEitherSmi(left, right, tmp);
3783 __ j(either_smi, &fail, Label::kNear);
3784 __ j(zero, &fail, Label::kNear);
3785 __ movp(tmp, FieldOperand(left, HeapObject::kMapOffset));
3786 __ cmpb(FieldOperand(tmp, Map::kInstanceTypeOffset),
3787 Immediate(JS_REGEXP_TYPE));
3788 __ j(not_equal, &fail, Label::kNear);
3789 __ cmpq(tmp, FieldOperand(right, HeapObject::kMapOffset));
3790 __ j(not_equal, &fail, Label::kNear);
3791 __ movp(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3792 __ cmpq(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3793 __ j(equal, &ok, Label::kNear);
3794 __ bind(&fail);
3795 __ Move(rax, isolate()->factory()->false_value());
3796 __ jmp(&done, Label::kNear);
3797 __ bind(&ok);
3798 __ Move(rax, isolate()->factory()->true_value());
3799 __ bind(&done);
3800
3801 context()->Plug(rax);
3802 }
3803
3804
3805 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 3796 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3806 ZoneList<Expression*>* args = expr->arguments(); 3797 ZoneList<Expression*>* args = expr->arguments();
3807 ASSERT(args->length() == 1); 3798 ASSERT(args->length() == 1);
3808 3799
3809 VisitForAccumulatorValue(args->at(0)); 3800 VisitForAccumulatorValue(args->at(0));
3810 3801
3811 Label materialize_true, materialize_false; 3802 Label materialize_true, materialize_false;
3812 Label* if_true = NULL; 3803 Label* if_true = NULL;
3813 Label* if_false = NULL; 3804 Label* if_false = NULL;
3814 Label* fall_through = NULL; 3805 Label* fall_through = NULL;
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
4128 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 4119 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4129 Handle<String> name = expr->name(); 4120 Handle<String> name = expr->name();
4130 if (name->length() > 0 && name->Get(0) == '_') { 4121 if (name->length() > 0 && name->Get(0) == '_') {
4131 Comment cmnt(masm_, "[ InlineRuntimeCall"); 4122 Comment cmnt(masm_, "[ InlineRuntimeCall");
4132 EmitInlineRuntimeCall(expr); 4123 EmitInlineRuntimeCall(expr);
4133 return; 4124 return;
4134 } 4125 }
4135 4126
4136 Comment cmnt(masm_, "[ CallRuntime"); 4127 Comment cmnt(masm_, "[ CallRuntime");
4137 ZoneList<Expression*>* args = expr->arguments(); 4128 ZoneList<Expression*>* args = expr->arguments();
4129 int arg_count = args->length();
4138 4130
4139 if (expr->is_jsruntime()) { 4131 if (expr->is_jsruntime()) {
4140 // Prepare for calling JS runtime function. 4132 // Push the builtins object as receiver.
4141 __ movp(rax, GlobalObjectOperand()); 4133 __ movp(rax, GlobalObjectOperand());
4142 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset)); 4134 __ push(FieldOperand(rax, GlobalObject::kBuiltinsOffset));
4143 }
4144 4135
4145 // Push the arguments ("left-to-right"). 4136 // Load the function from the receiver.
4146 int arg_count = args->length(); 4137 __ movp(rax, Operand(rsp, 0));
4147 for (int i = 0; i < arg_count; i++) { 4138 __ Move(rcx, expr->name());
4148 VisitForStackValue(args->at(i)); 4139 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4149 }
4150 4140
4151 if (expr->is_jsruntime()) { 4141 // Push the target function under the receiver.
4152 // Call the JS runtime function using a call IC. 4142 __ push(Operand(rsp, 0));
4153 __ Move(rcx, expr->name()); 4143 __ movp(Operand(rsp, kPointerSize), rax);
4154 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); 4144
4155 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); 4145 // Push the arguments ("left-to-right").
4146 for (int i = 0; i < arg_count; i++) {
4147 VisitForStackValue(args->at(i));
4148 }
4149
4150 // Record source position of the IC call.
4151 SetSourcePosition(expr->position());
4152 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
4153 __ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
4154 __ CallStub(&stub);
4155
4156 // Restore context register. 4156 // Restore context register.
4157 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4157 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4158 context()->DropAndPlug(1, rax);
4159
4158 } else { 4160 } else {
4161 // Push the arguments ("left-to-right").
4162 for (int i = 0; i < arg_count; i++) {
4163 VisitForStackValue(args->at(i));
4164 }
4165
4166 // Call the C runtime.
4159 __ CallRuntime(expr->function(), arg_count); 4167 __ CallRuntime(expr->function(), arg_count);
4168 context()->Plug(rax);
4160 } 4169 }
4161 context()->Plug(rax);
4162 } 4170 }
4163 4171
4164 4172
4165 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 4173 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4166 switch (expr->op()) { 4174 switch (expr->op()) {
4167 case Token::DELETE: { 4175 case Token::DELETE: {
4168 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 4176 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4169 Property* property = expr->expression()->AsProperty(); 4177 Property* property = expr->expression()->AsProperty();
4170 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 4178 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4171 4179
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
4395 } 4403 }
4396 4404
4397 // Record position before stub call. 4405 // Record position before stub call.
4398 SetSourcePosition(expr->position()); 4406 SetSourcePosition(expr->position());
4399 4407
4400 // Call stub for +1/-1. 4408 // Call stub for +1/-1.
4401 __ bind(&stub_call); 4409 __ bind(&stub_call);
4402 __ movp(rdx, rax); 4410 __ movp(rdx, rax);
4403 __ Move(rax, Smi::FromInt(1)); 4411 __ Move(rax, Smi::FromInt(1));
4404 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); 4412 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
4405 CallIC(stub.GetCode(isolate()), 4413 CallIC(stub.GetCode(isolate()), expr->CountBinOpFeedbackId());
4406 NOT_CONTEXTUAL,
4407 expr->CountBinOpFeedbackId());
4408 patch_site.EmitPatchInfo(); 4414 patch_site.EmitPatchInfo();
4409 __ bind(&done); 4415 __ bind(&done);
4410 4416
4411 // Store the value returned in rax. 4417 // Store the value returned in rax.
4412 switch (assign_type) { 4418 switch (assign_type) {
4413 case VARIABLE: 4419 case VARIABLE:
4414 if (expr->is_postfix()) { 4420 if (expr->is_postfix()) {
4415 // Perform the assignment as if via '='. 4421 // Perform the assignment as if via '='.
4416 { EffectContext context(this); 4422 { EffectContext context(this);
4417 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4423 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
(...skipping 10 matching lines...) Expand all
4428 // Perform the assignment as if via '='. 4434 // Perform the assignment as if via '='.
4429 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4435 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4430 Token::ASSIGN); 4436 Token::ASSIGN);
4431 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4437 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4432 context()->Plug(rax); 4438 context()->Plug(rax);
4433 } 4439 }
4434 break; 4440 break;
4435 case NAMED_PROPERTY: { 4441 case NAMED_PROPERTY: {
4436 __ Move(rcx, prop->key()->AsLiteral()->value()); 4442 __ Move(rcx, prop->key()->AsLiteral()->value());
4437 __ pop(rdx); 4443 __ pop(rdx);
4438 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); 4444 CallStoreIC(expr->CountStoreFeedbackId());
4439 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4445 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4440 if (expr->is_postfix()) { 4446 if (expr->is_postfix()) {
4441 if (!context()->IsEffect()) { 4447 if (!context()->IsEffect()) {
4442 context()->PlugTOS(); 4448 context()->PlugTOS();
4443 } 4449 }
4444 } else { 4450 } else {
4445 context()->Plug(rax); 4451 context()->Plug(rax);
4446 } 4452 }
4447 break; 4453 break;
4448 } 4454 }
4449 case KEYED_PROPERTY: { 4455 case KEYED_PROPERTY: {
4450 __ pop(rcx); 4456 __ pop(rcx);
4451 __ pop(rdx); 4457 __ pop(rdx);
4452 Handle<Code> ic = is_classic_mode() 4458 Handle<Code> ic = is_classic_mode()
4453 ? isolate()->builtins()->KeyedStoreIC_Initialize() 4459 ? isolate()->builtins()->KeyedStoreIC_Initialize()
4454 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 4460 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4455 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); 4461 CallIC(ic, expr->CountStoreFeedbackId());
4456 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4462 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4457 if (expr->is_postfix()) { 4463 if (expr->is_postfix()) {
4458 if (!context()->IsEffect()) { 4464 if (!context()->IsEffect()) {
4459 context()->PlugTOS(); 4465 context()->PlugTOS();
4460 } 4466 }
4461 } else { 4467 } else {
4462 context()->Plug(rax); 4468 context()->Plug(rax);
4463 } 4469 }
4464 break; 4470 break;
4465 } 4471 }
4466 } 4472 }
4467 } 4473 }
4468 4474
4469 4475
4470 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4476 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4471 VariableProxy* proxy = expr->AsVariableProxy(); 4477 VariableProxy* proxy = expr->AsVariableProxy();
4472 ASSERT(!context()->IsEffect()); 4478 ASSERT(!context()->IsEffect());
4473 ASSERT(!context()->IsTest()); 4479 ASSERT(!context()->IsTest());
4474 4480
4475 if (proxy != NULL && proxy->var()->IsUnallocated()) { 4481 if (proxy != NULL && proxy->var()->IsUnallocated()) {
4476 Comment cmnt(masm_, "Global variable"); 4482 Comment cmnt(masm_, "[ Global variable");
4477 __ Move(rcx, proxy->name()); 4483 __ Move(rcx, proxy->name());
4478 __ movp(rax, GlobalObjectOperand()); 4484 __ movp(rax, GlobalObjectOperand());
4479 // Use a regular load, not a contextual load, to avoid a reference 4485 // Use a regular load, not a contextual load, to avoid a reference
4480 // error. 4486 // error.
4481 CallLoadIC(NOT_CONTEXTUAL); 4487 CallLoadIC(NOT_CONTEXTUAL);
4482 PrepareForBailout(expr, TOS_REG); 4488 PrepareForBailout(expr, TOS_REG);
4483 context()->Plug(rax); 4489 context()->Plug(rax);
4484 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4490 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4491 Comment cmnt(masm_, "[ Lookup slot");
4485 Label done, slow; 4492 Label done, slow;
4486 4493
4487 // Generate code for loading from variables potentially shadowed 4494 // Generate code for loading from variables potentially shadowed
4488 // by eval-introduced variables. 4495 // by eval-introduced variables.
4489 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); 4496 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
4490 4497
4491 __ bind(&slow); 4498 __ bind(&slow);
4492 __ push(rsi); 4499 __ push(rsi);
4493 __ Push(proxy->name()); 4500 __ Push(proxy->name());
4494 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4501 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
4633 __ or_(rcx, rax); 4640 __ or_(rcx, rax);
4634 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear); 4641 patch_site.EmitJumpIfNotSmi(rcx, &slow_case, Label::kNear);
4635 __ cmpq(rdx, rax); 4642 __ cmpq(rdx, rax);
4636 Split(cc, if_true, if_false, NULL); 4643 Split(cc, if_true, if_false, NULL);
4637 __ bind(&slow_case); 4644 __ bind(&slow_case);
4638 } 4645 }
4639 4646
4640 // Record position and call the compare IC. 4647 // Record position and call the compare IC.
4641 SetSourcePosition(expr->position()); 4648 SetSourcePosition(expr->position());
4642 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 4649 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
4643 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); 4650 CallIC(ic, expr->CompareOperationFeedbackId());
4644 patch_site.EmitPatchInfo(); 4651 patch_site.EmitPatchInfo();
4645 4652
4646 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4653 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4647 __ testq(rax, rax); 4654 __ testq(rax, rax);
4648 Split(cc, if_true, if_false, fall_through); 4655 Split(cc, if_true, if_false, fall_through);
4649 } 4656 }
4650 } 4657 }
4651 4658
4652 // Convert the result of the comparison into one expected for this 4659 // Convert the result of the comparison into one expected for this
4653 // expression's context. 4660 // expression's context.
(...skipping 14 matching lines...) Expand all
4668 VisitForAccumulatorValue(sub_expr); 4675 VisitForAccumulatorValue(sub_expr);
4669 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4676 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4670 if (expr->op() == Token::EQ_STRICT) { 4677 if (expr->op() == Token::EQ_STRICT) {
4671 Heap::RootListIndex nil_value = nil == kNullValue ? 4678 Heap::RootListIndex nil_value = nil == kNullValue ?
4672 Heap::kNullValueRootIndex : 4679 Heap::kNullValueRootIndex :
4673 Heap::kUndefinedValueRootIndex; 4680 Heap::kUndefinedValueRootIndex;
4674 __ CompareRoot(rax, nil_value); 4681 __ CompareRoot(rax, nil_value);
4675 Split(equal, if_true, if_false, fall_through); 4682 Split(equal, if_true, if_false, fall_through);
4676 } else { 4683 } else {
4677 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4684 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4678 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); 4685 CallIC(ic, expr->CompareOperationFeedbackId());
4679 __ testq(rax, rax); 4686 __ testq(rax, rax);
4680 Split(not_zero, if_true, if_false, fall_through); 4687 Split(not_zero, if_true, if_false, fall_through);
4681 } 4688 }
4682 context()->Plug(if_true, if_false); 4689 context()->Plug(if_true, if_false);
4683 } 4690 }
4684 4691
4685 4692
4686 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4693 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4687 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 4694 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
4688 context()->Plug(rax); 4695 context()->Plug(rax);
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
4900 4907
4901 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4908 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4902 Assembler::target_address_at(call_target_address)); 4909 Assembler::target_address_at(call_target_address));
4903 return OSR_AFTER_STACK_CHECK; 4910 return OSR_AFTER_STACK_CHECK;
4904 } 4911 }
4905 4912
4906 4913
4907 } } // namespace v8::internal 4914 } } // namespace v8::internal
4908 4915
4909 #endif // V8_TARGET_ARCH_X64 4916 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/disasm-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698