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

Side by Side Diff: src/ia32/full-codegen-ia32.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/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 // o esi: our context 111 // o esi: our context
112 // o ebp: our caller's frame pointer 112 // o ebp: our caller's frame pointer
113 // o esp: stack pointer (pointing to return address) 113 // o esp: 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-ia32.h for its layout. 116 // frames-ia32.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 edi. 187 // Argument to NewContext is the function, which is still in edi.
185 __ push(edi);
186 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { 188 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
189 __ push(edi);
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(edi);
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 eax and esi. It replaces the context 200 // Context is returned in eax. It replaces the context passed to us.
197 // passed to us. It's saved in the stack and kept live in esi. 201 // It's saved in the stack and kept live in esi.
198 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), esi); 202 __ mov(esi, eax);
203 __ mov(Operand(ebp, StandardFrameConstants::kContextOffset), eax);
199 204
200 // Copy parameters into context if necessary. 205 // Copy parameters into context if necessary.
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 __ mov(eax, Operand(ebp, parameter_offset)); 213 __ mov(eax, Operand(ebp, parameter_offset));
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 if (false_label_ != fall_through_) __ jmp(false_label_); 622 if (false_label_ != fall_through_) __ jmp(false_label_);
618 } 623 }
619 } 624 }
620 625
621 626
622 void FullCodeGenerator::DoTest(Expression* condition, 627 void FullCodeGenerator::DoTest(Expression* condition,
623 Label* if_true, 628 Label* if_true,
624 Label* if_false, 629 Label* if_false,
625 Label* fall_through) { 630 Label* fall_through) {
626 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); 631 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
627 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); 632 CallIC(ic, condition->test_id());
628 __ test(result_register(), result_register()); 633 __ test(result_register(), result_register());
629 // The stub returns nonzero for true. 634 // The stub returns nonzero for true.
630 Split(not_zero, if_true, if_false, fall_through); 635 Split(not_zero, if_true, if_false, fall_through);
631 } 636 }
632 637
633 638
634 void FullCodeGenerator::Split(Condition cc, 639 void FullCodeGenerator::Split(Condition cc,
635 Label* if_true, 640 Label* if_true,
636 Label* if_false, 641 Label* if_false,
637 Label* fall_through) { 642 Label* fall_through) {
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 __ cmp(edx, eax); 973 __ cmp(edx, eax);
969 __ j(not_equal, &next_test); 974 __ j(not_equal, &next_test);
970 __ Drop(1); // Switch value is no longer needed. 975 __ Drop(1); // Switch value is no longer needed.
971 __ jmp(clause->body_target()); 976 __ jmp(clause->body_target());
972 __ bind(&slow_case); 977 __ bind(&slow_case);
973 } 978 }
974 979
975 // Record position before stub call for type feedback. 980 // Record position before stub call for type feedback.
976 SetSourcePosition(clause->position()); 981 SetSourcePosition(clause->position());
977 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); 982 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
978 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); 983 CallIC(ic, clause->CompareId());
979 patch_site.EmitPatchInfo(); 984 patch_site.EmitPatchInfo();
980 985
981 Label skip; 986 Label skip;
982 __ jmp(&skip, Label::kNear); 987 __ jmp(&skip, Label::kNear);
983 PrepareForBailout(clause, TOS_REG); 988 PrepareForBailout(clause, TOS_REG);
984 __ cmp(eax, isolate()->factory()->true_value()); 989 __ cmp(eax, isolate()->factory()->true_value());
985 __ j(not_equal, &next_test); 990 __ j(not_equal, &next_test);
986 __ Drop(1); 991 __ Drop(1);
987 __ jmp(clause->body_target()); 992 __ jmp(clause->body_target());
988 __ bind(&skip); 993 __ bind(&skip);
(...skipping 23 matching lines...) Expand all
1012 VisitStatements(clause->statements()); 1017 VisitStatements(clause->statements());
1013 } 1018 }
1014 1019
1015 __ bind(nested_statement.break_label()); 1020 __ bind(nested_statement.break_label());
1016 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1021 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1017 } 1022 }
1018 1023
1019 1024
1020 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 1025 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1021 Comment cmnt(masm_, "[ ForInStatement"); 1026 Comment cmnt(masm_, "[ ForInStatement");
1027 int slot = stmt->ForInFeedbackSlot();
1028
1022 SetStatementPosition(stmt); 1029 SetStatementPosition(stmt);
1023 1030
1024 Label loop, exit; 1031 Label loop, exit;
1025 ForIn loop_statement(this, stmt); 1032 ForIn loop_statement(this, stmt);
1026 increment_loop_depth(); 1033 increment_loop_depth();
1027 1034
1028 // Get the object to enumerate over. If the object is null or undefined, skip 1035 // Get the object to enumerate over. If the object is null or undefined, skip
1029 // over the loop. See ECMA-262 version 5, section 12.6.4. 1036 // over the loop. See ECMA-262 version 5, section 12.6.4.
1030 VisitForAccumulatorValue(stmt->enumerable()); 1037 VisitForAccumulatorValue(stmt->enumerable());
1031 __ cmp(eax, isolate()->factory()->undefined_value()); 1038 __ cmp(eax, isolate()->factory()->undefined_value());
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 __ jmp(&loop); 1097 __ jmp(&loop);
1091 1098
1092 __ bind(&no_descriptors); 1099 __ bind(&no_descriptors);
1093 __ add(esp, Immediate(kPointerSize)); 1100 __ add(esp, Immediate(kPointerSize));
1094 __ jmp(&exit); 1101 __ jmp(&exit);
1095 1102
1096 // We got a fixed array in register eax. Iterate through that. 1103 // We got a fixed array in register eax. Iterate through that.
1097 Label non_proxy; 1104 Label non_proxy;
1098 __ bind(&fixed_array); 1105 __ bind(&fixed_array);
1099 1106
1100 Handle<Cell> cell = isolate()->factory()->NewCell( 1107 Handle<Object> feedback = Handle<Object>(
1101 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker), 1108 Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
1102 isolate())); 1109 isolate());
1103 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); 1110 StoreFeedbackVectorSlot(slot, feedback);
1104 __ LoadHeapObject(ebx, cell); 1111
1105 __ mov(FieldOperand(ebx, Cell::kValueOffset), 1112 // No need for a write barrier, we are storing a Smi in the feedback vector.
1106 Immediate(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); 1113 __ LoadHeapObject(ebx, FeedbackVector());
1114 __ mov(FieldOperand(ebx, FixedArray::OffsetOfElementAt(slot)),
1115 Immediate(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
1107 1116
1108 __ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check 1117 __ mov(ebx, Immediate(Smi::FromInt(1))); // Smi indicates slow check
1109 __ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object 1118 __ mov(ecx, Operand(esp, 0 * kPointerSize)); // Get enumerated object
1110 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1119 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1111 __ CmpObjectType(ecx, LAST_JS_PROXY_TYPE, ecx); 1120 __ CmpObjectType(ecx, LAST_JS_PROXY_TYPE, ecx);
1112 __ j(above, &non_proxy); 1121 __ j(above, &non_proxy);
1113 __ Set(ebx, Immediate(Smi::FromInt(0))); // Zero indicates proxy 1122 __ Set(ebx, Immediate(Smi::FromInt(0))); // Zero indicates proxy
1114 __ bind(&non_proxy); 1123 __ bind(&non_proxy);
1115 __ push(ebx); // Smi 1124 __ push(ebx); // Smi
1116 __ push(eax); // Array 1125 __ push(eax); // Array
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
1403 1412
1404 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1413 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1405 // Record position before possible IC call. 1414 // Record position before possible IC call.
1406 SetSourcePosition(proxy->position()); 1415 SetSourcePosition(proxy->position());
1407 Variable* var = proxy->var(); 1416 Variable* var = proxy->var();
1408 1417
1409 // Three cases: global variables, lookup variables, and all other types of 1418 // Three cases: global variables, lookup variables, and all other types of
1410 // variables. 1419 // variables.
1411 switch (var->location()) { 1420 switch (var->location()) {
1412 case Variable::UNALLOCATED: { 1421 case Variable::UNALLOCATED: {
1413 Comment cmnt(masm_, "Global variable"); 1422 Comment cmnt(masm_, "[ Global variable");
1414 // Use inline caching. Variable name is passed in ecx and the global 1423 // Use inline caching. Variable name is passed in ecx and the global
1415 // object in eax. 1424 // object in eax.
1416 __ mov(edx, GlobalObjectOperand()); 1425 __ mov(edx, GlobalObjectOperand());
1417 __ mov(ecx, var->name()); 1426 __ mov(ecx, var->name());
1418 CallLoadIC(CONTEXTUAL); 1427 CallLoadIC(CONTEXTUAL);
1419 context()->Plug(eax); 1428 context()->Plug(eax);
1420 break; 1429 break;
1421 } 1430 }
1422 1431
1423 case Variable::PARAMETER: 1432 case Variable::PARAMETER:
1424 case Variable::LOCAL: 1433 case Variable::LOCAL:
1425 case Variable::CONTEXT: { 1434 case Variable::CONTEXT: {
1426 Comment cmnt(masm_, var->IsContextSlot() 1435 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1427 ? "Context variable" 1436 : "[ Stack variable");
1428 : "Stack variable");
1429 if (var->binding_needs_init()) { 1437 if (var->binding_needs_init()) {
1430 // var->scope() may be NULL when the proxy is located in eval code and 1438 // var->scope() may be NULL when the proxy is located in eval code and
1431 // refers to a potential outside binding. Currently those bindings are 1439 // refers to a potential outside binding. Currently those bindings are
1432 // always looked up dynamically, i.e. in that case 1440 // always looked up dynamically, i.e. in that case
1433 // var->location() == LOOKUP. 1441 // var->location() == LOOKUP.
1434 // always holds. 1442 // always holds.
1435 ASSERT(var->scope() != NULL); 1443 ASSERT(var->scope() != NULL);
1436 1444
1437 // Check if the binding really needs an initialization check. The check 1445 // Check if the binding really needs an initialization check. The check
1438 // can be skipped in the following situation: we have a LET or CONST 1446 // 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
1480 __ bind(&done); 1488 __ bind(&done);
1481 context()->Plug(eax); 1489 context()->Plug(eax);
1482 break; 1490 break;
1483 } 1491 }
1484 } 1492 }
1485 context()->Plug(var); 1493 context()->Plug(var);
1486 break; 1494 break;
1487 } 1495 }
1488 1496
1489 case Variable::LOOKUP: { 1497 case Variable::LOOKUP: {
1498 Comment cmnt(masm_, "[ Lookup variable");
1490 Label done, slow; 1499 Label done, slow;
1491 // Generate code for loading from variables potentially shadowed 1500 // Generate code for loading from variables potentially shadowed
1492 // by eval-introduced variables. 1501 // by eval-introduced variables.
1493 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); 1502 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1494 __ bind(&slow); 1503 __ bind(&slow);
1495 Comment cmnt(masm_, "Lookup variable");
1496 __ push(esi); // Context. 1504 __ push(esi); // Context.
1497 __ push(Immediate(var->name())); 1505 __ push(Immediate(var->name()));
1498 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1506 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1499 __ bind(&done); 1507 __ bind(&done);
1500 context()->Plug(eax); 1508 context()->Plug(eax);
1501 break; 1509 break;
1502 } 1510 }
1503 } 1511 }
1504 } 1512 }
1505 1513
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1624 UNREACHABLE(); 1632 UNREACHABLE();
1625 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1633 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1626 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 1634 ASSERT(!CompileTimeValue::IsCompileTimeValue(value));
1627 // Fall through. 1635 // Fall through.
1628 case ObjectLiteral::Property::COMPUTED: 1636 case ObjectLiteral::Property::COMPUTED:
1629 if (key->value()->IsInternalizedString()) { 1637 if (key->value()->IsInternalizedString()) {
1630 if (property->emit_store()) { 1638 if (property->emit_store()) {
1631 VisitForAccumulatorValue(value); 1639 VisitForAccumulatorValue(value);
1632 __ mov(ecx, Immediate(key->value())); 1640 __ mov(ecx, Immediate(key->value()));
1633 __ mov(edx, Operand(esp, 0)); 1641 __ mov(edx, Operand(esp, 0));
1634 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); 1642 CallStoreIC(key->LiteralFeedbackId());
1635 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1643 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1636 } else { 1644 } else {
1637 VisitForEffect(value); 1645 VisitForEffect(value);
1638 } 1646 }
1639 break; 1647 break;
1640 } 1648 }
1641 __ push(Operand(esp, 0)); // Duplicate receiver. 1649 __ push(Operand(esp, 0)); // Duplicate receiver.
1642 VisitForStackValue(key); 1650 VisitForStackValue(key);
1643 VisitForStackValue(value); 1651 VisitForStackValue(value);
1644 if (property->emit_store()) { 1652 if (property->emit_store()) {
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
2036 2044
2037 // receiver = iter; f = iter.next; arg = received; 2045 // receiver = iter; f = iter.next; arg = received;
2038 __ bind(&l_next); 2046 __ bind(&l_next);
2039 __ mov(ecx, isolate()->factory()->next_string()); // "next" 2047 __ mov(ecx, isolate()->factory()->next_string()); // "next"
2040 __ push(ecx); 2048 __ push(ecx);
2041 __ push(Operand(esp, 2 * kPointerSize)); // iter 2049 __ push(Operand(esp, 2 * kPointerSize)); // iter
2042 __ push(eax); // received 2050 __ push(eax); // received
2043 2051
2044 // result = receiver[f](arg); 2052 // result = receiver[f](arg);
2045 __ bind(&l_call); 2053 __ bind(&l_call);
2046 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); 2054 __ mov(edx, Operand(esp, kPointerSize));
2047 CallIC(ic); 2055 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2056 CallIC(ic, TypeFeedbackId::None());
2057 __ mov(edi, eax);
2058 __ mov(Operand(esp, 2 * kPointerSize), edi);
2059 CallFunctionStub stub(1, CALL_AS_METHOD);
2060 __ CallStub(&stub);
2061
2048 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2062 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2049 __ Drop(1); // The key is still on the stack; drop it. 2063 __ Drop(1); // The function is still on the stack; drop it.
2050 2064
2051 // if (!result.done) goto l_try; 2065 // if (!result.done) goto l_try;
2052 __ bind(&l_loop); 2066 __ bind(&l_loop);
2053 __ push(eax); // save result 2067 __ push(eax); // save result
2054 __ mov(edx, eax); // result 2068 __ mov(edx, eax); // result
2055 __ mov(ecx, isolate()->factory()->done_string()); // "done" 2069 __ mov(ecx, isolate()->factory()->done_string()); // "done"
2056 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax 2070 CallLoadIC(NOT_CONTEXTUAL); // result.done in eax
2057 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2071 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2058 CallIC(bool_ic); 2072 CallIC(bool_ic);
2059 __ test(eax, eax); 2073 __ test(eax, eax);
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
2222 Literal* key = prop->key()->AsLiteral(); 2236 Literal* key = prop->key()->AsLiteral();
2223 ASSERT(!key->value()->IsSmi()); 2237 ASSERT(!key->value()->IsSmi());
2224 __ mov(ecx, Immediate(key->value())); 2238 __ mov(ecx, Immediate(key->value()));
2225 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2239 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2226 } 2240 }
2227 2241
2228 2242
2229 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 2243 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2230 SetSourcePosition(prop->position()); 2244 SetSourcePosition(prop->position());
2231 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2245 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2232 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2246 CallIC(ic, prop->PropertyFeedbackId());
2233 } 2247 }
2234 2248
2235 2249
2236 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2250 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2237 Token::Value op, 2251 Token::Value op,
2238 OverwriteMode mode, 2252 OverwriteMode mode,
2239 Expression* left, 2253 Expression* left,
2240 Expression* right) { 2254 Expression* right) {
2241 // Do combined smi check of the operands. Left operand is on the 2255 // Do combined smi check of the operands. Left operand is on the
2242 // stack. Right operand is in eax. 2256 // stack. Right operand is in eax.
2243 Label smi_case, done, stub_call; 2257 Label smi_case, done, stub_call;
2244 __ pop(edx); 2258 __ pop(edx);
2245 __ mov(ecx, eax); 2259 __ mov(ecx, eax);
2246 __ or_(eax, edx); 2260 __ or_(eax, edx);
2247 JumpPatchSite patch_site(masm_); 2261 JumpPatchSite patch_site(masm_);
2248 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear); 2262 patch_site.EmitJumpIfSmi(eax, &smi_case, Label::kNear);
2249 2263
2250 __ bind(&stub_call); 2264 __ bind(&stub_call);
2251 __ mov(eax, ecx); 2265 __ mov(eax, ecx);
2252 BinaryOpICStub stub(op, mode); 2266 BinaryOpICStub stub(op, mode);
2253 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, 2267 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId());
2254 expr->BinaryOperationFeedbackId());
2255 patch_site.EmitPatchInfo(); 2268 patch_site.EmitPatchInfo();
2256 __ jmp(&done, Label::kNear); 2269 __ jmp(&done, Label::kNear);
2257 2270
2258 // Smi case. 2271 // Smi case.
2259 __ bind(&smi_case); 2272 __ bind(&smi_case);
2260 __ mov(eax, edx); // Copy left operand in case of a stub call. 2273 __ mov(eax, edx); // Copy left operand in case of a stub call.
2261 2274
2262 switch (op) { 2275 switch (op) {
2263 case Token::SAR: 2276 case Token::SAR:
2264 __ SmiUntag(eax); 2277 __ SmiUntag(eax);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2329 context()->Plug(eax); 2342 context()->Plug(eax);
2330 } 2343 }
2331 2344
2332 2345
2333 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2346 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2334 Token::Value op, 2347 Token::Value op,
2335 OverwriteMode mode) { 2348 OverwriteMode mode) {
2336 __ pop(edx); 2349 __ pop(edx);
2337 BinaryOpICStub stub(op, mode); 2350 BinaryOpICStub stub(op, mode);
2338 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2351 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
2339 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, 2352 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId());
2340 expr->BinaryOperationFeedbackId());
2341 patch_site.EmitPatchInfo(); 2353 patch_site.EmitPatchInfo();
2342 context()->Plug(eax); 2354 context()->Plug(eax);
2343 } 2355 }
2344 2356
2345 2357
2346 void FullCodeGenerator::EmitAssignment(Expression* expr) { 2358 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2347 // Invalid left-hand sides are rewritten by the parser to have a 'throw 2359 // Invalid left-hand sides are rewritten by the parser to have a 'throw
2348 // ReferenceError' on the left-hand side. 2360 // ReferenceError' on the left-hand side.
2349 if (!expr->IsValidLeftHandSide()) { 2361 if (!expr->IsValidLeftHandSide()) {
2350 VisitForEffect(expr); 2362 VisitForEffect(expr);
(...skipping 17 matching lines...) Expand all
2368 EffectContext context(this); 2380 EffectContext context(this);
2369 EmitVariableAssignment(var, Token::ASSIGN); 2381 EmitVariableAssignment(var, Token::ASSIGN);
2370 break; 2382 break;
2371 } 2383 }
2372 case NAMED_PROPERTY: { 2384 case NAMED_PROPERTY: {
2373 __ push(eax); // Preserve value. 2385 __ push(eax); // Preserve value.
2374 VisitForAccumulatorValue(prop->obj()); 2386 VisitForAccumulatorValue(prop->obj());
2375 __ mov(edx, eax); 2387 __ mov(edx, eax);
2376 __ pop(eax); // Restore value. 2388 __ pop(eax); // Restore value.
2377 __ mov(ecx, prop->key()->AsLiteral()->value()); 2389 __ mov(ecx, prop->key()->AsLiteral()->value());
2378 CallStoreIC(NOT_CONTEXTUAL); 2390 CallStoreIC();
2379 break; 2391 break;
2380 } 2392 }
2381 case KEYED_PROPERTY: { 2393 case KEYED_PROPERTY: {
2382 __ push(eax); // Preserve value. 2394 __ push(eax); // Preserve value.
2383 VisitForStackValue(prop->obj()); 2395 VisitForStackValue(prop->obj());
2384 VisitForAccumulatorValue(prop->key()); 2396 VisitForAccumulatorValue(prop->key());
2385 __ mov(ecx, eax); 2397 __ mov(ecx, eax);
2386 __ pop(edx); // Receiver. 2398 __ pop(edx); // Receiver.
2387 __ pop(eax); // Restore value. 2399 __ pop(eax); // Restore value.
2388 Handle<Code> ic = is_classic_mode() 2400 Handle<Code> ic = is_classic_mode()
2389 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2401 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2390 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2402 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2391 CallIC(ic); 2403 CallIC(ic);
2392 break; 2404 break;
2393 } 2405 }
2394 } 2406 }
2395 context()->Plug(eax); 2407 context()->Plug(eax);
2396 } 2408 }
2397 2409
2398 2410
2411 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2412 Variable* var, MemOperand location) {
2413 __ mov(location, eax);
2414 if (var->IsContextSlot()) {
2415 __ mov(edx, eax);
2416 int offset = Context::SlotOffset(var->index());
2417 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
2418 }
2419 }
2420
2421
2422 void FullCodeGenerator::EmitCallStoreContextSlot(
2423 Handle<String> name, LanguageMode mode) {
2424 __ push(eax); // Value.
2425 __ push(esi); // Context.
2426 __ push(Immediate(name));
2427 __ push(Immediate(Smi::FromInt(mode)));
2428 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2429 }
2430
2431
2399 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2432 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2400 Token::Value op) { 2433 Token::Value op) {
2401 if (var->IsUnallocated()) { 2434 if (var->IsUnallocated()) {
2402 // Global var, const, or let. 2435 // Global var, const, or let.
2403 __ mov(ecx, var->name()); 2436 __ mov(ecx, var->name());
2404 __ mov(edx, GlobalObjectOperand()); 2437 __ mov(edx, GlobalObjectOperand());
2405 CallStoreIC(CONTEXTUAL); 2438 CallStoreIC();
2439
2406 } else if (op == Token::INIT_CONST) { 2440 } else if (op == Token::INIT_CONST) {
2407 // Const initializers need a write barrier. 2441 // Const initializers need a write barrier.
2408 ASSERT(!var->IsParameter()); // No const parameters. 2442 ASSERT(!var->IsParameter()); // No const parameters.
2409 if (var->IsStackLocal()) { 2443 if (var->IsLookupSlot()) {
2410 Label skip;
2411 __ mov(edx, StackOperand(var));
2412 __ cmp(edx, isolate()->factory()->the_hole_value());
2413 __ j(not_equal, &skip);
2414 __ mov(StackOperand(var), eax);
2415 __ bind(&skip);
2416 } else {
2417 ASSERT(var->IsContextSlot() || var->IsLookupSlot());
2418 // Like var declarations, const declarations are hoisted to function
2419 // scope. However, unlike var initializers, const initializers are
2420 // able to drill a hole to that function context, even from inside a
2421 // 'with' context. We thus bypass the normal static scope lookup for
2422 // var->IsContextSlot().
2423 __ push(eax); 2444 __ push(eax);
2424 __ push(esi); 2445 __ push(esi);
2425 __ push(Immediate(var->name())); 2446 __ push(Immediate(var->name()));
2426 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3); 2447 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2448 } else {
2449 ASSERT(var->IsStackLocal() || var->IsContextSlot());
2450 Label skip;
2451 MemOperand location = VarOperand(var, ecx);
2452 __ mov(edx, location);
2453 __ cmp(edx, isolate()->factory()->the_hole_value());
2454 __ j(not_equal, &skip, Label::kNear);
2455 EmitStoreToStackLocalOrContextSlot(var, location);
2456 __ bind(&skip);
2427 } 2457 }
2428 2458
2429 } else if (var->mode() == LET && op != Token::INIT_LET) { 2459 } else if (var->mode() == LET && op != Token::INIT_LET) {
2430 // Non-initializing assignment to let variable needs a write barrier. 2460 // Non-initializing assignment to let variable needs a write barrier.
2431 if (var->IsLookupSlot()) { 2461 if (var->IsLookupSlot()) {
2432 __ push(eax); // Value. 2462 EmitCallStoreContextSlot(var->name(), language_mode());
2433 __ push(esi); // Context.
2434 __ push(Immediate(var->name()));
2435 __ push(Immediate(Smi::FromInt(language_mode())));
2436 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2437 } else { 2463 } else {
2438 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2464 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2439 Label assign; 2465 Label assign;
2440 MemOperand location = VarOperand(var, ecx); 2466 MemOperand location = VarOperand(var, ecx);
2441 __ mov(edx, location); 2467 __ mov(edx, location);
2442 __ cmp(edx, isolate()->factory()->the_hole_value()); 2468 __ cmp(edx, isolate()->factory()->the_hole_value());
2443 __ j(not_equal, &assign, Label::kNear); 2469 __ j(not_equal, &assign, Label::kNear);
2444 __ push(Immediate(var->name())); 2470 __ push(Immediate(var->name()));
2445 __ CallRuntime(Runtime::kThrowReferenceError, 1); 2471 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2446 __ bind(&assign); 2472 __ bind(&assign);
2447 __ mov(location, eax); 2473 EmitStoreToStackLocalOrContextSlot(var, location);
2448 if (var->IsContextSlot()) {
2449 __ mov(edx, eax);
2450 int offset = Context::SlotOffset(var->index());
2451 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
2452 }
2453 } 2474 }
2454 2475
2455 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { 2476 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
2456 // Assignment to var or initializing assignment to let/const 2477 // Assignment to var or initializing assignment to let/const
2457 // in harmony mode. 2478 // in harmony mode.
2458 if (var->IsStackAllocated() || var->IsContextSlot()) { 2479 if (var->IsLookupSlot()) {
2480 EmitCallStoreContextSlot(var->name(), language_mode());
2481 } else {
2482 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2459 MemOperand location = VarOperand(var, ecx); 2483 MemOperand location = VarOperand(var, ecx);
2460 if (generate_debug_code_ && op == Token::INIT_LET) { 2484 if (generate_debug_code_ && op == Token::INIT_LET) {
2461 // Check for an uninitialized let binding. 2485 // Check for an uninitialized let binding.
2462 __ mov(edx, location); 2486 __ mov(edx, location);
2463 __ cmp(edx, isolate()->factory()->the_hole_value()); 2487 __ cmp(edx, isolate()->factory()->the_hole_value());
2464 __ Check(equal, kLetBindingReInitialization); 2488 __ Check(equal, kLetBindingReInitialization);
2465 } 2489 }
2466 // Perform the assignment. 2490 EmitStoreToStackLocalOrContextSlot(var, location);
2467 __ mov(location, eax);
2468 if (var->IsContextSlot()) {
2469 __ mov(edx, eax);
2470 int offset = Context::SlotOffset(var->index());
2471 __ RecordWriteContextSlot(ecx, offset, edx, ebx, kDontSaveFPRegs);
2472 }
2473 } else {
2474 ASSERT(var->IsLookupSlot());
2475 __ push(eax); // Value.
2476 __ push(esi); // Context.
2477 __ push(Immediate(var->name()));
2478 __ push(Immediate(Smi::FromInt(language_mode())));
2479 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2480 } 2491 }
2481 } 2492 }
2482 // Non-initializing assignments to consts are ignored. 2493 // Non-initializing assignments to consts are ignored.
2483 } 2494 }
2484 2495
2485 2496
2486 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2497 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2487 // Assignment to a property, using a named store IC. 2498 // Assignment to a property, using a named store IC.
2488 // eax : value 2499 // eax : value
2489 // esp[0] : receiver 2500 // esp[0] : receiver
2490 2501
2491 Property* prop = expr->target()->AsProperty(); 2502 Property* prop = expr->target()->AsProperty();
2492 ASSERT(prop != NULL); 2503 ASSERT(prop != NULL);
2493 ASSERT(prop->key()->AsLiteral() != NULL); 2504 ASSERT(prop->key()->AsLiteral() != NULL);
2494 2505
2495 // Record source code position before IC call. 2506 // Record source code position before IC call.
2496 SetSourcePosition(expr->position()); 2507 SetSourcePosition(expr->position());
2497 __ mov(ecx, prop->key()->AsLiteral()->value()); 2508 __ mov(ecx, prop->key()->AsLiteral()->value());
2498 __ pop(edx); 2509 __ pop(edx);
2499 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); 2510 CallStoreIC(expr->AssignmentFeedbackId());
2500 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2511 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2501 context()->Plug(eax); 2512 context()->Plug(eax);
2502 } 2513 }
2503 2514
2504 2515
2505 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2516 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2506 // Assignment to a property, using a keyed store IC. 2517 // Assignment to a property, using a keyed store IC.
2507 // eax : value 2518 // eax : value
2508 // esp[0] : key 2519 // esp[0] : key
2509 // esp[kPointerSize] : receiver 2520 // esp[kPointerSize] : receiver
2510 2521
2511 __ pop(ecx); // Key. 2522 __ pop(ecx); // Key.
2512 __ pop(edx); 2523 __ pop(edx);
2513 // Record source code position before IC call. 2524 // Record source code position before IC call.
2514 SetSourcePosition(expr->position()); 2525 SetSourcePosition(expr->position());
2515 Handle<Code> ic = is_classic_mode() 2526 Handle<Code> ic = is_classic_mode()
2516 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2527 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2517 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2528 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2518 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); 2529 CallIC(ic, expr->AssignmentFeedbackId());
2519 2530
2520 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2531 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2521 context()->Plug(eax); 2532 context()->Plug(eax);
2522 } 2533 }
2523 2534
2524 2535
2525 void FullCodeGenerator::VisitProperty(Property* expr) { 2536 void FullCodeGenerator::VisitProperty(Property* expr) {
2526 Comment cmnt(masm_, "[ Property"); 2537 Comment cmnt(masm_, "[ Property");
2527 Expression* key = expr->key(); 2538 Expression* key = expr->key();
2528 2539
2529 if (key->IsPropertyName()) { 2540 if (key->IsPropertyName()) {
2530 VisitForAccumulatorValue(expr->obj()); 2541 VisitForAccumulatorValue(expr->obj());
2531 __ mov(edx, result_register()); 2542 __ mov(edx, result_register());
2532 EmitNamedPropertyLoad(expr); 2543 EmitNamedPropertyLoad(expr);
2533 PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2544 PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2534 context()->Plug(eax); 2545 context()->Plug(eax);
2535 } else { 2546 } else {
2536 VisitForStackValue(expr->obj()); 2547 VisitForStackValue(expr->obj());
2537 VisitForAccumulatorValue(expr->key()); 2548 VisitForAccumulatorValue(expr->key());
2538 __ pop(edx); // Object. 2549 __ pop(edx); // Object.
2539 __ mov(ecx, result_register()); // Key. 2550 __ mov(ecx, result_register()); // Key.
2540 EmitKeyedPropertyLoad(expr); 2551 EmitKeyedPropertyLoad(expr);
2541 context()->Plug(eax); 2552 context()->Plug(eax);
2542 } 2553 }
2543 } 2554 }
2544 2555
2545 2556
2546 void FullCodeGenerator::CallIC(Handle<Code> code, 2557 void FullCodeGenerator::CallIC(Handle<Code> code,
2547 ContextualMode mode,
2548 TypeFeedbackId ast_id) { 2558 TypeFeedbackId ast_id) {
2549 ic_total_count_++; 2559 ic_total_count_++;
2550 ASSERT(mode != CONTEXTUAL || ast_id.IsNone());
2551 __ call(code, RelocInfo::CODE_TARGET, ast_id); 2560 __ call(code, RelocInfo::CODE_TARGET, ast_id);
2552 } 2561 }
2553 2562
2554 2563
2555 2564
2556 2565
2557 void FullCodeGenerator::EmitCallWithIC(Call* expr, 2566 // Code common for calls using the IC.
2558 Handle<Object> name, 2567 void FullCodeGenerator::EmitCallWithIC(Call* expr) {
2559 ContextualMode mode) { 2568 Expression* callee = expr->expression();
2560 // Code common for calls using the IC.
2561 ZoneList<Expression*>* args = expr->arguments(); 2569 ZoneList<Expression*>* args = expr->arguments();
2562 int arg_count = args->length(); 2570 int arg_count = args->length();
2571
2572 CallFunctionFlags flags;
2573 // Get the target function.
2574 if (callee->IsVariableProxy()) {
2575 { StackValueContext context(this);
2576 EmitVariableLoad(callee->AsVariableProxy());
2577 PrepareForBailout(callee, NO_REGISTERS);
2578 }
2579 // Push undefined as receiver. This is patched in the method prologue if it
2580 // is a classic mode method.
2581 __ push(Immediate(isolate()->factory()->undefined_value()));
2582 flags = NO_CALL_FUNCTION_FLAGS;
2583 } else {
2584 // Load the function from the receiver.
2585 ASSERT(callee->IsProperty());
2586 __ mov(edx, Operand(esp, 0));
2587 EmitNamedPropertyLoad(callee->AsProperty());
2588 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2589 // Push the target function under the receiver.
2590 __ push(Operand(esp, 0));
2591 __ mov(Operand(esp, kPointerSize), eax);
2592 flags = CALL_AS_METHOD;
2593 }
2594
2595 // Load the arguments.
2563 { PreservePositionScope scope(masm()->positions_recorder()); 2596 { PreservePositionScope scope(masm()->positions_recorder());
2564 for (int i = 0; i < arg_count; i++) { 2597 for (int i = 0; i < arg_count; i++) {
2565 VisitForStackValue(args->at(i)); 2598 VisitForStackValue(args->at(i));
2566 } 2599 }
2567 __ Set(ecx, Immediate(name));
2568 } 2600 }
2601
2569 // Record source position of the IC call. 2602 // Record source position of the IC call.
2570 SetSourcePosition(expr->position()); 2603 SetSourcePosition(expr->position());
2571 Handle<Code> ic = 2604 CallFunctionStub stub(arg_count, flags);
2572 isolate()->stub_cache()->ComputeCallInitialize(arg_count); 2605 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2573 TypeFeedbackId ast_id = mode == CONTEXTUAL 2606 __ CallStub(&stub);
2574 ? TypeFeedbackId::None()
2575 : expr->CallFeedbackId();
2576 CallIC(ic, mode, ast_id);
2577 RecordJSReturnSite(expr); 2607 RecordJSReturnSite(expr);
2608
2578 // Restore context register. 2609 // Restore context register.
2579 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2610 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2580 context()->Plug(eax); 2611
2612 context()->DropAndPlug(1, eax);
2581 } 2613 }
2582 2614
2583 2615
2616 // Code common for calls using the IC.
2584 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, 2617 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2585 Expression* key) { 2618 Expression* key) {
2586 // Load the key. 2619 // Load the key.
2587 VisitForAccumulatorValue(key); 2620 VisitForAccumulatorValue(key);
2588 2621
2589 // Swap the name of the function and the receiver on the stack to follow 2622 Expression* callee = expr->expression();
2590 // the calling convention for call ICs. 2623 ZoneList<Expression*>* args = expr->arguments();
2591 __ pop(ecx); 2624 int arg_count = args->length();
2592 __ push(eax); 2625
2593 __ push(ecx); 2626 // Load the function from the receiver.
2627 ASSERT(callee->IsProperty());
2628 __ mov(edx, Operand(esp, 0));
2629 // Move the key into the right register for the keyed load IC.
2630 __ mov(ecx, eax);
2631 EmitKeyedPropertyLoad(callee->AsProperty());
2632 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2633
2634 // Push the target function under the receiver.
2635 __ push(Operand(esp, 0));
2636 __ mov(Operand(esp, kPointerSize), eax);
2594 2637
2595 // Load the arguments. 2638 // Load the arguments.
2596 ZoneList<Expression*>* args = expr->arguments();
2597 int arg_count = args->length();
2598 { PreservePositionScope scope(masm()->positions_recorder()); 2639 { PreservePositionScope scope(masm()->positions_recorder());
2599 for (int i = 0; i < arg_count; i++) { 2640 for (int i = 0; i < arg_count; i++) {
2600 VisitForStackValue(args->at(i)); 2641 VisitForStackValue(args->at(i));
2601 } 2642 }
2602 } 2643 }
2644
2603 // Record source position of the IC call. 2645 // Record source position of the IC call.
2604 SetSourcePosition(expr->position()); 2646 SetSourcePosition(expr->position());
2605 Handle<Code> ic = 2647 CallFunctionStub stub(arg_count, CALL_AS_METHOD);
2606 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); 2648 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2607 __ mov(ecx, Operand(esp, (arg_count + 1) * kPointerSize)); // Key. 2649 __ CallStub(&stub);
2608 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId());
2609 RecordJSReturnSite(expr); 2650 RecordJSReturnSite(expr);
2651
2610 // Restore context register. 2652 // Restore context register.
2611 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2653 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2612 context()->DropAndPlug(1, eax); // Drop the key still on the stack. 2654
2655 context()->DropAndPlug(1, eax);
2613 } 2656 }
2614 2657
2615 2658
2616 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 2659 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
2617 // Code common for calls using the call stub. 2660 // Code common for calls using the call stub.
2618 ZoneList<Expression*>* args = expr->arguments(); 2661 ZoneList<Expression*>* args = expr->arguments();
2619 int arg_count = args->length(); 2662 int arg_count = args->length();
2620 { PreservePositionScope scope(masm()->positions_recorder()); 2663 { PreservePositionScope scope(masm()->positions_recorder());
2621 for (int i = 0; i < arg_count; i++) { 2664 for (int i = 0; i < arg_count; i++) {
2622 VisitForStackValue(args->at(i)); 2665 VisitForStackValue(args->at(i));
2623 } 2666 }
2624 } 2667 }
2625 // Record source position for debugger. 2668 // Record source position for debugger.
2626 SetSourcePosition(expr->position()); 2669 SetSourcePosition(expr->position());
2627 2670
2628 Handle<Object> uninitialized = 2671 Handle<Object> uninitialized =
2629 TypeFeedbackCells::UninitializedSentinel(isolate()); 2672 TypeFeedbackInfo::UninitializedSentinel(isolate());
2630 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); 2673 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
2631 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell); 2674 __ LoadHeapObject(ebx, FeedbackVector());
2632 __ mov(ebx, cell); 2675 __ mov(edx, Immediate(Smi::FromInt(expr->CallFeedbackSlot())));
2633 2676
2634 // Record call targets in unoptimized code. 2677 // Record call targets in unoptimized code.
2635 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); 2678 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
2636 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2679 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2637 __ CallStub(&stub, expr->CallFeedbackId()); 2680 __ CallStub(&stub);
2638 2681
2639 RecordJSReturnSite(expr); 2682 RecordJSReturnSite(expr);
2640 // Restore context register. 2683 // Restore context register.
2641 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2684 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2642 context()->DropAndPlug(1, eax); 2685 context()->DropAndPlug(1, eax);
2643 } 2686 }
2644 2687
2645 2688
2646 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2689 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2647 // Push copy of the first argument or undefined if it doesn't exist. 2690 // Push copy of the first argument or undefined if it doesn't exist.
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2704 SetSourcePosition(expr->position()); 2747 SetSourcePosition(expr->position());
2705 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); 2748 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
2706 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize)); 2749 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
2707 __ CallStub(&stub); 2750 __ CallStub(&stub);
2708 RecordJSReturnSite(expr); 2751 RecordJSReturnSite(expr);
2709 // Restore context register. 2752 // Restore context register.
2710 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 2753 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
2711 context()->DropAndPlug(1, eax); 2754 context()->DropAndPlug(1, eax);
2712 2755
2713 } else if (call_type == Call::GLOBAL_CALL) { 2756 } else if (call_type == Call::GLOBAL_CALL) {
2714 // Push global object as receiver for the call IC. 2757 EmitCallWithIC(expr);
2715 __ push(GlobalObjectOperand()); 2758
2716 VariableProxy* proxy = callee->AsVariableProxy();
2717 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
2718 } else if (call_type == Call::LOOKUP_SLOT_CALL) { 2759 } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2719 // Call to a lookup slot (dynamically introduced variable). 2760 // Call to a lookup slot (dynamically introduced variable).
2720 VariableProxy* proxy = callee->AsVariableProxy(); 2761 VariableProxy* proxy = callee->AsVariableProxy();
2721 Label slow, done; 2762 Label slow, done;
2722 { PreservePositionScope scope(masm()->positions_recorder()); 2763 { PreservePositionScope scope(masm()->positions_recorder());
2723 // Generate code for loading from variables potentially shadowed by 2764 // Generate code for loading from variables potentially shadowed by
2724 // eval-introduced variables. 2765 // eval-introduced variables.
2725 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2766 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2726 } 2767 }
2727 __ bind(&slow); 2768 __ bind(&slow);
(...skipping 22 matching lines...) Expand all
2750 // The receiver is either the global receiver or an object found by 2791 // The receiver is either the global receiver or an object found by
2751 // LoadContextSlot. 2792 // LoadContextSlot.
2752 EmitCallWithStub(expr); 2793 EmitCallWithStub(expr);
2753 2794
2754 } else if (call_type == Call::PROPERTY_CALL) { 2795 } else if (call_type == Call::PROPERTY_CALL) {
2755 Property* property = callee->AsProperty(); 2796 Property* property = callee->AsProperty();
2756 { PreservePositionScope scope(masm()->positions_recorder()); 2797 { PreservePositionScope scope(masm()->positions_recorder());
2757 VisitForStackValue(property->obj()); 2798 VisitForStackValue(property->obj());
2758 } 2799 }
2759 if (property->key()->IsPropertyName()) { 2800 if (property->key()->IsPropertyName()) {
2760 EmitCallWithIC(expr, 2801 EmitCallWithIC(expr);
2761 property->key()->AsLiteral()->value(),
2762 NOT_CONTEXTUAL);
2763 } else { 2802 } else {
2764 EmitKeyedCallWithIC(expr, property->key()); 2803 EmitKeyedCallWithIC(expr, property->key());
2765 } 2804 }
2766 2805
2767 } else { 2806 } else {
2768 ASSERT(call_type == Call::OTHER_CALL); 2807 ASSERT(call_type == Call::OTHER_CALL);
2769 // Call to an arbitrary expression not handled specially above. 2808 // Call to an arbitrary expression not handled specially above.
2770 { PreservePositionScope scope(masm()->positions_recorder()); 2809 { PreservePositionScope scope(masm()->positions_recorder());
2771 VisitForStackValue(callee); 2810 VisitForStackValue(callee);
2772 } 2811 }
(...skipping 30 matching lines...) Expand all
2803 // Call the construct call builtin that handles allocation and 2842 // Call the construct call builtin that handles allocation and
2804 // constructor invocation. 2843 // constructor invocation.
2805 SetSourcePosition(expr->position()); 2844 SetSourcePosition(expr->position());
2806 2845
2807 // Load function and argument count into edi and eax. 2846 // Load function and argument count into edi and eax.
2808 __ Set(eax, Immediate(arg_count)); 2847 __ Set(eax, Immediate(arg_count));
2809 __ mov(edi, Operand(esp, arg_count * kPointerSize)); 2848 __ mov(edi, Operand(esp, arg_count * kPointerSize));
2810 2849
2811 // Record call targets in unoptimized code. 2850 // Record call targets in unoptimized code.
2812 Handle<Object> uninitialized = 2851 Handle<Object> uninitialized =
2813 TypeFeedbackCells::UninitializedSentinel(isolate()); 2852 TypeFeedbackInfo::UninitializedSentinel(isolate());
2814 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); 2853 StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
2815 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell); 2854 __ LoadHeapObject(ebx, FeedbackVector());
2816 __ mov(ebx, cell); 2855 __ mov(edx, Immediate(Smi::FromInt(expr->CallNewFeedbackSlot())));
2817 2856
2818 CallConstructStub stub(RECORD_CALL_TARGET); 2857 CallConstructStub stub(RECORD_CALL_TARGET);
2819 __ call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); 2858 __ call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
2820 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2859 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2821 context()->Plug(eax); 2860 context()->Plug(eax);
2822 } 2861 }
2823 2862
2824 2863
2825 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 2864 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2826 ZoneList<Expression*>* args = expr->arguments(); 2865 ZoneList<Expression*>* args = expr->arguments();
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after
3402 3441
3403 VisitForStackValue(args->at(1)); // index 3442 VisitForStackValue(args->at(1)); // index
3404 VisitForStackValue(args->at(2)); // value 3443 VisitForStackValue(args->at(2)); // value
3405 VisitForAccumulatorValue(args->at(0)); // string 3444 VisitForAccumulatorValue(args->at(0)); // string
3406 3445
3407 __ pop(value); 3446 __ pop(value);
3408 __ pop(index); 3447 __ pop(index);
3409 3448
3410 if (FLAG_debug_code) { 3449 if (FLAG_debug_code) {
3411 __ test(value, Immediate(kSmiTagMask)); 3450 __ test(value, Immediate(kSmiTagMask));
3412 __ ThrowIf(not_zero, kNonSmiValue); 3451 __ Check(zero, kNonSmiValue);
3413 __ test(index, Immediate(kSmiTagMask)); 3452 __ test(index, Immediate(kSmiTagMask));
3414 __ ThrowIf(not_zero, kNonSmiValue); 3453 __ Check(zero, kNonSmiValue);
3415 } 3454 }
3416 3455
3417 __ SmiUntag(value); 3456 __ SmiUntag(value);
3418 __ SmiUntag(index); 3457 __ SmiUntag(index);
3419 3458
3420 if (FLAG_debug_code) { 3459 if (FLAG_debug_code) {
3421 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 3460 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3422 __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type); 3461 __ EmitSeqStringSetCharCheck(string, index, value, one_byte_seq_type);
3423 } 3462 }
3424 3463
(...skipping 12 matching lines...) Expand all
3437 Register value = ecx; 3476 Register value = ecx;
3438 3477
3439 VisitForStackValue(args->at(1)); // index 3478 VisitForStackValue(args->at(1)); // index
3440 VisitForStackValue(args->at(2)); // value 3479 VisitForStackValue(args->at(2)); // value
3441 VisitForAccumulatorValue(args->at(0)); // string 3480 VisitForAccumulatorValue(args->at(0)); // string
3442 __ pop(value); 3481 __ pop(value);
3443 __ pop(index); 3482 __ pop(index);
3444 3483
3445 if (FLAG_debug_code) { 3484 if (FLAG_debug_code) {
3446 __ test(value, Immediate(kSmiTagMask)); 3485 __ test(value, Immediate(kSmiTagMask));
3447 __ ThrowIf(not_zero, kNonSmiValue); 3486 __ Check(zero, kNonSmiValue);
3448 __ test(index, Immediate(kSmiTagMask)); 3487 __ test(index, Immediate(kSmiTagMask));
3449 __ ThrowIf(not_zero, kNonSmiValue); 3488 __ Check(zero, kNonSmiValue);
3450 __ SmiUntag(index); 3489 __ SmiUntag(index);
3451 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 3490 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3452 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type); 3491 __ EmitSeqStringSetCharCheck(string, index, value, two_byte_seq_type);
3453 __ SmiTag(index); 3492 __ SmiTag(index);
3454 } 3493 }
3455 3494
3456 __ SmiUntag(value); 3495 __ SmiUntag(value);
3457 // No need to untag a smi for two-byte addressing. 3496 // No need to untag a smi for two-byte addressing.
3458 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize), 3497 __ mov_w(FieldOperand(string, index, times_1, SeqTwoByteString::kHeaderSize),
3459 value); 3498 value);
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
3629 generator.GenerateSlow(masm_, call_helper); 3668 generator.GenerateSlow(masm_, call_helper);
3630 3669
3631 __ bind(&done); 3670 __ bind(&done);
3632 context()->Plug(result); 3671 context()->Plug(result);
3633 } 3672 }
3634 3673
3635 3674
3636 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 3675 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3637 ZoneList<Expression*>* args = expr->arguments(); 3676 ZoneList<Expression*>* args = expr->arguments();
3638 ASSERT_EQ(2, args->length()); 3677 ASSERT_EQ(2, args->length());
3678 VisitForStackValue(args->at(0));
3679 VisitForAccumulatorValue(args->at(1));
3639 3680
3640 if (FLAG_new_string_add) { 3681 __ pop(edx);
3641 VisitForStackValue(args->at(0)); 3682 StringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED);
3642 VisitForAccumulatorValue(args->at(1)); 3683 __ CallStub(&stub);
3643
3644 __ pop(edx);
3645 NewStringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED);
3646 __ CallStub(&stub);
3647 } else {
3648 VisitForStackValue(args->at(0));
3649 VisitForStackValue(args->at(1));
3650
3651 StringAddStub stub(STRING_ADD_CHECK_BOTH);
3652 __ CallStub(&stub);
3653 }
3654 context()->Plug(eax); 3684 context()->Plug(eax);
3655 } 3685 }
3656 3686
3657 3687
3658 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 3688 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3659 ZoneList<Expression*>* args = expr->arguments(); 3689 ZoneList<Expression*>* args = expr->arguments();
3660 ASSERT_EQ(2, args->length()); 3690 ASSERT_EQ(2, args->length());
3661 3691
3662 VisitForStackValue(args->at(0)); 3692 VisitForStackValue(args->at(0));
3663 VisitForStackValue(args->at(1)); 3693 VisitForStackValue(args->at(1));
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
3720 } 3750 }
3721 3751
3722 3752
3723 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3753 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3724 // Load the arguments on the stack and call the stub. 3754 // Load the arguments on the stack and call the stub.
3725 RegExpConstructResultStub stub; 3755 RegExpConstructResultStub stub;
3726 ZoneList<Expression*>* args = expr->arguments(); 3756 ZoneList<Expression*>* args = expr->arguments();
3727 ASSERT(args->length() == 3); 3757 ASSERT(args->length() == 3);
3728 VisitForStackValue(args->at(0)); 3758 VisitForStackValue(args->at(0));
3729 VisitForStackValue(args->at(1)); 3759 VisitForStackValue(args->at(1));
3730 VisitForStackValue(args->at(2)); 3760 VisitForAccumulatorValue(args->at(2));
3761 __ pop(ebx);
3762 __ pop(ecx);
3731 __ CallStub(&stub); 3763 __ CallStub(&stub);
3732 context()->Plug(eax); 3764 context()->Plug(eax);
3733 } 3765 }
3734 3766
3735 3767
3736 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 3768 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3737 ZoneList<Expression*>* args = expr->arguments(); 3769 ZoneList<Expression*>* args = expr->arguments();
3738 ASSERT_EQ(2, args->length()); 3770 ASSERT_EQ(2, args->length());
3739 3771
3740 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3772 ASSERT_NE(NULL, args->at(0)->AsLiteral());
(...skipping 14 matching lines...) Expand all
3755 Register cache = ebx; 3787 Register cache = ebx;
3756 Register tmp = ecx; 3788 Register tmp = ecx;
3757 __ mov(cache, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX)); 3789 __ mov(cache, ContextOperand(esi, Context::GLOBAL_OBJECT_INDEX));
3758 __ mov(cache, 3790 __ mov(cache,
3759 FieldOperand(cache, GlobalObject::kNativeContextOffset)); 3791 FieldOperand(cache, GlobalObject::kNativeContextOffset));
3760 __ mov(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX)); 3792 __ mov(cache, ContextOperand(cache, Context::JSFUNCTION_RESULT_CACHES_INDEX));
3761 __ mov(cache, 3793 __ mov(cache,
3762 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id))); 3794 FieldOperand(cache, FixedArray::OffsetOfElementAt(cache_id)));
3763 3795
3764 Label done, not_found; 3796 Label done, not_found;
3765 // tmp now holds finger offset as a smi.
3766 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); 3797 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1);
3767 __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset)); 3798 __ mov(tmp, FieldOperand(cache, JSFunctionResultCache::kFingerOffset));
3768 __ cmp(key, CodeGenerator::FixedArrayElementOperand(cache, tmp)); 3799 // tmp now holds finger offset as a smi.
3800 __ cmp(key, FixedArrayElementOperand(cache, tmp));
3769 __ j(not_equal, &not_found); 3801 __ j(not_equal, &not_found);
3770 3802
3771 __ mov(eax, CodeGenerator::FixedArrayElementOperand(cache, tmp, 1)); 3803 __ mov(eax, FixedArrayElementOperand(cache, tmp, 1));
3772 __ jmp(&done); 3804 __ jmp(&done);
3773 3805
3774 __ bind(&not_found); 3806 __ bind(&not_found);
3775 // Call runtime to perform the lookup. 3807 // Call runtime to perform the lookup.
3776 __ push(cache); 3808 __ push(cache);
3777 __ push(key); 3809 __ push(key);
3778 __ CallRuntime(Runtime::kGetFromCache, 2); 3810 __ CallRuntime(Runtime::kGetFromCache, 2);
3779 3811
3780 __ bind(&done); 3812 __ bind(&done);
3781 context()->Plug(eax); 3813 context()->Plug(eax);
3782 } 3814 }
3783 3815
3784 3816
3785 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
3786 ZoneList<Expression*>* args = expr->arguments();
3787 ASSERT_EQ(2, args->length());
3788
3789 Register right = eax;
3790 Register left = ebx;
3791 Register tmp = ecx;
3792
3793 VisitForStackValue(args->at(0));
3794 VisitForAccumulatorValue(args->at(1));
3795 __ pop(left);
3796
3797 Label done, fail, ok;
3798 __ cmp(left, right);
3799 __ j(equal, &ok);
3800 // Fail if either is a non-HeapObject.
3801 __ mov(tmp, left);
3802 __ and_(tmp, right);
3803 __ JumpIfSmi(tmp, &fail);
3804 __ mov(tmp, FieldOperand(left, HeapObject::kMapOffset));
3805 __ CmpInstanceType(tmp, JS_REGEXP_TYPE);
3806 __ j(not_equal, &fail);
3807 __ cmp(tmp, FieldOperand(right, HeapObject::kMapOffset));
3808 __ j(not_equal, &fail);
3809 __ mov(tmp, FieldOperand(left, JSRegExp::kDataOffset));
3810 __ cmp(tmp, FieldOperand(right, JSRegExp::kDataOffset));
3811 __ j(equal, &ok);
3812 __ bind(&fail);
3813 __ mov(eax, Immediate(isolate()->factory()->false_value()));
3814 __ jmp(&done);
3815 __ bind(&ok);
3816 __ mov(eax, Immediate(isolate()->factory()->true_value()));
3817 __ bind(&done);
3818
3819 context()->Plug(eax);
3820 }
3821
3822
3823 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 3817 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3824 ZoneList<Expression*>* args = expr->arguments(); 3818 ZoneList<Expression*>* args = expr->arguments();
3825 ASSERT(args->length() == 1); 3819 ASSERT(args->length() == 1);
3826 3820
3827 VisitForAccumulatorValue(args->at(0)); 3821 VisitForAccumulatorValue(args->at(0));
3828 3822
3829 __ AssertString(eax); 3823 __ AssertString(eax);
3830 3824
3831 Label materialize_true, materialize_false; 3825 Label materialize_true, materialize_false;
3832 Label* if_true = NULL; 3826 Label* if_true = NULL;
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
4127 if (name->length() > 0 && name->Get(0) == '_') { 4121 if (name->length() > 0 && name->Get(0) == '_') {
4128 Comment cmnt(masm_, "[ InlineRuntimeCall"); 4122 Comment cmnt(masm_, "[ InlineRuntimeCall");
4129 EmitInlineRuntimeCall(expr); 4123 EmitInlineRuntimeCall(expr);
4130 return; 4124 return;
4131 } 4125 }
4132 4126
4133 Comment cmnt(masm_, "[ CallRuntime"); 4127 Comment cmnt(masm_, "[ CallRuntime");
4134 ZoneList<Expression*>* args = expr->arguments(); 4128 ZoneList<Expression*>* args = expr->arguments();
4135 4129
4136 if (expr->is_jsruntime()) { 4130 if (expr->is_jsruntime()) {
4137 // Prepare for calling JS runtime function. 4131 // Push the builtins object as receiver.
4138 __ mov(eax, GlobalObjectOperand()); 4132 __ mov(eax, GlobalObjectOperand());
4139 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset)); 4133 __ push(FieldOperand(eax, GlobalObject::kBuiltinsOffset));
4140 }
4141 4134
4142 // Push the arguments ("left-to-right"). 4135 // Load the function from the receiver.
4143 int arg_count = args->length(); 4136 __ mov(edx, Operand(esp, 0));
4144 for (int i = 0; i < arg_count; i++) { 4137 __ mov(ecx, Immediate(expr->name()));
4145 VisitForStackValue(args->at(i)); 4138 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4146 }
4147 4139
4148 if (expr->is_jsruntime()) { 4140 // Push the target function under the receiver.
4149 // Call the JS runtime function via a call IC. 4141 __ push(Operand(esp, 0));
4150 __ Set(ecx, Immediate(expr->name())); 4142 __ mov(Operand(esp, kPointerSize), eax);
4151 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); 4143
4152 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); 4144 // Code common for calls using the IC.
4145 ZoneList<Expression*>* args = expr->arguments();
4146 int arg_count = args->length();
4147 for (int i = 0; i < arg_count; i++) {
4148 VisitForStackValue(args->at(i));
4149 }
4150
4151 // Record source position of the IC call.
4152 SetSourcePosition(expr->position());
4153 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
4154 __ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
4155 __ CallStub(&stub);
4153 // Restore context register. 4156 // Restore context register.
4154 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 4157 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
4158 context()->DropAndPlug(1, eax);
4159
4155 } else { 4160 } else {
4161 // Push the arguments ("left-to-right").
4162 int arg_count = args->length();
4163 for (int i = 0; i < arg_count; i++) {
4164 VisitForStackValue(args->at(i));
4165 }
4166
4156 // Call the C runtime function. 4167 // Call the C runtime function.
4157 __ CallRuntime(expr->function(), arg_count); 4168 __ CallRuntime(expr->function(), arg_count);
4169
4170 context()->Plug(eax);
4158 } 4171 }
4159 context()->Plug(eax);
4160 } 4172 }
4161 4173
4162 4174
4163 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 4175 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4164 switch (expr->op()) { 4176 switch (expr->op()) {
4165 case Token::DELETE: { 4177 case Token::DELETE: {
4166 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 4178 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4167 Property* property = expr->expression()->AsProperty(); 4179 Property* property = expr->expression()->AsProperty();
4168 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 4180 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4169 4181
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
4398 } 4410 }
4399 4411
4400 // Record position before stub call. 4412 // Record position before stub call.
4401 SetSourcePosition(expr->position()); 4413 SetSourcePosition(expr->position());
4402 4414
4403 // Call stub for +1/-1. 4415 // Call stub for +1/-1.
4404 __ bind(&stub_call); 4416 __ bind(&stub_call);
4405 __ mov(edx, eax); 4417 __ mov(edx, eax);
4406 __ mov(eax, Immediate(Smi::FromInt(1))); 4418 __ mov(eax, Immediate(Smi::FromInt(1)));
4407 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE); 4419 BinaryOpICStub stub(expr->binary_op(), NO_OVERWRITE);
4408 CallIC(stub.GetCode(isolate()), 4420 CallIC(stub.GetCode(isolate()), expr->CountBinOpFeedbackId());
4409 NOT_CONTEXTUAL,
4410 expr->CountBinOpFeedbackId());
4411 patch_site.EmitPatchInfo(); 4421 patch_site.EmitPatchInfo();
4412 __ bind(&done); 4422 __ bind(&done);
4413 4423
4414 // Store the value returned in eax. 4424 // Store the value returned in eax.
4415 switch (assign_type) { 4425 switch (assign_type) {
4416 case VARIABLE: 4426 case VARIABLE:
4417 if (expr->is_postfix()) { 4427 if (expr->is_postfix()) {
4418 // Perform the assignment as if via '='. 4428 // Perform the assignment as if via '='.
4419 { EffectContext context(this); 4429 { EffectContext context(this);
4420 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4430 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
(...skipping 10 matching lines...) Expand all
4431 // Perform the assignment as if via '='. 4441 // Perform the assignment as if via '='.
4432 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4442 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4433 Token::ASSIGN); 4443 Token::ASSIGN);
4434 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4444 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4435 context()->Plug(eax); 4445 context()->Plug(eax);
4436 } 4446 }
4437 break; 4447 break;
4438 case NAMED_PROPERTY: { 4448 case NAMED_PROPERTY: {
4439 __ mov(ecx, prop->key()->AsLiteral()->value()); 4449 __ mov(ecx, prop->key()->AsLiteral()->value());
4440 __ pop(edx); 4450 __ pop(edx);
4441 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); 4451 CallStoreIC(expr->CountStoreFeedbackId());
4442 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4452 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4443 if (expr->is_postfix()) { 4453 if (expr->is_postfix()) {
4444 if (!context()->IsEffect()) { 4454 if (!context()->IsEffect()) {
4445 context()->PlugTOS(); 4455 context()->PlugTOS();
4446 } 4456 }
4447 } else { 4457 } else {
4448 context()->Plug(eax); 4458 context()->Plug(eax);
4449 } 4459 }
4450 break; 4460 break;
4451 } 4461 }
4452 case KEYED_PROPERTY: { 4462 case KEYED_PROPERTY: {
4453 __ pop(ecx); 4463 __ pop(ecx);
4454 __ pop(edx); 4464 __ pop(edx);
4455 Handle<Code> ic = is_classic_mode() 4465 Handle<Code> ic = is_classic_mode()
4456 ? isolate()->builtins()->KeyedStoreIC_Initialize() 4466 ? isolate()->builtins()->KeyedStoreIC_Initialize()
4457 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 4467 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4458 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); 4468 CallIC(ic, expr->CountStoreFeedbackId());
4459 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4469 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4460 if (expr->is_postfix()) { 4470 if (expr->is_postfix()) {
4461 // Result is on the stack 4471 // Result is on the stack
4462 if (!context()->IsEffect()) { 4472 if (!context()->IsEffect()) {
4463 context()->PlugTOS(); 4473 context()->PlugTOS();
4464 } 4474 }
4465 } else { 4475 } else {
4466 context()->Plug(eax); 4476 context()->Plug(eax);
4467 } 4477 }
4468 break; 4478 break;
4469 } 4479 }
4470 } 4480 }
4471 } 4481 }
4472 4482
4473 4483
4474 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4484 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4475 VariableProxy* proxy = expr->AsVariableProxy(); 4485 VariableProxy* proxy = expr->AsVariableProxy();
4476 ASSERT(!context()->IsEffect()); 4486 ASSERT(!context()->IsEffect());
4477 ASSERT(!context()->IsTest()); 4487 ASSERT(!context()->IsTest());
4478 4488
4479 if (proxy != NULL && proxy->var()->IsUnallocated()) { 4489 if (proxy != NULL && proxy->var()->IsUnallocated()) {
4480 Comment cmnt(masm_, "Global variable"); 4490 Comment cmnt(masm_, "[ Global variable");
4481 __ mov(edx, GlobalObjectOperand()); 4491 __ mov(edx, GlobalObjectOperand());
4482 __ mov(ecx, Immediate(proxy->name())); 4492 __ mov(ecx, Immediate(proxy->name()));
4483 // Use a regular load, not a contextual load, to avoid a reference 4493 // Use a regular load, not a contextual load, to avoid a reference
4484 // error. 4494 // error.
4485 CallLoadIC(NOT_CONTEXTUAL); 4495 CallLoadIC(NOT_CONTEXTUAL);
4486 PrepareForBailout(expr, TOS_REG); 4496 PrepareForBailout(expr, TOS_REG);
4487 context()->Plug(eax); 4497 context()->Plug(eax);
4488 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4498 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4499 Comment cmnt(masm_, "[ Lookup slot");
4489 Label done, slow; 4500 Label done, slow;
4490 4501
4491 // Generate code for loading from variables potentially shadowed 4502 // Generate code for loading from variables potentially shadowed
4492 // by eval-introduced variables. 4503 // by eval-introduced variables.
4493 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); 4504 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
4494 4505
4495 __ bind(&slow); 4506 __ bind(&slow);
4496 __ push(esi); 4507 __ push(esi);
4497 __ push(Immediate(proxy->name())); 4508 __ push(Immediate(proxy->name()));
4498 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4509 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
4637 __ or_(ecx, eax); 4648 __ or_(ecx, eax);
4638 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear); 4649 patch_site.EmitJumpIfNotSmi(ecx, &slow_case, Label::kNear);
4639 __ cmp(edx, eax); 4650 __ cmp(edx, eax);
4640 Split(cc, if_true, if_false, NULL); 4651 Split(cc, if_true, if_false, NULL);
4641 __ bind(&slow_case); 4652 __ bind(&slow_case);
4642 } 4653 }
4643 4654
4644 // Record position and call the compare IC. 4655 // Record position and call the compare IC.
4645 SetSourcePosition(expr->position()); 4656 SetSourcePosition(expr->position());
4646 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 4657 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
4647 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); 4658 CallIC(ic, expr->CompareOperationFeedbackId());
4648 patch_site.EmitPatchInfo(); 4659 patch_site.EmitPatchInfo();
4649 4660
4650 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4661 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4651 __ test(eax, eax); 4662 __ test(eax, eax);
4652 Split(cc, if_true, if_false, fall_through); 4663 Split(cc, if_true, if_false, fall_through);
4653 } 4664 }
4654 } 4665 }
4655 4666
4656 // Convert the result of the comparison into one expected for this 4667 // Convert the result of the comparison into one expected for this
4657 // expression's context. 4668 // expression's context.
(...skipping 15 matching lines...) Expand all
4673 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4684 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4674 4685
4675 Handle<Object> nil_value = nil == kNullValue 4686 Handle<Object> nil_value = nil == kNullValue
4676 ? isolate()->factory()->null_value() 4687 ? isolate()->factory()->null_value()
4677 : isolate()->factory()->undefined_value(); 4688 : isolate()->factory()->undefined_value();
4678 if (expr->op() == Token::EQ_STRICT) { 4689 if (expr->op() == Token::EQ_STRICT) {
4679 __ cmp(eax, nil_value); 4690 __ cmp(eax, nil_value);
4680 Split(equal, if_true, if_false, fall_through); 4691 Split(equal, if_true, if_false, fall_through);
4681 } else { 4692 } else {
4682 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4693 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4683 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); 4694 CallIC(ic, expr->CompareOperationFeedbackId());
4684 __ test(eax, eax); 4695 __ test(eax, eax);
4685 Split(not_zero, if_true, if_false, fall_through); 4696 Split(not_zero, if_true, if_false, fall_through);
4686 } 4697 }
4687 context()->Plug(if_true, if_false); 4698 context()->Plug(if_true, if_false);
4688 } 4699 }
4689 4700
4690 4701
4691 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4702 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4692 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 4703 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
4693 context()->Plug(eax); 4704 context()->Plug(eax);
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
4901 4912
4902 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(), 4913 ASSERT_EQ(isolate->builtins()->OsrAfterStackCheck()->entry(),
4903 Assembler::target_address_at(call_target_address)); 4914 Assembler::target_address_at(call_target_address));
4904 return OSR_AFTER_STACK_CHECK; 4915 return OSR_AFTER_STACK_CHECK;
4905 } 4916 }
4906 4917
4907 4918
4908 } } // namespace v8::internal 4919 } } // namespace v8::internal
4909 4920
4910 #endif // V8_TARGET_ARCH_IA32 4921 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/disasm-ia32.cc ('k') | src/ia32/ic-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698