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

Side by Side Diff: src/mips/full-codegen-mips.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/mips/deoptimizer-mips.cc ('k') | src/mips/ic-mips.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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 } 77 }
78 78
79 // When initially emitting this ensure that a jump is always generated to skip 79 // When initially emitting this ensure that a jump is always generated to skip
80 // the inlined smi code. 80 // the inlined smi code.
81 void EmitJumpIfNotSmi(Register reg, Label* target) { 81 void EmitJumpIfNotSmi(Register reg, Label* target) {
82 ASSERT(!patch_site_.is_bound() && !info_emitted_); 82 ASSERT(!patch_site_.is_bound() && !info_emitted_);
83 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); 83 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
84 __ bind(&patch_site_); 84 __ bind(&patch_site_);
85 __ andi(at, reg, 0); 85 __ andi(at, reg, 0);
86 // Always taken before patched. 86 // Always taken before patched.
87 __ Branch(target, eq, at, Operand(zero_reg)); 87 __ BranchShort(target, eq, at, Operand(zero_reg));
88 } 88 }
89 89
90 // When initially emitting this ensure that a jump is never generated to skip 90 // When initially emitting this ensure that a jump is never generated to skip
91 // the inlined smi code. 91 // the inlined smi code.
92 void EmitJumpIfSmi(Register reg, Label* target) { 92 void EmitJumpIfSmi(Register reg, Label* target) {
93 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); 93 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
94 ASSERT(!patch_site_.is_bound() && !info_emitted_); 94 ASSERT(!patch_site_.is_bound() && !info_emitted_);
95 __ bind(&patch_site_); 95 __ bind(&patch_site_);
96 __ andi(at, reg, 0); 96 __ andi(at, reg, 0);
97 // Never taken before patched. 97 // Never taken before patched.
98 __ Branch(target, ne, at, Operand(zero_reg)); 98 __ BranchShort(target, ne, at, Operand(zero_reg));
99 } 99 }
100 100
101 void EmitPatchInfo() { 101 void EmitPatchInfo() {
102 if (patch_site_.is_bound()) { 102 if (patch_site_.is_bound()) {
103 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_); 103 int delta_to_patch_site = masm_->InstructionsGeneratedSince(&patch_site_);
104 Register reg = Register::from_code(delta_to_patch_site / kImm16Mask); 104 Register reg = Register::from_code(delta_to_patch_site / kImm16Mask);
105 __ andi(zero_reg, reg, delta_to_patch_site % kImm16Mask); 105 __ andi(zero_reg, reg, delta_to_patch_site % kImm16Mask);
106 #ifdef DEBUG 106 #ifdef DEBUG
107 info_emitted_ = true; 107 info_emitted_ = true;
108 #endif 108 #endif
(...skipping 22 matching lines...) Expand all
131 // o fp: our caller's frame pointer 131 // o fp: our caller's frame pointer
132 // o sp: stack pointer 132 // o sp: stack pointer
133 // o ra: return address 133 // o ra: return address
134 // 134 //
135 // The function builds a JS frame. Please see JavaScriptFrameConstants in 135 // The function builds a JS frame. Please see JavaScriptFrameConstants in
136 // frames-mips.h for its layout. 136 // frames-mips.h for its layout.
137 void FullCodeGenerator::Generate() { 137 void FullCodeGenerator::Generate() {
138 CompilationInfo* info = info_; 138 CompilationInfo* info = info_;
139 handler_table_ = 139 handler_table_ =
140 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED); 140 isolate()->factory()->NewFixedArray(function()->handler_count(), TENURED);
141
142 InitializeFeedbackVector();
143
141 profiling_counter_ = isolate()->factory()->NewCell( 144 profiling_counter_ = isolate()->factory()->NewCell(
142 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate())); 145 Handle<Smi>(Smi::FromInt(FLAG_interrupt_budget), isolate()));
143 SetFunctionPosition(function()); 146 SetFunctionPosition(function());
144 Comment cmnt(masm_, "[ function compiled by full code generator"); 147 Comment cmnt(masm_, "[ function compiled by full code generator");
145 148
146 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 149 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
147 150
148 #ifdef DEBUG 151 #ifdef DEBUG
149 if (strlen(FLAG_stop_at) > 0 && 152 if (strlen(FLAG_stop_at) > 0 &&
150 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 153 info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 } 207 }
205 } 208 }
206 209
207 bool function_in_register = true; 210 bool function_in_register = true;
208 211
209 // Possibly allocate a local context. 212 // Possibly allocate a local context.
210 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 213 int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
211 if (heap_slots > 0) { 214 if (heap_slots > 0) {
212 Comment cmnt(masm_, "[ Allocate context"); 215 Comment cmnt(masm_, "[ Allocate context");
213 // Argument to NewContext is the function, which is still in a1. 216 // Argument to NewContext is the function, which is still in a1.
214 __ push(a1);
215 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) { 217 if (FLAG_harmony_scoping && info->scope()->is_global_scope()) {
218 __ push(a1);
216 __ Push(info->scope()->GetScopeInfo()); 219 __ Push(info->scope()->GetScopeInfo());
217 __ CallRuntime(Runtime::kNewGlobalContext, 2); 220 __ CallRuntime(Runtime::kNewGlobalContext, 2);
218 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) { 221 } else if (heap_slots <= FastNewContextStub::kMaximumSlots) {
219 FastNewContextStub stub(heap_slots); 222 FastNewContextStub stub(heap_slots);
220 __ CallStub(&stub); 223 __ CallStub(&stub);
221 } else { 224 } else {
225 __ push(a1);
222 __ CallRuntime(Runtime::kNewFunctionContext, 1); 226 __ CallRuntime(Runtime::kNewFunctionContext, 1);
223 } 227 }
224 function_in_register = false; 228 function_in_register = false;
225 // Context is returned in both v0 and cp. It replaces the context 229 // Context is returned in v0. It replaces the context passed to us.
226 // passed to us. It's saved in the stack and kept live in cp. 230 // It's saved in the stack and kept live in cp.
227 __ sw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 231 __ mov(cp, v0);
232 __ sw(v0, MemOperand(fp, StandardFrameConstants::kContextOffset));
228 // Copy any necessary parameters into the context. 233 // Copy any necessary parameters into the context.
229 int num_parameters = info->scope()->num_parameters(); 234 int num_parameters = info->scope()->num_parameters();
230 for (int i = 0; i < num_parameters; i++) { 235 for (int i = 0; i < num_parameters; i++) {
231 Variable* var = scope()->parameter(i); 236 Variable* var = scope()->parameter(i);
232 if (var->IsContextSlot()) { 237 if (var->IsContextSlot()) {
233 int parameter_offset = StandardFrameConstants::kCallerSPOffset + 238 int parameter_offset = StandardFrameConstants::kCallerSPOffset +
234 (num_parameters - 1 - i) * kPointerSize; 239 (num_parameters - 1 - i) * kPointerSize;
235 // Load parameter from stack. 240 // Load parameter from stack.
236 __ lw(a0, MemOperand(fp, parameter_offset)); 241 __ lw(a0, MemOperand(fp, parameter_offset));
237 // Store it in the context. 242 // Store it in the context.
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 } 675 }
671 } 676 }
672 677
673 678
674 void FullCodeGenerator::DoTest(Expression* condition, 679 void FullCodeGenerator::DoTest(Expression* condition,
675 Label* if_true, 680 Label* if_true,
676 Label* if_false, 681 Label* if_false,
677 Label* fall_through) { 682 Label* fall_through) {
678 __ mov(a0, result_register()); 683 __ mov(a0, result_register());
679 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate()); 684 Handle<Code> ic = ToBooleanStub::GetUninitialized(isolate());
680 CallIC(ic, NOT_CONTEXTUAL, condition->test_id()); 685 CallIC(ic, condition->test_id());
681 __ mov(at, zero_reg); 686 __ mov(at, zero_reg);
682 Split(ne, v0, Operand(at), if_true, if_false, fall_through); 687 Split(ne, v0, Operand(at), if_true, if_false, fall_through);
683 } 688 }
684 689
685 690
686 void FullCodeGenerator::Split(Condition cc, 691 void FullCodeGenerator::Split(Condition cc,
687 Register lhs, 692 Register lhs,
688 const Operand& rhs, 693 const Operand& rhs,
689 Label* if_true, 694 Label* if_true,
690 Label* if_false, 695 Label* if_false,
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
1035 __ Branch(&next_test, ne, a1, Operand(a0)); 1040 __ Branch(&next_test, ne, a1, Operand(a0));
1036 __ Drop(1); // Switch value is no longer needed. 1041 __ Drop(1); // Switch value is no longer needed.
1037 __ Branch(clause->body_target()); 1042 __ Branch(clause->body_target());
1038 1043
1039 __ bind(&slow_case); 1044 __ bind(&slow_case);
1040 } 1045 }
1041 1046
1042 // Record position before stub call for type feedback. 1047 // Record position before stub call for type feedback.
1043 SetSourcePosition(clause->position()); 1048 SetSourcePosition(clause->position());
1044 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT); 1049 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), Token::EQ_STRICT);
1045 CallIC(ic, NOT_CONTEXTUAL, clause->CompareId()); 1050 CallIC(ic, clause->CompareId());
1046 patch_site.EmitPatchInfo(); 1051 patch_site.EmitPatchInfo();
1047 1052
1048 Label skip; 1053 Label skip;
1049 __ Branch(&skip); 1054 __ Branch(&skip);
1050 PrepareForBailout(clause, TOS_REG); 1055 PrepareForBailout(clause, TOS_REG);
1051 __ LoadRoot(at, Heap::kTrueValueRootIndex); 1056 __ LoadRoot(at, Heap::kTrueValueRootIndex);
1052 __ Branch(&next_test, ne, v0, Operand(at)); 1057 __ Branch(&next_test, ne, v0, Operand(at));
1053 __ Drop(1); 1058 __ Drop(1);
1054 __ Branch(clause->body_target()); 1059 __ Branch(clause->body_target());
1055 __ bind(&skip); 1060 __ bind(&skip);
(...skipping 22 matching lines...) Expand all
1078 VisitStatements(clause->statements()); 1083 VisitStatements(clause->statements());
1079 } 1084 }
1080 1085
1081 __ bind(nested_statement.break_label()); 1086 __ bind(nested_statement.break_label());
1082 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); 1087 PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1083 } 1088 }
1084 1089
1085 1090
1086 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { 1091 void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1087 Comment cmnt(masm_, "[ ForInStatement"); 1092 Comment cmnt(masm_, "[ ForInStatement");
1093 int slot = stmt->ForInFeedbackSlot();
1088 SetStatementPosition(stmt); 1094 SetStatementPosition(stmt);
1089 1095
1090 Label loop, exit; 1096 Label loop, exit;
1091 ForIn loop_statement(this, stmt); 1097 ForIn loop_statement(this, stmt);
1092 increment_loop_depth(); 1098 increment_loop_depth();
1093 1099
1094 // Get the object to enumerate over. If the object is null or undefined, skip 1100 // Get the object to enumerate over. If the object is null or undefined, skip
1095 // over the loop. See ECMA-262 version 5, section 12.6.4. 1101 // over the loop. See ECMA-262 version 5, section 12.6.4.
1096 VisitForAccumulatorValue(stmt->enumerable()); 1102 VisitForAccumulatorValue(stmt->enumerable());
1097 __ mov(a0, result_register()); // Result as param to InvokeBuiltin below. 1103 __ mov(a0, result_register()); // Result as param to InvokeBuiltin below.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1150 __ bind(&use_cache); 1156 __ bind(&use_cache);
1151 1157
1152 __ EnumLength(a1, v0); 1158 __ EnumLength(a1, v0);
1153 __ Branch(&no_descriptors, eq, a1, Operand(Smi::FromInt(0))); 1159 __ Branch(&no_descriptors, eq, a1, Operand(Smi::FromInt(0)));
1154 1160
1155 __ LoadInstanceDescriptors(v0, a2); 1161 __ LoadInstanceDescriptors(v0, a2);
1156 __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheOffset)); 1162 __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheOffset));
1157 __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheBridgeCacheOffset)); 1163 __ lw(a2, FieldMemOperand(a2, DescriptorArray::kEnumCacheBridgeCacheOffset));
1158 1164
1159 // Set up the four remaining stack slots. 1165 // Set up the four remaining stack slots.
1160 __ push(v0); // Map.
1161 __ li(a0, Operand(Smi::FromInt(0))); 1166 __ li(a0, Operand(Smi::FromInt(0)));
1162 // Push enumeration cache, enumeration cache length (as smi) and zero. 1167 // Push map, enumeration cache, enumeration cache length (as smi) and zero.
1163 __ Push(a2, a1, a0); 1168 __ Push(v0, a2, a1, a0);
1164 __ jmp(&loop); 1169 __ jmp(&loop);
1165 1170
1166 __ bind(&no_descriptors); 1171 __ bind(&no_descriptors);
1167 __ Drop(1); 1172 __ Drop(1);
1168 __ jmp(&exit); 1173 __ jmp(&exit);
1169 1174
1170 // We got a fixed array in register v0. Iterate through that. 1175 // We got a fixed array in register v0. Iterate through that.
1171 Label non_proxy; 1176 Label non_proxy;
1172 __ bind(&fixed_array); 1177 __ bind(&fixed_array);
1173 1178
1174 Handle<Cell> cell = isolate()->factory()->NewCell( 1179 Handle<Object> feedback = Handle<Object>(
1175 Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker), 1180 Smi::FromInt(TypeFeedbackInfo::kForInFastCaseMarker),
1176 isolate())); 1181 isolate());
1177 RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell); 1182 StoreFeedbackVectorSlot(slot, feedback);
1178 __ li(a1, cell); 1183 __ li(a1, FeedbackVector());
1179 __ li(a2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker))); 1184 __ li(a2, Operand(Smi::FromInt(TypeFeedbackInfo::kForInSlowCaseMarker)));
1180 __ sw(a2, FieldMemOperand(a1, Cell::kValueOffset)); 1185 __ sw(a2, FieldMemOperand(a1, FixedArray::OffsetOfElementAt(slot)));
1181 1186
1182 __ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check 1187 __ li(a1, Operand(Smi::FromInt(1))); // Smi indicates slow check
1183 __ lw(a2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object 1188 __ lw(a2, MemOperand(sp, 0 * kPointerSize)); // Get enumerated object
1184 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 1189 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
1185 __ GetObjectType(a2, a3, a3); 1190 __ GetObjectType(a2, a3, a3);
1186 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE)); 1191 __ Branch(&non_proxy, gt, a3, Operand(LAST_JS_PROXY_TYPE));
1187 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy 1192 __ li(a1, Operand(Smi::FromInt(0))); // Zero indicates proxy
1188 __ bind(&non_proxy); 1193 __ bind(&non_proxy);
1189 __ Push(a1, v0); // Smi and array 1194 __ Push(a1, v0); // Smi and array
1190 __ lw(a1, FieldMemOperand(v0, FixedArray::kLengthOffset)); 1195 __ lw(a1, FieldMemOperand(v0, FixedArray::kLengthOffset));
(...skipping 27 matching lines...) Expand all
1218 __ Branch(&update_each, eq, t0, Operand(a2)); 1223 __ Branch(&update_each, eq, t0, Operand(a2));
1219 1224
1220 // For proxies, no filtering is done. 1225 // For proxies, no filtering is done.
1221 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet. 1226 // TODO(rossberg): What if only a prototype is a proxy? Not specified yet.
1222 ASSERT_EQ(Smi::FromInt(0), 0); 1227 ASSERT_EQ(Smi::FromInt(0), 0);
1223 __ Branch(&update_each, eq, a2, Operand(zero_reg)); 1228 __ Branch(&update_each, eq, a2, Operand(zero_reg));
1224 1229
1225 // Convert the entry to a string or (smi) 0 if it isn't a property 1230 // Convert the entry to a string or (smi) 0 if it isn't a property
1226 // any more. If the property has been removed while iterating, we 1231 // any more. If the property has been removed while iterating, we
1227 // just skip it. 1232 // just skip it.
1228 __ push(a1); // Enumerable. 1233 __ Push(a1, a3); // Enumerable and current entry.
1229 __ push(a3); // Current entry.
1230 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION); 1234 __ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
1231 __ mov(a3, result_register()); 1235 __ mov(a3, result_register());
1232 __ Branch(loop_statement.continue_label(), eq, a3, Operand(zero_reg)); 1236 __ Branch(loop_statement.continue_label(), eq, a3, Operand(zero_reg));
1233 1237
1234 // Update the 'each' property or variable from the possibly filtered 1238 // Update the 'each' property or variable from the possibly filtered
1235 // entry in register a3. 1239 // entry in register a3.
1236 __ bind(&update_each); 1240 __ bind(&update_each);
1237 __ mov(result_register(), a3); 1241 __ mov(result_register(), a3);
1238 // Perform the assignment as if via '='. 1242 // Perform the assignment as if via '='.
1239 { EffectContext context(this); 1243 { EffectContext context(this);
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1479 1483
1480 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { 1484 void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) {
1481 // Record position before possible IC call. 1485 // Record position before possible IC call.
1482 SetSourcePosition(proxy->position()); 1486 SetSourcePosition(proxy->position());
1483 Variable* var = proxy->var(); 1487 Variable* var = proxy->var();
1484 1488
1485 // Three cases: global variables, lookup variables, and all other types of 1489 // Three cases: global variables, lookup variables, and all other types of
1486 // variables. 1490 // variables.
1487 switch (var->location()) { 1491 switch (var->location()) {
1488 case Variable::UNALLOCATED: { 1492 case Variable::UNALLOCATED: {
1489 Comment cmnt(masm_, "Global variable"); 1493 Comment cmnt(masm_, "[ Global variable");
1490 // Use inline caching. Variable name is passed in a2 and the global 1494 // Use inline caching. Variable name is passed in a2 and the global
1491 // object (receiver) in a0. 1495 // object (receiver) in a0.
1492 __ lw(a0, GlobalObjectOperand()); 1496 __ lw(a0, GlobalObjectOperand());
1493 __ li(a2, Operand(var->name())); 1497 __ li(a2, Operand(var->name()));
1494 CallLoadIC(CONTEXTUAL); 1498 CallLoadIC(CONTEXTUAL);
1495 context()->Plug(v0); 1499 context()->Plug(v0);
1496 break; 1500 break;
1497 } 1501 }
1498 1502
1499 case Variable::PARAMETER: 1503 case Variable::PARAMETER:
1500 case Variable::LOCAL: 1504 case Variable::LOCAL:
1501 case Variable::CONTEXT: { 1505 case Variable::CONTEXT: {
1502 Comment cmnt(masm_, var->IsContextSlot() 1506 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1503 ? "Context variable" 1507 : "[ Stack variable");
1504 : "Stack variable");
1505 if (var->binding_needs_init()) { 1508 if (var->binding_needs_init()) {
1506 // var->scope() may be NULL when the proxy is located in eval code and 1509 // var->scope() may be NULL when the proxy is located in eval code and
1507 // refers to a potential outside binding. Currently those bindings are 1510 // refers to a potential outside binding. Currently those bindings are
1508 // always looked up dynamically, i.e. in that case 1511 // always looked up dynamically, i.e. in that case
1509 // var->location() == LOOKUP. 1512 // var->location() == LOOKUP.
1510 // always holds. 1513 // always holds.
1511 ASSERT(var->scope() != NULL); 1514 ASSERT(var->scope() != NULL);
1512 1515
1513 // Check if the binding really needs an initialization check. The check 1516 // Check if the binding really needs an initialization check. The check
1514 // can be skipped in the following situation: we have a LET or CONST 1517 // can be skipped in the following situation: we have a LET or CONST
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1559 } 1562 }
1560 context()->Plug(v0); 1563 context()->Plug(v0);
1561 break; 1564 break;
1562 } 1565 }
1563 } 1566 }
1564 context()->Plug(var); 1567 context()->Plug(var);
1565 break; 1568 break;
1566 } 1569 }
1567 1570
1568 case Variable::LOOKUP: { 1571 case Variable::LOOKUP: {
1572 Comment cmnt(masm_, "[ Lookup variable");
1569 Label done, slow; 1573 Label done, slow;
1570 // Generate code for loading from variables potentially shadowed 1574 // Generate code for loading from variables potentially shadowed
1571 // by eval-introduced variables. 1575 // by eval-introduced variables.
1572 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done); 1576 EmitDynamicLookupFastCase(var, NOT_INSIDE_TYPEOF, &slow, &done);
1573 __ bind(&slow); 1577 __ bind(&slow);
1574 Comment cmnt(masm_, "Lookup variable");
1575 __ li(a1, Operand(var->name())); 1578 __ li(a1, Operand(var->name()));
1576 __ Push(cp, a1); // Context and name. 1579 __ Push(cp, a1); // Context and name.
1577 __ CallRuntime(Runtime::kLoadContextSlot, 2); 1580 __ CallRuntime(Runtime::kLoadContextSlot, 2);
1578 __ bind(&done); 1581 __ bind(&done);
1579 context()->Plug(v0); 1582 context()->Plug(v0);
1580 } 1583 }
1581 } 1584 }
1582 } 1585 }
1583 1586
1584 1587
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1696 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 1699 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1697 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value())); 1700 ASSERT(!CompileTimeValue::IsCompileTimeValue(property->value()));
1698 // Fall through. 1701 // Fall through.
1699 case ObjectLiteral::Property::COMPUTED: 1702 case ObjectLiteral::Property::COMPUTED:
1700 if (key->value()->IsInternalizedString()) { 1703 if (key->value()->IsInternalizedString()) {
1701 if (property->emit_store()) { 1704 if (property->emit_store()) {
1702 VisitForAccumulatorValue(value); 1705 VisitForAccumulatorValue(value);
1703 __ mov(a0, result_register()); 1706 __ mov(a0, result_register());
1704 __ li(a2, Operand(key->value())); 1707 __ li(a2, Operand(key->value()));
1705 __ lw(a1, MemOperand(sp)); 1708 __ lw(a1, MemOperand(sp));
1706 CallStoreIC(NOT_CONTEXTUAL, key->LiteralFeedbackId()); 1709 CallStoreIC(key->LiteralFeedbackId());
1707 PrepareForBailoutForId(key->id(), NO_REGISTERS); 1710 PrepareForBailoutForId(key->id(), NO_REGISTERS);
1708 } else { 1711 } else {
1709 VisitForEffect(value); 1712 VisitForEffect(value);
1710 } 1713 }
1711 break; 1714 break;
1712 } 1715 }
1713 // Duplicate receiver on stack. 1716 // Duplicate receiver on stack.
1714 __ lw(a0, MemOperand(sp)); 1717 __ lw(a0, MemOperand(sp));
1715 __ push(a0); 1718 __ push(a0);
1716 VisitForStackValue(key); 1719 VisitForStackValue(key);
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after
2057 Label l_catch, l_try, l_suspend, l_continuation, l_resume; 2060 Label l_catch, l_try, l_suspend, l_continuation, l_resume;
2058 Label l_next, l_call, l_loop; 2061 Label l_next, l_call, l_loop;
2059 // Initial send value is undefined. 2062 // Initial send value is undefined.
2060 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); 2063 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
2061 __ Branch(&l_next); 2064 __ Branch(&l_next);
2062 2065
2063 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; } 2066 // catch (e) { receiver = iter; f = 'throw'; arg = e; goto l_call; }
2064 __ bind(&l_catch); 2067 __ bind(&l_catch);
2065 __ mov(a0, v0); 2068 __ mov(a0, v0);
2066 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos())); 2069 handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
2067 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw" 2070 __ LoadRoot(a2, Heap::kthrow_stringRootIndex); // "throw"
2068 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter 2071 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter
2069 __ Push(a3, a0); // iter, exception 2072 __ Push(a2, a3, a0); // "throw", iter, except
2070 __ jmp(&l_call); 2073 __ jmp(&l_call);
2071 2074
2072 // try { received = %yield result } 2075 // try { received = %yield result }
2073 // Shuffle the received result above a try handler and yield it without 2076 // Shuffle the received result above a try handler and yield it without
2074 // re-boxing. 2077 // re-boxing.
2075 __ bind(&l_try); 2078 __ bind(&l_try);
2076 __ pop(a0); // result 2079 __ pop(a0); // result
2077 __ PushTryHandler(StackHandler::CATCH, expr->index()); 2080 __ PushTryHandler(StackHandler::CATCH, expr->index());
2078 const int handler_size = StackHandlerConstants::kSize; 2081 const int handler_size = StackHandlerConstants::kSize;
2079 __ push(a0); // result 2082 __ push(a0); // result
2080 __ jmp(&l_suspend); 2083 __ jmp(&l_suspend);
2081 __ bind(&l_continuation); 2084 __ bind(&l_continuation);
2082 __ mov(a0, v0); 2085 __ mov(a0, v0);
2083 __ jmp(&l_resume); 2086 __ jmp(&l_resume);
2084 __ bind(&l_suspend); 2087 __ bind(&l_suspend);
2085 const int generator_object_depth = kPointerSize + handler_size; 2088 const int generator_object_depth = kPointerSize + handler_size;
2086 __ lw(a0, MemOperand(sp, generator_object_depth)); 2089 __ lw(a0, MemOperand(sp, generator_object_depth));
2087 __ push(a0); // g 2090 __ push(a0); // g
2088 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos())); 2091 ASSERT(l_continuation.pos() > 0 && Smi::IsValid(l_continuation.pos()));
2089 __ li(a1, Operand(Smi::FromInt(l_continuation.pos()))); 2092 __ li(a1, Operand(Smi::FromInt(l_continuation.pos())));
2090 __ sw(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset)); 2093 __ sw(a1, FieldMemOperand(a0, JSGeneratorObject::kContinuationOffset));
2091 __ sw(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset)); 2094 __ sw(cp, FieldMemOperand(a0, JSGeneratorObject::kContextOffset));
2092 __ mov(a1, cp); 2095 __ mov(a1, cp);
2093 __ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2, 2096 __ RecordWriteField(a0, JSGeneratorObject::kContextOffset, a1, a2,
2094 kRAHasBeenSaved, kDontSaveFPRegs); 2097 kRAHasBeenSaved, kDontSaveFPRegs);
2095 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1); 2098 __ CallRuntime(Runtime::kSuspendJSGeneratorObject, 1);
2096 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2099 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2097 __ pop(v0); // result 2100 __ pop(v0); // result
2098 EmitReturnSequence(); 2101 EmitReturnSequence();
2099 __ mov(a0, v0); 2102 __ mov(a0, v0);
2100 __ bind(&l_resume); // received in a0 2103 __ bind(&l_resume); // received in a0
2101 __ PopTryHandler(); 2104 __ PopTryHandler();
2102 2105
2103 // receiver = iter; f = 'next'; arg = received; 2106 // receiver = iter; f = 'next'; arg = received;
2104 __ bind(&l_next); 2107 __ bind(&l_next);
2105 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next" 2108 __ LoadRoot(a2, Heap::knext_stringRootIndex); // "next"
2106 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter 2109 __ lw(a3, MemOperand(sp, 1 * kPointerSize)); // iter
2107 __ Push(a3, a0); // iter, received 2110 __ Push(a2, a3, a0); // "next", iter, received
2108 2111
2109 // result = receiver[f](arg); 2112 // result = receiver[f](arg);
2110 __ bind(&l_call); 2113 __ bind(&l_call);
2111 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(1); 2114 __ lw(a1, MemOperand(sp, kPointerSize));
2112 CallIC(ic); 2115 __ lw(a0, MemOperand(sp, 2 * kPointerSize));
2116 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2117 CallIC(ic, TypeFeedbackId::None());
2118 __ mov(a0, v0);
2119 __ mov(a1, a0);
2120 __ sw(a1, MemOperand(sp, 2 * kPointerSize));
2121 CallFunctionStub stub(1, CALL_AS_METHOD);
2122 __ CallStub(&stub);
2123
2113 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2124 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2125 __ Drop(1); // The function is still on the stack; drop it.
2114 2126
2115 // if (!result.done) goto l_try; 2127 // if (!result.done) goto l_try;
2116 __ bind(&l_loop); 2128 __ bind(&l_loop);
2117 __ mov(a0, v0); 2129 __ mov(a0, v0);
2118 __ push(a0); // save result 2130 __ push(a0); // save result
2119 __ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done" 2131 __ LoadRoot(a2, Heap::kdone_stringRootIndex); // "done"
2120 CallLoadIC(NOT_CONTEXTUAL); // result.done in v0 2132 CallLoadIC(NOT_CONTEXTUAL); // result.done in v0
2121 __ mov(a0, v0); 2133 __ mov(a0, v0);
2122 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate()); 2134 Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
2123 CallIC(bool_ic); 2135 CallIC(bool_ic);
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
2293 // Call load IC. It has arguments receiver and property name a0 and a2. 2305 // Call load IC. It has arguments receiver and property name a0 and a2.
2294 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2306 CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
2295 } 2307 }
2296 2308
2297 2309
2298 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { 2310 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
2299 SetSourcePosition(prop->position()); 2311 SetSourcePosition(prop->position());
2300 __ mov(a0, result_register()); 2312 __ mov(a0, result_register());
2301 // Call keyed load IC. It has arguments key and receiver in a0 and a1. 2313 // Call keyed load IC. It has arguments key and receiver in a0 and a1.
2302 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); 2314 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
2303 CallIC(ic, NOT_CONTEXTUAL, prop->PropertyFeedbackId()); 2315 CallIC(ic, prop->PropertyFeedbackId());
2304 } 2316 }
2305 2317
2306 2318
2307 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, 2319 void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
2308 Token::Value op, 2320 Token::Value op,
2309 OverwriteMode mode, 2321 OverwriteMode mode,
2310 Expression* left_expr, 2322 Expression* left_expr,
2311 Expression* right_expr) { 2323 Expression* right_expr) {
2312 Label done, smi_case, stub_call; 2324 Label done, smi_case, stub_call;
2313 2325
2314 Register scratch1 = a2; 2326 Register scratch1 = a2;
2315 Register scratch2 = a3; 2327 Register scratch2 = a3;
2316 2328
2317 // Get the arguments. 2329 // Get the arguments.
2318 Register left = a1; 2330 Register left = a1;
2319 Register right = a0; 2331 Register right = a0;
2320 __ pop(left); 2332 __ pop(left);
2321 __ mov(a0, result_register()); 2333 __ mov(a0, result_register());
2322 2334
2323 // Perform combined smi check on both operands. 2335 // Perform combined smi check on both operands.
2324 __ Or(scratch1, left, Operand(right)); 2336 __ Or(scratch1, left, Operand(right));
2325 STATIC_ASSERT(kSmiTag == 0); 2337 STATIC_ASSERT(kSmiTag == 0);
2326 JumpPatchSite patch_site(masm_); 2338 JumpPatchSite patch_site(masm_);
2327 patch_site.EmitJumpIfSmi(scratch1, &smi_case); 2339 patch_site.EmitJumpIfSmi(scratch1, &smi_case);
2328 2340
2329 __ bind(&stub_call); 2341 __ bind(&stub_call);
2330 BinaryOpICStub stub(op, mode); 2342 BinaryOpICStub stub(op, mode);
2331 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, 2343 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId());
2332 expr->BinaryOperationFeedbackId());
2333 patch_site.EmitPatchInfo(); 2344 patch_site.EmitPatchInfo();
2334 __ jmp(&done); 2345 __ jmp(&done);
2335 2346
2336 __ bind(&smi_case); 2347 __ bind(&smi_case);
2337 // Smi case. This code works the same way as the smi-smi case in the type 2348 // Smi case. This code works the same way as the smi-smi case in the type
2338 // recording binary operation stub, see 2349 // recording binary operation stub, see
2339 switch (op) { 2350 switch (op) {
2340 case Token::SAR: 2351 case Token::SAR:
2341 __ Branch(&stub_call);
2342 __ GetLeastBitsFromSmi(scratch1, right, 5); 2352 __ GetLeastBitsFromSmi(scratch1, right, 5);
2343 __ srav(right, left, scratch1); 2353 __ srav(right, left, scratch1);
2344 __ And(v0, right, Operand(~kSmiTagMask)); 2354 __ And(v0, right, Operand(~kSmiTagMask));
2345 break; 2355 break;
2346 case Token::SHL: { 2356 case Token::SHL: {
2347 __ Branch(&stub_call);
2348 __ SmiUntag(scratch1, left); 2357 __ SmiUntag(scratch1, left);
2349 __ GetLeastBitsFromSmi(scratch2, right, 5); 2358 __ GetLeastBitsFromSmi(scratch2, right, 5);
2350 __ sllv(scratch1, scratch1, scratch2); 2359 __ sllv(scratch1, scratch1, scratch2);
2351 __ Addu(scratch2, scratch1, Operand(0x40000000)); 2360 __ Addu(scratch2, scratch1, Operand(0x40000000));
2352 __ Branch(&stub_call, lt, scratch2, Operand(zero_reg)); 2361 __ Branch(&stub_call, lt, scratch2, Operand(zero_reg));
2353 __ SmiTag(v0, scratch1); 2362 __ SmiTag(v0, scratch1);
2354 break; 2363 break;
2355 } 2364 }
2356 case Token::SHR: { 2365 case Token::SHR: {
2357 __ Branch(&stub_call);
2358 __ SmiUntag(scratch1, left); 2366 __ SmiUntag(scratch1, left);
2359 __ GetLeastBitsFromSmi(scratch2, right, 5); 2367 __ GetLeastBitsFromSmi(scratch2, right, 5);
2360 __ srlv(scratch1, scratch1, scratch2); 2368 __ srlv(scratch1, scratch1, scratch2);
2361 __ And(scratch2, scratch1, 0xc0000000); 2369 __ And(scratch2, scratch1, 0xc0000000);
2362 __ Branch(&stub_call, ne, scratch2, Operand(zero_reg)); 2370 __ Branch(&stub_call, ne, scratch2, Operand(zero_reg));
2363 __ SmiTag(v0, scratch1); 2371 __ SmiTag(v0, scratch1);
2364 break; 2372 break;
2365 } 2373 }
2366 case Token::ADD: 2374 case Token::ADD:
2367 __ AdduAndCheckForOverflow(v0, left, right, scratch1); 2375 __ AdduAndCheckForOverflow(v0, left, right, scratch1);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
2404 } 2412 }
2405 2413
2406 2414
2407 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, 2415 void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr,
2408 Token::Value op, 2416 Token::Value op,
2409 OverwriteMode mode) { 2417 OverwriteMode mode) {
2410 __ mov(a0, result_register()); 2418 __ mov(a0, result_register());
2411 __ pop(a1); 2419 __ pop(a1);
2412 BinaryOpICStub stub(op, mode); 2420 BinaryOpICStub stub(op, mode);
2413 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code. 2421 JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
2414 CallIC(stub.GetCode(isolate()), NOT_CONTEXTUAL, 2422 CallIC(stub.GetCode(isolate()), expr->BinaryOperationFeedbackId());
2415 expr->BinaryOperationFeedbackId());
2416 patch_site.EmitPatchInfo(); 2423 patch_site.EmitPatchInfo();
2417 context()->Plug(v0); 2424 context()->Plug(v0);
2418 } 2425 }
2419 2426
2420 2427
2421 void FullCodeGenerator::EmitAssignment(Expression* expr) { 2428 void FullCodeGenerator::EmitAssignment(Expression* expr) {
2422 // Invalid left-hand sides are rewritten by the parser to have a 'throw 2429 // Invalid left-hand sides are rewritten by the parser to have a 'throw
2423 // ReferenceError' on the left-hand side. 2430 // ReferenceError' on the left-hand side.
2424 if (!expr->IsValidLeftHandSide()) { 2431 if (!expr->IsValidLeftHandSide()) {
2425 VisitForEffect(expr); 2432 VisitForEffect(expr);
(...skipping 17 matching lines...) Expand all
2443 EffectContext context(this); 2450 EffectContext context(this);
2444 EmitVariableAssignment(var, Token::ASSIGN); 2451 EmitVariableAssignment(var, Token::ASSIGN);
2445 break; 2452 break;
2446 } 2453 }
2447 case NAMED_PROPERTY: { 2454 case NAMED_PROPERTY: {
2448 __ push(result_register()); // Preserve value. 2455 __ push(result_register()); // Preserve value.
2449 VisitForAccumulatorValue(prop->obj()); 2456 VisitForAccumulatorValue(prop->obj());
2450 __ mov(a1, result_register()); 2457 __ mov(a1, result_register());
2451 __ pop(a0); // Restore value. 2458 __ pop(a0); // Restore value.
2452 __ li(a2, Operand(prop->key()->AsLiteral()->value())); 2459 __ li(a2, Operand(prop->key()->AsLiteral()->value()));
2453 CallStoreIC(NOT_CONTEXTUAL); 2460 CallStoreIC();
2454 break; 2461 break;
2455 } 2462 }
2456 case KEYED_PROPERTY: { 2463 case KEYED_PROPERTY: {
2457 __ push(result_register()); // Preserve value. 2464 __ push(result_register()); // Preserve value.
2458 VisitForStackValue(prop->obj()); 2465 VisitForStackValue(prop->obj());
2459 VisitForAccumulatorValue(prop->key()); 2466 VisitForAccumulatorValue(prop->key());
2460 __ mov(a1, result_register()); 2467 __ mov(a1, result_register());
2461 __ Pop(a0, a2); // a0 = restored value. 2468 __ Pop(a0, a2); // a0 = restored value.
2462 Handle<Code> ic = is_classic_mode() 2469 Handle<Code> ic = is_classic_mode()
2463 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2470 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2464 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2471 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2465 CallIC(ic); 2472 CallIC(ic);
2466 break; 2473 break;
2467 } 2474 }
2468 } 2475 }
2469 context()->Plug(v0); 2476 context()->Plug(v0);
2470 } 2477 }
2471 2478
2472 2479
2480 void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
2481 Variable* var, MemOperand location) {
2482 __ sw(result_register(), location);
2483 if (var->IsContextSlot()) {
2484 // RecordWrite may destroy all its register arguments.
2485 __ Move(a3, result_register());
2486 int offset = Context::SlotOffset(var->index());
2487 __ RecordWriteContextSlot(
2488 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs);
2489 }
2490 }
2491
2492
2493 void FullCodeGenerator::EmitCallStoreContextSlot(
2494 Handle<String> name, LanguageMode mode) {
2495 __ li(a1, Operand(name));
2496 __ li(a0, Operand(Smi::FromInt(mode)));
2497 __ Push(v0, cp, a1, a0); // Value, context, name, strict mode.
2498 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2499 }
2500
2501
2473 void FullCodeGenerator::EmitVariableAssignment(Variable* var, 2502 void FullCodeGenerator::EmitVariableAssignment(Variable* var,
2474 Token::Value op) { 2503 Token::Value op) {
2475 if (var->IsUnallocated()) { 2504 if (var->IsUnallocated()) {
2476 // Global var, const, or let. 2505 // Global var, const, or let.
2477 __ mov(a0, result_register()); 2506 __ mov(a0, result_register());
2478 __ li(a2, Operand(var->name())); 2507 __ li(a2, Operand(var->name()));
2479 __ lw(a1, GlobalObjectOperand()); 2508 __ lw(a1, GlobalObjectOperand());
2480 CallStoreIC(CONTEXTUAL); 2509 CallStoreIC();
2510
2481 } else if (op == Token::INIT_CONST) { 2511 } else if (op == Token::INIT_CONST) {
2482 // Const initializers need a write barrier. 2512 // Const initializers need a write barrier.
2483 ASSERT(!var->IsParameter()); // No const parameters. 2513 ASSERT(!var->IsParameter()); // No const parameters.
2484 if (var->IsStackLocal()) { 2514 if (var->IsLookupSlot()) {
2515 __ li(a0, Operand(var->name()));
2516 __ Push(v0, cp, a0); // Context and name.
2517 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2518 } else {
2519 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2485 Label skip; 2520 Label skip;
2486 __ lw(a1, StackOperand(var)); 2521 MemOperand location = VarOperand(var, a1);
2487 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 2522 __ lw(a2, location);
2488 __ Branch(&skip, ne, a1, Operand(t0)); 2523 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2489 __ sw(result_register(), StackOperand(var)); 2524 __ Branch(&skip, ne, a2, Operand(at));
2525 EmitStoreToStackLocalOrContextSlot(var, location);
2490 __ bind(&skip); 2526 __ bind(&skip);
2491 } else {
2492 ASSERT(var->IsContextSlot() || var->IsLookupSlot());
2493 // Like var declarations, const declarations are hoisted to function
2494 // scope. However, unlike var initializers, const initializers are
2495 // able to drill a hole to that function context, even from inside a
2496 // 'with' context. We thus bypass the normal static scope lookup for
2497 // var->IsContextSlot().
2498 __ push(v0);
2499 __ li(a0, Operand(var->name()));
2500 __ Push(cp, a0); // Context and name.
2501 __ CallRuntime(Runtime::kInitializeConstContextSlot, 3);
2502 } 2527 }
2503 2528
2504 } else if (var->mode() == LET && op != Token::INIT_LET) { 2529 } else if (var->mode() == LET && op != Token::INIT_LET) {
2505 // Non-initializing assignment to let variable needs a write barrier. 2530 // Non-initializing assignment to let variable needs a write barrier.
2506 if (var->IsLookupSlot()) { 2531 if (var->IsLookupSlot()) {
2507 __ push(v0); // Value. 2532 EmitCallStoreContextSlot(var->name(), language_mode());
2508 __ li(a1, Operand(var->name()));
2509 __ li(a0, Operand(Smi::FromInt(language_mode())));
2510 __ Push(cp, a1, a0); // Context, name, strict mode.
2511 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2512 } else { 2533 } else {
2513 ASSERT(var->IsStackAllocated() || var->IsContextSlot()); 2534 ASSERT(var->IsStackAllocated() || var->IsContextSlot());
2514 Label assign; 2535 Label assign;
2515 MemOperand location = VarOperand(var, a1); 2536 MemOperand location = VarOperand(var, a1);
2516 __ lw(a3, location); 2537 __ lw(a3, location);
2517 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 2538 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
2518 __ Branch(&assign, ne, a3, Operand(t0)); 2539 __ Branch(&assign, ne, a3, Operand(t0));
2519 __ li(a3, Operand(var->name())); 2540 __ li(a3, Operand(var->name()));
2520 __ push(a3); 2541 __ push(a3);
2521 __ CallRuntime(Runtime::kThrowReferenceError, 1); 2542 __ CallRuntime(Runtime::kThrowReferenceError, 1);
2522 // Perform the assignment. 2543 // Perform the assignment.
2523 __ bind(&assign); 2544 __ bind(&assign);
2524 __ sw(result_register(), location); 2545 EmitStoreToStackLocalOrContextSlot(var, location);
2525 if (var->IsContextSlot()) {
2526 // RecordWrite may destroy all its register arguments.
2527 __ mov(a3, result_register());
2528 int offset = Context::SlotOffset(var->index());
2529 __ RecordWriteContextSlot(
2530 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs);
2531 }
2532 } 2546 }
2533 2547
2534 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) { 2548 } else if (!var->is_const_mode() || op == Token::INIT_CONST_HARMONY) {
2535 // Assignment to var or initializing assignment to let/const 2549 // Assignment to var or initializing assignment to let/const
2536 // in harmony mode. 2550 // in harmony mode.
2537 if (var->IsStackAllocated() || var->IsContextSlot()) { 2551 if (var->IsLookupSlot()) {
2552 EmitCallStoreContextSlot(var->name(), language_mode());
2553 } else {
2554 ASSERT((var->IsStackAllocated() || var->IsContextSlot()));
2538 MemOperand location = VarOperand(var, a1); 2555 MemOperand location = VarOperand(var, a1);
2539 if (generate_debug_code_ && op == Token::INIT_LET) { 2556 if (generate_debug_code_ && op == Token::INIT_LET) {
2540 // Check for an uninitialized let binding. 2557 // Check for an uninitialized let binding.
2541 __ lw(a2, location); 2558 __ lw(a2, location);
2542 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); 2559 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex);
2543 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); 2560 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0));
2544 } 2561 }
2545 // Perform the assignment. 2562 EmitStoreToStackLocalOrContextSlot(var, location);
2546 __ sw(v0, location);
2547 if (var->IsContextSlot()) {
2548 __ mov(a3, v0);
2549 int offset = Context::SlotOffset(var->index());
2550 __ RecordWriteContextSlot(
2551 a1, offset, a3, a2, kRAHasBeenSaved, kDontSaveFPRegs);
2552 }
2553 } else {
2554 ASSERT(var->IsLookupSlot());
2555 __ push(v0); // Value.
2556 __ li(a1, Operand(var->name()));
2557 __ li(a0, Operand(Smi::FromInt(language_mode())));
2558 __ Push(cp, a1, a0); // Context, name, strict mode.
2559 __ CallRuntime(Runtime::kStoreContextSlot, 4);
2560 } 2563 }
2561 } 2564 }
2562 // Non-initializing assignments to consts are ignored. 2565 // Non-initializing assignments to consts are ignored.
2563 } 2566 }
2564 2567
2565 2568
2566 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) { 2569 void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
2567 // Assignment to a property, using a named store IC. 2570 // Assignment to a property, using a named store IC.
2568 Property* prop = expr->target()->AsProperty(); 2571 Property* prop = expr->target()->AsProperty();
2569 ASSERT(prop != NULL); 2572 ASSERT(prop != NULL);
2570 ASSERT(prop->key()->AsLiteral() != NULL); 2573 ASSERT(prop->key()->AsLiteral() != NULL);
2571 2574
2572 // Record source code position before IC call. 2575 // Record source code position before IC call.
2573 SetSourcePosition(expr->position()); 2576 SetSourcePosition(expr->position());
2574 __ mov(a0, result_register()); // Load the value. 2577 __ mov(a0, result_register()); // Load the value.
2575 __ li(a2, Operand(prop->key()->AsLiteral()->value())); 2578 __ li(a2, Operand(prop->key()->AsLiteral()->value()));
2576 __ pop(a1); 2579 __ pop(a1);
2577 2580
2578 CallStoreIC(NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); 2581 CallStoreIC(expr->AssignmentFeedbackId());
2579 2582
2580 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2583 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2581 context()->Plug(v0); 2584 context()->Plug(v0);
2582 } 2585 }
2583 2586
2584 2587
2585 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) { 2588 void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
2586 // Assignment to a property, using a keyed store IC. 2589 // Assignment to a property, using a keyed store IC.
2587 2590
2588 // Record source code position before IC call. 2591 // Record source code position before IC call.
2589 SetSourcePosition(expr->position()); 2592 SetSourcePosition(expr->position());
2590 // Call keyed store IC. 2593 // Call keyed store IC.
2591 // The arguments are: 2594 // The arguments are:
2592 // - a0 is the value, 2595 // - a0 is the value,
2593 // - a1 is the key, 2596 // - a1 is the key,
2594 // - a2 is the receiver. 2597 // - a2 is the receiver.
2595 __ mov(a0, result_register()); 2598 __ mov(a0, result_register());
2596 __ Pop(a2, a1); // a1 = key. 2599 __ Pop(a2, a1); // a1 = key.
2597 2600
2598 Handle<Code> ic = is_classic_mode() 2601 Handle<Code> ic = is_classic_mode()
2599 ? isolate()->builtins()->KeyedStoreIC_Initialize() 2602 ? isolate()->builtins()->KeyedStoreIC_Initialize()
2600 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 2603 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
2601 CallIC(ic, NOT_CONTEXTUAL, expr->AssignmentFeedbackId()); 2604 CallIC(ic, expr->AssignmentFeedbackId());
2602 2605
2603 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 2606 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
2604 context()->Plug(v0); 2607 context()->Plug(v0);
2605 } 2608 }
2606 2609
2607 2610
2608 void FullCodeGenerator::VisitProperty(Property* expr) { 2611 void FullCodeGenerator::VisitProperty(Property* expr) {
2609 Comment cmnt(masm_, "[ Property"); 2612 Comment cmnt(masm_, "[ Property");
2610 Expression* key = expr->key(); 2613 Expression* key = expr->key();
2611 2614
2612 if (key->IsPropertyName()) { 2615 if (key->IsPropertyName()) {
2613 VisitForAccumulatorValue(expr->obj()); 2616 VisitForAccumulatorValue(expr->obj());
2614 EmitNamedPropertyLoad(expr); 2617 EmitNamedPropertyLoad(expr);
2615 PrepareForBailoutForId(expr->LoadId(), TOS_REG); 2618 PrepareForBailoutForId(expr->LoadId(), TOS_REG);
2616 context()->Plug(v0); 2619 context()->Plug(v0);
2617 } else { 2620 } else {
2618 VisitForStackValue(expr->obj()); 2621 VisitForStackValue(expr->obj());
2619 VisitForAccumulatorValue(expr->key()); 2622 VisitForAccumulatorValue(expr->key());
2620 __ pop(a1); 2623 __ pop(a1);
2621 EmitKeyedPropertyLoad(expr); 2624 EmitKeyedPropertyLoad(expr);
2622 context()->Plug(v0); 2625 context()->Plug(v0);
2623 } 2626 }
2624 } 2627 }
2625 2628
2626 2629
2627 void FullCodeGenerator::CallIC(Handle<Code> code, 2630 void FullCodeGenerator::CallIC(Handle<Code> code,
2628 ContextualMode mode,
2629 TypeFeedbackId id) { 2631 TypeFeedbackId id) {
2630 ic_total_count_++; 2632 ic_total_count_++;
2631 ASSERT(mode != CONTEXTUAL || id.IsNone());
2632 __ Call(code, RelocInfo::CODE_TARGET, id); 2633 __ Call(code, RelocInfo::CODE_TARGET, id);
2633 } 2634 }
2634 2635
2635 2636
2636 void FullCodeGenerator::EmitCallWithIC(Call* expr, 2637 // Code common for calls using the IC.
2637 Handle<Object> name, 2638 void FullCodeGenerator::EmitCallWithIC(Call* expr) {
2638 ContextualMode mode) { 2639 Expression* callee = expr->expression();
2639 // Code common for calls using the IC.
2640 ZoneList<Expression*>* args = expr->arguments(); 2640 ZoneList<Expression*>* args = expr->arguments();
2641 int arg_count = args->length(); 2641 int arg_count = args->length();
2642 { PreservePositionScope scope(masm()->positions_recorder()); 2642
2643 for (int i = 0; i < arg_count; i++) { 2643 CallFunctionFlags flags;
2644 VisitForStackValue(args->at(i)); 2644 // Get the target function.
2645 if (callee->IsVariableProxy()) {
2646 { StackValueContext context(this);
2647 EmitVariableLoad(callee->AsVariableProxy());
2648 PrepareForBailout(callee, NO_REGISTERS);
2645 } 2649 }
2646 __ li(a2, Operand(name)); 2650 // Push undefined as receiver. This is patched in the method prologue if it
2651 // is a classic mode method.
2652 __ Push(isolate()->factory()->undefined_value());
2653 flags = NO_CALL_FUNCTION_FLAGS;
2654 } else {
2655 // Load the function from the receiver.
2656 ASSERT(callee->IsProperty());
2657 __ lw(v0, MemOperand(sp, 0));
2658 EmitNamedPropertyLoad(callee->AsProperty());
2659 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2660 // Push the target function under the receiver.
2661 __ lw(at, MemOperand(sp, 0));
2662 __ push(at);
2663 __ sw(v0, MemOperand(sp, kPointerSize));
2664 flags = CALL_AS_METHOD;
2647 } 2665 }
2648 // Record source position for debugger.
2649 SetSourcePosition(expr->position());
2650 // Call the IC initialization code.
2651 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count);
2652 TypeFeedbackId ast_id = mode == CONTEXTUAL
2653 ? TypeFeedbackId::None()
2654 : expr->CallFeedbackId();
2655 CallIC(ic, mode, ast_id);
2656 RecordJSReturnSite(expr);
2657 // Restore context register.
2658 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2659 context()->Plug(v0);
2660 }
2661 2666
2662 2667 // Load the arguments.
2663 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2664 Expression* key) {
2665 // Load the key.
2666 VisitForAccumulatorValue(key);
2667
2668 // Swap the name of the function and the receiver on the stack to follow
2669 // the calling convention for call ICs.
2670 __ pop(a1);
2671 __ push(v0);
2672 __ push(a1);
2673
2674 // Code common for calls using the IC.
2675 ZoneList<Expression*>* args = expr->arguments();
2676 int arg_count = args->length();
2677 { PreservePositionScope scope(masm()->positions_recorder()); 2668 { PreservePositionScope scope(masm()->positions_recorder());
2678 for (int i = 0; i < arg_count; i++) { 2669 for (int i = 0; i < arg_count; i++) {
2679 VisitForStackValue(args->at(i)); 2670 VisitForStackValue(args->at(i));
2680 } 2671 }
2681 } 2672 }
2682 // Record source position for debugger. 2673 // Record source position for debugger.
2683 SetSourcePosition(expr->position()); 2674 SetSourcePosition(expr->position());
2684 // Call the IC initialization code. 2675 CallFunctionStub stub(arg_count, flags);
2685 Handle<Code> ic = 2676 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2686 isolate()->stub_cache()->ComputeKeyedCallInitialize(arg_count); 2677 __ CallStub(&stub);
2687 __ lw(a2, MemOperand(sp, (arg_count + 1) * kPointerSize)); // Key. 2678
2688 CallIC(ic, NOT_CONTEXTUAL, expr->CallFeedbackId()); 2679 RecordJSReturnSite(expr);
2680
2681 // Restore context register.
2682 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2683
2684 context()->DropAndPlug(1, v0);
2685 }
2686
2687
2688 // Code common for calls using the IC.
2689 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr,
2690 Expression* key) {
2691 // Load the key.
2692 VisitForAccumulatorValue(key);
2693
2694 Expression* callee = expr->expression();
2695 ZoneList<Expression*>* args = expr->arguments();
2696 int arg_count = args->length();
2697
2698 // Load the function from the receiver.
2699 ASSERT(callee->IsProperty());
2700 __ lw(a1, MemOperand(sp, 0));
2701 EmitKeyedPropertyLoad(callee->AsProperty());
2702 PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
2703
2704 // Push the target function under the receiver.
2705 __ lw(at, MemOperand(sp, 0));
2706 __ push(at);
2707 __ sw(v0, MemOperand(sp, kPointerSize));
2708
2709 { PreservePositionScope scope(masm()->positions_recorder());
2710 for (int i = 0; i < arg_count; i++) {
2711 VisitForStackValue(args->at(i));
2712 }
2713 }
2714
2715 // Record source position for debugger.
2716 SetSourcePosition(expr->position());
2717 CallFunctionStub stub(arg_count, CALL_AS_METHOD);
2718 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2719 __ CallStub(&stub);
2720
2689 RecordJSReturnSite(expr); 2721 RecordJSReturnSite(expr);
2690 // Restore context register. 2722 // Restore context register.
2691 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2723 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2692 context()->DropAndPlug(1, v0); // Drop the key still on the stack. 2724
2725 context()->DropAndPlug(1, v0);
2693 } 2726 }
2694 2727
2695 2728
2696 void FullCodeGenerator::EmitCallWithStub(Call* expr) { 2729 void FullCodeGenerator::EmitCallWithStub(Call* expr) {
2697 // Code common for calls using the call stub. 2730 // Code common for calls using the call stub.
2698 ZoneList<Expression*>* args = expr->arguments(); 2731 ZoneList<Expression*>* args = expr->arguments();
2699 int arg_count = args->length(); 2732 int arg_count = args->length();
2700 { PreservePositionScope scope(masm()->positions_recorder()); 2733 { PreservePositionScope scope(masm()->positions_recorder());
2701 for (int i = 0; i < arg_count; i++) { 2734 for (int i = 0; i < arg_count; i++) {
2702 VisitForStackValue(args->at(i)); 2735 VisitForStackValue(args->at(i));
2703 } 2736 }
2704 } 2737 }
2705 // Record source position for debugger. 2738 // Record source position for debugger.
2706 SetSourcePosition(expr->position()); 2739 SetSourcePosition(expr->position());
2707 2740
2708 Handle<Object> uninitialized = 2741 Handle<Object> uninitialized =
2709 TypeFeedbackCells::UninitializedSentinel(isolate()); 2742 TypeFeedbackInfo::UninitializedSentinel(isolate());
2710 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); 2743 StoreFeedbackVectorSlot(expr->CallFeedbackSlot(), uninitialized);
2711 RecordTypeFeedbackCell(expr->CallFeedbackId(), cell); 2744 __ li(a2, FeedbackVector());
2712 __ li(a2, Operand(cell)); 2745 __ li(a3, Operand(Smi::FromInt(expr->CallFeedbackSlot())));
2713 2746
2714 // Record call targets in unoptimized code. 2747 // Record call targets in unoptimized code.
2715 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET); 2748 CallFunctionStub stub(arg_count, RECORD_CALL_TARGET);
2716 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2749 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2717 __ CallStub(&stub, expr->CallFeedbackId()); 2750 __ CallStub(&stub);
2718 RecordJSReturnSite(expr); 2751 RecordJSReturnSite(expr);
2719 // Restore context register. 2752 // Restore context register.
2720 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2753 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2721 context()->DropAndPlug(1, v0); 2754 context()->DropAndPlug(1, v0);
2722 } 2755 }
2723 2756
2724 2757
2725 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) { 2758 void FullCodeGenerator::EmitResolvePossiblyDirectEval(int arg_count) {
2726 // t2: copy of the first argument or undefined if it doesn't exist. 2759 // t2: copy of the first argument or undefined if it doesn't exist.
2727 if (arg_count > 0) { 2760 if (arg_count > 0) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
2789 // Record source position for debugger. 2822 // Record source position for debugger.
2790 SetSourcePosition(expr->position()); 2823 SetSourcePosition(expr->position());
2791 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS); 2824 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
2792 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize)); 2825 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
2793 __ CallStub(&stub); 2826 __ CallStub(&stub);
2794 RecordJSReturnSite(expr); 2827 RecordJSReturnSite(expr);
2795 // Restore context register. 2828 // Restore context register.
2796 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 2829 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
2797 context()->DropAndPlug(1, v0); 2830 context()->DropAndPlug(1, v0);
2798 } else if (call_type == Call::GLOBAL_CALL) { 2831 } else if (call_type == Call::GLOBAL_CALL) {
2799 // Push global object as receiver for the call IC. 2832 EmitCallWithIC(expr);
2800 __ lw(a0, GlobalObjectOperand());
2801 __ push(a0);
2802 VariableProxy* proxy = callee->AsVariableProxy();
2803 EmitCallWithIC(expr, proxy->name(), CONTEXTUAL);
2804 } else if (call_type == Call::LOOKUP_SLOT_CALL) { 2833 } else if (call_type == Call::LOOKUP_SLOT_CALL) {
2805 // Call to a lookup slot (dynamically introduced variable). 2834 // Call to a lookup slot (dynamically introduced variable).
2806 VariableProxy* proxy = callee->AsVariableProxy(); 2835 VariableProxy* proxy = callee->AsVariableProxy();
2807 Label slow, done; 2836 Label slow, done;
2808 2837
2809 { PreservePositionScope scope(masm()->positions_recorder()); 2838 { PreservePositionScope scope(masm()->positions_recorder());
2810 // Generate code for loading from variables potentially shadowed 2839 // Generate code for loading from variables potentially shadowed
2811 // by eval-introduced variables. 2840 // by eval-introduced variables.
2812 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done); 2841 EmitDynamicLookupFastCase(proxy->var(), NOT_INSIDE_TYPEOF, &slow, &done);
2813 } 2842 }
(...skipping 25 matching lines...) Expand all
2839 2868
2840 // The receiver is either the global receiver or an object found 2869 // The receiver is either the global receiver or an object found
2841 // by LoadContextSlot. 2870 // by LoadContextSlot.
2842 EmitCallWithStub(expr); 2871 EmitCallWithStub(expr);
2843 } else if (call_type == Call::PROPERTY_CALL) { 2872 } else if (call_type == Call::PROPERTY_CALL) {
2844 Property* property = callee->AsProperty(); 2873 Property* property = callee->AsProperty();
2845 { PreservePositionScope scope(masm()->positions_recorder()); 2874 { PreservePositionScope scope(masm()->positions_recorder());
2846 VisitForStackValue(property->obj()); 2875 VisitForStackValue(property->obj());
2847 } 2876 }
2848 if (property->key()->IsPropertyName()) { 2877 if (property->key()->IsPropertyName()) {
2849 EmitCallWithIC(expr, 2878 EmitCallWithIC(expr);
2850 property->key()->AsLiteral()->value(),
2851 NOT_CONTEXTUAL);
2852 } else { 2879 } else {
2853 EmitKeyedCallWithIC(expr, property->key()); 2880 EmitKeyedCallWithIC(expr, property->key());
2854 } 2881 }
2855 } else { 2882 } else {
2856 ASSERT(call_type == Call::OTHER_CALL); 2883 ASSERT(call_type == Call::OTHER_CALL);
2857 // Call to an arbitrary expression not handled specially above. 2884 // Call to an arbitrary expression not handled specially above.
2858 { PreservePositionScope scope(masm()->positions_recorder()); 2885 { PreservePositionScope scope(masm()->positions_recorder());
2859 VisitForStackValue(callee); 2886 VisitForStackValue(callee);
2860 } 2887 }
2861 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex); 2888 __ LoadRoot(a1, Heap::kUndefinedValueRootIndex);
(...skipping 30 matching lines...) Expand all
2892 // Call the construct call builtin that handles allocation and 2919 // Call the construct call builtin that handles allocation and
2893 // constructor invocation. 2920 // constructor invocation.
2894 SetSourcePosition(expr->position()); 2921 SetSourcePosition(expr->position());
2895 2922
2896 // Load function and argument count into a1 and a0. 2923 // Load function and argument count into a1 and a0.
2897 __ li(a0, Operand(arg_count)); 2924 __ li(a0, Operand(arg_count));
2898 __ lw(a1, MemOperand(sp, arg_count * kPointerSize)); 2925 __ lw(a1, MemOperand(sp, arg_count * kPointerSize));
2899 2926
2900 // Record call targets in unoptimized code. 2927 // Record call targets in unoptimized code.
2901 Handle<Object> uninitialized = 2928 Handle<Object> uninitialized =
2902 TypeFeedbackCells::UninitializedSentinel(isolate()); 2929 TypeFeedbackInfo::UninitializedSentinel(isolate());
2903 Handle<Cell> cell = isolate()->factory()->NewCell(uninitialized); 2930 StoreFeedbackVectorSlot(expr->CallNewFeedbackSlot(), uninitialized);
2904 RecordTypeFeedbackCell(expr->CallNewFeedbackId(), cell); 2931 __ li(a2, FeedbackVector());
2905 __ li(a2, Operand(cell)); 2932 __ li(a3, Operand(Smi::FromInt(expr->CallNewFeedbackSlot())));
2906 2933
2907 CallConstructStub stub(RECORD_CALL_TARGET); 2934 CallConstructStub stub(RECORD_CALL_TARGET);
2908 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL); 2935 __ Call(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL);
2909 PrepareForBailoutForId(expr->ReturnId(), TOS_REG); 2936 PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
2910 context()->Plug(v0); 2937 context()->Plug(v0);
2911 } 2938 }
2912 2939
2913 2940
2914 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) { 2941 void FullCodeGenerator::EmitIsSmi(CallRuntime* expr) {
2915 ZoneList<Expression*>* args = expr->arguments(); 2942 ZoneList<Expression*>* args = expr->arguments();
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
3016 Label materialize_true, materialize_false; 3043 Label materialize_true, materialize_false;
3017 Label* if_true = NULL; 3044 Label* if_true = NULL;
3018 Label* if_false = NULL; 3045 Label* if_false = NULL;
3019 Label* fall_through = NULL; 3046 Label* fall_through = NULL;
3020 context()->PrepareTest(&materialize_true, &materialize_false, 3047 context()->PrepareTest(&materialize_true, &materialize_false,
3021 &if_true, &if_false, &fall_through); 3048 &if_true, &if_false, &fall_through);
3022 3049
3023 __ JumpIfSmi(v0, if_false); 3050 __ JumpIfSmi(v0, if_false);
3024 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); 3051 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
3025 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset)); 3052 __ lbu(a1, FieldMemOperand(a1, Map::kBitFieldOffset));
3053 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3026 __ And(at, a1, Operand(1 << Map::kIsUndetectable)); 3054 __ And(at, a1, Operand(1 << Map::kIsUndetectable));
3027 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
3028 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through); 3055 Split(ne, at, Operand(zero_reg), if_true, if_false, fall_through);
3029 3056
3030 context()->Plug(if_true, if_false); 3057 context()->Plug(if_true, if_false);
3031 } 3058 }
3032 3059
3033 3060
3034 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( 3061 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf(
3035 CallRuntime* expr) { 3062 CallRuntime* expr) {
3036 ZoneList<Expression*>* args = expr->arguments(); 3063 ZoneList<Expression*>* args = expr->arguments();
3037 ASSERT(args->length() == 1); 3064 ASSERT(args->length() == 1);
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after
3491 Register index = a1; 3518 Register index = a1;
3492 Register value = a2; 3519 Register value = a2;
3493 3520
3494 VisitForStackValue(args->at(1)); // index 3521 VisitForStackValue(args->at(1)); // index
3495 VisitForStackValue(args->at(2)); // value 3522 VisitForStackValue(args->at(2)); // value
3496 VisitForAccumulatorValue(args->at(0)); // string 3523 VisitForAccumulatorValue(args->at(0)); // string
3497 __ Pop(index, value); 3524 __ Pop(index, value);
3498 3525
3499 if (FLAG_debug_code) { 3526 if (FLAG_debug_code) {
3500 __ SmiTst(value, at); 3527 __ SmiTst(value, at);
3501 __ ThrowIf(ne, kNonSmiValue, at, Operand(zero_reg)); 3528 __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
3502 __ SmiTst(index, at); 3529 __ SmiTst(index, at);
3503 __ ThrowIf(ne, kNonSmiIndex, at, Operand(zero_reg)); 3530 __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
3504 __ SmiUntag(index, index); 3531 __ SmiUntag(index, index);
3505 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 3532 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
3506 Register scratch = t5; 3533 Register scratch = t5;
3507 __ EmitSeqStringSetCharCheck( 3534 __ EmitSeqStringSetCharCheck(
3508 string, index, value, scratch, one_byte_seq_type); 3535 string, index, value, scratch, one_byte_seq_type);
3509 __ SmiTag(index, index); 3536 __ SmiTag(index, index);
3510 } 3537 }
3511 3538
3512 __ SmiUntag(value, value); 3539 __ SmiUntag(value, value);
3513 __ Addu(at, 3540 __ Addu(at,
(...skipping 14 matching lines...) Expand all
3528 Register index = a1; 3555 Register index = a1;
3529 Register value = a2; 3556 Register value = a2;
3530 3557
3531 VisitForStackValue(args->at(1)); // index 3558 VisitForStackValue(args->at(1)); // index
3532 VisitForStackValue(args->at(2)); // value 3559 VisitForStackValue(args->at(2)); // value
3533 VisitForAccumulatorValue(args->at(0)); // string 3560 VisitForAccumulatorValue(args->at(0)); // string
3534 __ Pop(index, value); 3561 __ Pop(index, value);
3535 3562
3536 if (FLAG_debug_code) { 3563 if (FLAG_debug_code) {
3537 __ SmiTst(value, at); 3564 __ SmiTst(value, at);
3538 __ ThrowIf(ne, kNonSmiValue, at, Operand(zero_reg)); 3565 __ Check(eq, kNonSmiValue, at, Operand(zero_reg));
3539 __ SmiTst(index, at); 3566 __ SmiTst(index, at);
3540 __ ThrowIf(ne, kNonSmiIndex, at, Operand(zero_reg)); 3567 __ Check(eq, kNonSmiIndex, at, Operand(zero_reg));
3541 __ SmiUntag(index, index); 3568 __ SmiUntag(index, index);
3542 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 3569 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
3543 Register scratch = t5; 3570 Register scratch = t5;
3544 __ EmitSeqStringSetCharCheck( 3571 __ EmitSeqStringSetCharCheck(
3545 string, index, value, scratch, two_byte_seq_type); 3572 string, index, value, scratch, two_byte_seq_type);
3546 __ SmiTag(index, index); 3573 __ SmiTag(index, index);
3547 } 3574 }
3548 3575
3549 __ SmiUntag(value, value); 3576 __ SmiUntag(value, value);
3550 __ Addu(at, 3577 __ Addu(at,
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
3723 generator.GenerateSlow(masm_, call_helper); 3750 generator.GenerateSlow(masm_, call_helper);
3724 3751
3725 __ bind(&done); 3752 __ bind(&done);
3726 context()->Plug(result); 3753 context()->Plug(result);
3727 } 3754 }
3728 3755
3729 3756
3730 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) { 3757 void FullCodeGenerator::EmitStringAdd(CallRuntime* expr) {
3731 ZoneList<Expression*>* args = expr->arguments(); 3758 ZoneList<Expression*>* args = expr->arguments();
3732 ASSERT_EQ(2, args->length()); 3759 ASSERT_EQ(2, args->length());
3733 if (FLAG_new_string_add) { 3760 VisitForStackValue(args->at(0));
3734 VisitForStackValue(args->at(0)); 3761 VisitForAccumulatorValue(args->at(1));
3735 VisitForAccumulatorValue(args->at(1));
3736 3762
3737 __ pop(a1); 3763 __ pop(a1);
3738 __ mov(a0, result_register()); // NewStringAddStub requires args in a0, a1. 3764 __ mov(a0, result_register()); // StringAddStub requires args in a0, a1.
3739 NewStringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED); 3765 StringAddStub stub(STRING_ADD_CHECK_BOTH, NOT_TENURED);
3740 __ CallStub(&stub); 3766 __ CallStub(&stub);
3741 } else {
3742 VisitForStackValue(args->at(0));
3743 VisitForStackValue(args->at(1));
3744
3745 StringAddStub stub(STRING_ADD_CHECK_BOTH);
3746 __ CallStub(&stub);
3747 }
3748 context()->Plug(v0); 3767 context()->Plug(v0);
3749 } 3768 }
3750 3769
3751 3770
3752 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) { 3771 void FullCodeGenerator::EmitStringCompare(CallRuntime* expr) {
3753 ZoneList<Expression*>* args = expr->arguments(); 3772 ZoneList<Expression*>* args = expr->arguments();
3754 ASSERT_EQ(2, args->length()); 3773 ASSERT_EQ(2, args->length());
3755 3774
3756 VisitForStackValue(args->at(0)); 3775 VisitForStackValue(args->at(0));
3757 VisitForStackValue(args->at(1)); 3776 VisitForStackValue(args->at(1));
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
3813 context()->Plug(v0); 3832 context()->Plug(v0);
3814 } 3833 }
3815 3834
3816 3835
3817 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) { 3836 void FullCodeGenerator::EmitRegExpConstructResult(CallRuntime* expr) {
3818 RegExpConstructResultStub stub; 3837 RegExpConstructResultStub stub;
3819 ZoneList<Expression*>* args = expr->arguments(); 3838 ZoneList<Expression*>* args = expr->arguments();
3820 ASSERT(args->length() == 3); 3839 ASSERT(args->length() == 3);
3821 VisitForStackValue(args->at(0)); 3840 VisitForStackValue(args->at(0));
3822 VisitForStackValue(args->at(1)); 3841 VisitForStackValue(args->at(1));
3823 VisitForStackValue(args->at(2)); 3842 VisitForAccumulatorValue(args->at(2));
3843 __ mov(a0, result_register());
3844 __ pop(a1);
3845 __ pop(a2);
3824 __ CallStub(&stub); 3846 __ CallStub(&stub);
3825 context()->Plug(v0); 3847 context()->Plug(v0);
3826 } 3848 }
3827 3849
3828 3850
3829 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) { 3851 void FullCodeGenerator::EmitGetFromCache(CallRuntime* expr) {
3830 ZoneList<Expression*>* args = expr->arguments(); 3852 ZoneList<Expression*>* args = expr->arguments();
3831 ASSERT_EQ(2, args->length()); 3853 ASSERT_EQ(2, args->length());
3832 3854
3833 ASSERT_NE(NULL, args->at(0)->AsLiteral()); 3855 ASSERT_NE(NULL, args->at(0)->AsLiteral());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
3873 __ bind(&not_found); 3895 __ bind(&not_found);
3874 // Call runtime to perform the lookup. 3896 // Call runtime to perform the lookup.
3875 __ Push(cache, key); 3897 __ Push(cache, key);
3876 __ CallRuntime(Runtime::kGetFromCache, 2); 3898 __ CallRuntime(Runtime::kGetFromCache, 2);
3877 3899
3878 __ bind(&done); 3900 __ bind(&done);
3879 context()->Plug(v0); 3901 context()->Plug(v0);
3880 } 3902 }
3881 3903
3882 3904
3883 void FullCodeGenerator::EmitIsRegExpEquivalent(CallRuntime* expr) {
3884 ZoneList<Expression*>* args = expr->arguments();
3885 ASSERT_EQ(2, args->length());
3886
3887 Register right = v0;
3888 Register left = a1;
3889 Register tmp = a2;
3890 Register tmp2 = a3;
3891
3892 VisitForStackValue(args->at(0));
3893 VisitForAccumulatorValue(args->at(1)); // Result (right) in v0.
3894 __ pop(left);
3895
3896 Label done, fail, ok;
3897 __ Branch(&ok, eq, left, Operand(right));
3898 // Fail if either is a non-HeapObject.
3899 __ And(tmp, left, Operand(right));
3900 __ JumpIfSmi(tmp, &fail);
3901 __ lw(tmp, FieldMemOperand(left, HeapObject::kMapOffset));
3902 __ lbu(tmp2, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
3903 __ Branch(&fail, ne, tmp2, Operand(JS_REGEXP_TYPE));
3904 __ lw(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
3905 __ Branch(&fail, ne, tmp, Operand(tmp2));
3906 __ lw(tmp, FieldMemOperand(left, JSRegExp::kDataOffset));
3907 __ lw(tmp2, FieldMemOperand(right, JSRegExp::kDataOffset));
3908 __ Branch(&ok, eq, tmp, Operand(tmp2));
3909 __ bind(&fail);
3910 __ LoadRoot(v0, Heap::kFalseValueRootIndex);
3911 __ jmp(&done);
3912 __ bind(&ok);
3913 __ LoadRoot(v0, Heap::kTrueValueRootIndex);
3914 __ bind(&done);
3915
3916 context()->Plug(v0);
3917 }
3918
3919
3920 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) { 3905 void FullCodeGenerator::EmitHasCachedArrayIndex(CallRuntime* expr) {
3921 ZoneList<Expression*>* args = expr->arguments(); 3906 ZoneList<Expression*>* args = expr->arguments();
3922 VisitForAccumulatorValue(args->at(0)); 3907 VisitForAccumulatorValue(args->at(0));
3923 3908
3924 Label materialize_true, materialize_false; 3909 Label materialize_true, materialize_false;
3925 Label* if_true = NULL; 3910 Label* if_true = NULL;
3926 Label* if_false = NULL; 3911 Label* if_false = NULL;
3927 Label* fall_through = NULL; 3912 Label* fall_through = NULL;
3928 context()->PrepareTest(&materialize_true, &materialize_false, 3913 context()->PrepareTest(&materialize_true, &materialize_false,
3929 &if_true, &if_false, &fall_through); 3914 &if_true, &if_false, &fall_through);
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
4193 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { 4178 void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
4194 Handle<String> name = expr->name(); 4179 Handle<String> name = expr->name();
4195 if (name->length() > 0 && name->Get(0) == '_') { 4180 if (name->length() > 0 && name->Get(0) == '_') {
4196 Comment cmnt(masm_, "[ InlineRuntimeCall"); 4181 Comment cmnt(masm_, "[ InlineRuntimeCall");
4197 EmitInlineRuntimeCall(expr); 4182 EmitInlineRuntimeCall(expr);
4198 return; 4183 return;
4199 } 4184 }
4200 4185
4201 Comment cmnt(masm_, "[ CallRuntime"); 4186 Comment cmnt(masm_, "[ CallRuntime");
4202 ZoneList<Expression*>* args = expr->arguments(); 4187 ZoneList<Expression*>* args = expr->arguments();
4188 int arg_count = args->length();
4203 4189
4204 if (expr->is_jsruntime()) { 4190 if (expr->is_jsruntime()) {
4205 // Prepare for calling JS runtime function. 4191 // Push the builtins object as the receiver.
4206 __ lw(a0, GlobalObjectOperand()); 4192 __ lw(a0, GlobalObjectOperand());
4207 __ lw(a0, FieldMemOperand(a0, GlobalObject::kBuiltinsOffset)); 4193 __ lw(a0, FieldMemOperand(a0, GlobalObject::kBuiltinsOffset));
4208 __ push(a0); 4194 __ push(a0);
4209 } 4195 // Load the function from the receiver.
4196 __ li(a2, Operand(expr->name()));
4197 CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());
4210 4198
4211 // Push the arguments ("left-to-right"). 4199 // Push the target function under the receiver.
4212 int arg_count = args->length(); 4200 __ lw(at, MemOperand(sp, 0));
4213 for (int i = 0; i < arg_count; i++) { 4201 __ push(at);
4214 VisitForStackValue(args->at(i)); 4202 __ sw(v0, MemOperand(sp, kPointerSize));
4215 }
4216 4203
4217 if (expr->is_jsruntime()) { 4204 // Push the arguments ("left-to-right").
4218 // Call the JS runtime function. 4205 int arg_count = args->length();
4219 __ li(a2, Operand(expr->name())); 4206 for (int i = 0; i < arg_count; i++) {
4220 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arg_count); 4207 VisitForStackValue(args->at(i));
4221 CallIC(ic, NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId()); 4208 }
4209
4210 // Record source position of the IC call.
4211 SetSourcePosition(expr->position());
4212 CallFunctionStub stub(arg_count, NO_CALL_FUNCTION_FLAGS);
4213 __ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
4214 __ CallStub(&stub);
4215
4222 // Restore context register. 4216 // Restore context register.
4223 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 4217 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
4218
4219 context()->DropAndPlug(1, v0);
4224 } else { 4220 } else {
4221 // Push the arguments ("left-to-right").
4222 for (int i = 0; i < arg_count; i++) {
4223 VisitForStackValue(args->at(i));
4224 }
4225
4225 // Call the C runtime function. 4226 // Call the C runtime function.
4226 __ CallRuntime(expr->function(), arg_count); 4227 __ CallRuntime(expr->function(), arg_count);
4228 context()->Plug(v0);
4227 } 4229 }
4228 context()->Plug(v0);
4229 } 4230 }
4230 4231
4231 4232
4232 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { 4233 void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
4233 switch (expr->op()) { 4234 switch (expr->op()) {
4234 case Token::DELETE: { 4235 case Token::DELETE: {
4235 Comment cmnt(masm_, "[ UnaryOperation (DELETE)"); 4236 Comment cmnt(masm_, "[ UnaryOperation (DELETE)");
4236 Property* property = expr->expression()->AsProperty(); 4237 Property* property = expr->expression()->AsProperty();
4237 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 4238 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4238 4239
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
4461 } 4462 }
4462 4463
4463 __ bind(&stub_call); 4464 __ bind(&stub_call);
4464 __ mov(a1, v0); 4465 __ mov(a1, v0);
4465 __ li(a0, Operand(Smi::FromInt(count_value))); 4466 __ li(a0, Operand(Smi::FromInt(count_value)));
4466 4467
4467 // Record position before stub call. 4468 // Record position before stub call.
4468 SetSourcePosition(expr->position()); 4469 SetSourcePosition(expr->position());
4469 4470
4470 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE); 4471 BinaryOpICStub stub(Token::ADD, NO_OVERWRITE);
4471 CallIC(stub.GetCode(isolate()), 4472 CallIC(stub.GetCode(isolate()), expr->CountBinOpFeedbackId());
4472 NOT_CONTEXTUAL,
4473 expr->CountBinOpFeedbackId());
4474 patch_site.EmitPatchInfo(); 4473 patch_site.EmitPatchInfo();
4475 __ bind(&done); 4474 __ bind(&done);
4476 4475
4477 // Store the value returned in v0. 4476 // Store the value returned in v0.
4478 switch (assign_type) { 4477 switch (assign_type) {
4479 case VARIABLE: 4478 case VARIABLE:
4480 if (expr->is_postfix()) { 4479 if (expr->is_postfix()) {
4481 { EffectContext context(this); 4480 { EffectContext context(this);
4482 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4481 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4483 Token::ASSIGN); 4482 Token::ASSIGN);
4484 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4483 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4485 context.Plug(v0); 4484 context.Plug(v0);
4486 } 4485 }
4487 // For all contexts except EffectConstant we have the result on 4486 // For all contexts except EffectConstant we have the result on
4488 // top of the stack. 4487 // top of the stack.
4489 if (!context()->IsEffect()) { 4488 if (!context()->IsEffect()) {
4490 context()->PlugTOS(); 4489 context()->PlugTOS();
4491 } 4490 }
4492 } else { 4491 } else {
4493 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), 4492 EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
4494 Token::ASSIGN); 4493 Token::ASSIGN);
4495 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4494 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4496 context()->Plug(v0); 4495 context()->Plug(v0);
4497 } 4496 }
4498 break; 4497 break;
4499 case NAMED_PROPERTY: { 4498 case NAMED_PROPERTY: {
4500 __ mov(a0, result_register()); // Value. 4499 __ mov(a0, result_register()); // Value.
4501 __ li(a2, Operand(prop->key()->AsLiteral()->value())); // Name. 4500 __ li(a2, Operand(prop->key()->AsLiteral()->value())); // Name.
4502 __ pop(a1); // Receiver. 4501 __ pop(a1); // Receiver.
4503 CallStoreIC(NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); 4502 CallStoreIC(expr->CountStoreFeedbackId());
4504 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4503 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4505 if (expr->is_postfix()) { 4504 if (expr->is_postfix()) {
4506 if (!context()->IsEffect()) { 4505 if (!context()->IsEffect()) {
4507 context()->PlugTOS(); 4506 context()->PlugTOS();
4508 } 4507 }
4509 } else { 4508 } else {
4510 context()->Plug(v0); 4509 context()->Plug(v0);
4511 } 4510 }
4512 break; 4511 break;
4513 } 4512 }
4514 case KEYED_PROPERTY: { 4513 case KEYED_PROPERTY: {
4515 __ mov(a0, result_register()); // Value. 4514 __ mov(a0, result_register()); // Value.
4516 __ Pop(a2, a1); // a1 = key, a2 = receiver. 4515 __ Pop(a2, a1); // a1 = key, a2 = receiver.
4517 Handle<Code> ic = is_classic_mode() 4516 Handle<Code> ic = is_classic_mode()
4518 ? isolate()->builtins()->KeyedStoreIC_Initialize() 4517 ? isolate()->builtins()->KeyedStoreIC_Initialize()
4519 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict(); 4518 : isolate()->builtins()->KeyedStoreIC_Initialize_Strict();
4520 CallIC(ic, NOT_CONTEXTUAL, expr->CountStoreFeedbackId()); 4519 CallIC(ic, expr->CountStoreFeedbackId());
4521 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); 4520 PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
4522 if (expr->is_postfix()) { 4521 if (expr->is_postfix()) {
4523 if (!context()->IsEffect()) { 4522 if (!context()->IsEffect()) {
4524 context()->PlugTOS(); 4523 context()->PlugTOS();
4525 } 4524 }
4526 } else { 4525 } else {
4527 context()->Plug(v0); 4526 context()->Plug(v0);
4528 } 4527 }
4529 break; 4528 break;
4530 } 4529 }
4531 } 4530 }
4532 } 4531 }
4533 4532
4534 4533
4535 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { 4534 void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
4536 ASSERT(!context()->IsEffect()); 4535 ASSERT(!context()->IsEffect());
4537 ASSERT(!context()->IsTest()); 4536 ASSERT(!context()->IsTest());
4538 VariableProxy* proxy = expr->AsVariableProxy(); 4537 VariableProxy* proxy = expr->AsVariableProxy();
4539 if (proxy != NULL && proxy->var()->IsUnallocated()) { 4538 if (proxy != NULL && proxy->var()->IsUnallocated()) {
4540 Comment cmnt(masm_, "Global variable"); 4539 Comment cmnt(masm_, "[ Global variable");
4541 __ lw(a0, GlobalObjectOperand()); 4540 __ lw(a0, GlobalObjectOperand());
4542 __ li(a2, Operand(proxy->name())); 4541 __ li(a2, Operand(proxy->name()));
4543 // Use a regular load, not a contextual load, to avoid a reference 4542 // Use a regular load, not a contextual load, to avoid a reference
4544 // error. 4543 // error.
4545 CallLoadIC(NOT_CONTEXTUAL); 4544 CallLoadIC(NOT_CONTEXTUAL);
4546 PrepareForBailout(expr, TOS_REG); 4545 PrepareForBailout(expr, TOS_REG);
4547 context()->Plug(v0); 4546 context()->Plug(v0);
4548 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { 4547 } else if (proxy != NULL && proxy->var()->IsLookupSlot()) {
4548 Comment cmnt(masm_, "[ Lookup slot");
4549 Label done, slow; 4549 Label done, slow;
4550 4550
4551 // Generate code for loading from variables potentially shadowed 4551 // Generate code for loading from variables potentially shadowed
4552 // by eval-introduced variables. 4552 // by eval-introduced variables.
4553 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done); 4553 EmitDynamicLookupFastCase(proxy->var(), INSIDE_TYPEOF, &slow, &done);
4554 4554
4555 __ bind(&slow); 4555 __ bind(&slow);
4556 __ li(a0, Operand(proxy->name())); 4556 __ li(a0, Operand(proxy->name()));
4557 __ Push(cp, a0); 4557 __ Push(cp, a0);
4558 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2); 4558 __ CallRuntime(Runtime::kLoadContextSlotNoReferenceError, 2);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
4695 if (inline_smi_code) { 4695 if (inline_smi_code) {
4696 Label slow_case; 4696 Label slow_case;
4697 __ Or(a2, a0, Operand(a1)); 4697 __ Or(a2, a0, Operand(a1));
4698 patch_site.EmitJumpIfNotSmi(a2, &slow_case); 4698 patch_site.EmitJumpIfNotSmi(a2, &slow_case);
4699 Split(cc, a1, Operand(a0), if_true, if_false, NULL); 4699 Split(cc, a1, Operand(a0), if_true, if_false, NULL);
4700 __ bind(&slow_case); 4700 __ bind(&slow_case);
4701 } 4701 }
4702 // Record position and call the compare IC. 4702 // Record position and call the compare IC.
4703 SetSourcePosition(expr->position()); 4703 SetSourcePosition(expr->position());
4704 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); 4704 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op);
4705 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); 4705 CallIC(ic, expr->CompareOperationFeedbackId());
4706 patch_site.EmitPatchInfo(); 4706 patch_site.EmitPatchInfo();
4707 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4707 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4708 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through); 4708 Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
4709 } 4709 }
4710 } 4710 }
4711 4711
4712 // Convert the result of the comparison into one expected for this 4712 // Convert the result of the comparison into one expected for this
4713 // expression's context. 4713 // expression's context.
4714 context()->Plug(if_true, if_false); 4714 context()->Plug(if_true, if_false);
4715 } 4715 }
(...skipping 13 matching lines...) Expand all
4729 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 4729 PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
4730 __ mov(a0, result_register()); 4730 __ mov(a0, result_register());
4731 if (expr->op() == Token::EQ_STRICT) { 4731 if (expr->op() == Token::EQ_STRICT) {
4732 Heap::RootListIndex nil_value = nil == kNullValue ? 4732 Heap::RootListIndex nil_value = nil == kNullValue ?
4733 Heap::kNullValueRootIndex : 4733 Heap::kNullValueRootIndex :
4734 Heap::kUndefinedValueRootIndex; 4734 Heap::kUndefinedValueRootIndex;
4735 __ LoadRoot(a1, nil_value); 4735 __ LoadRoot(a1, nil_value);
4736 Split(eq, a0, Operand(a1), if_true, if_false, fall_through); 4736 Split(eq, a0, Operand(a1), if_true, if_false, fall_through);
4737 } else { 4737 } else {
4738 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil); 4738 Handle<Code> ic = CompareNilICStub::GetUninitialized(isolate(), nil);
4739 CallIC(ic, NOT_CONTEXTUAL, expr->CompareOperationFeedbackId()); 4739 CallIC(ic, expr->CompareOperationFeedbackId());
4740 Split(ne, v0, Operand(zero_reg), if_true, if_false, fall_through); 4740 Split(ne, v0, Operand(zero_reg), if_true, if_false, fall_through);
4741 } 4741 }
4742 context()->Plug(if_true, if_false); 4742 context()->Plug(if_true, if_false);
4743 } 4743 }
4744 4744
4745 4745
4746 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { 4746 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) {
4747 __ lw(v0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 4747 __ lw(v0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
4748 context()->Plug(v0); 4748 context()->Plug(v0);
4749 } 4749 }
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after
4967 Assembler::target_address_at(pc_immediate_load_address)) == 4967 Assembler::target_address_at(pc_immediate_load_address)) ==
4968 reinterpret_cast<uint32_t>( 4968 reinterpret_cast<uint32_t>(
4969 isolate->builtins()->OsrAfterStackCheck()->entry())); 4969 isolate->builtins()->OsrAfterStackCheck()->entry()));
4970 return OSR_AFTER_STACK_CHECK; 4970 return OSR_AFTER_STACK_CHECK;
4971 } 4971 }
4972 4972
4973 4973
4974 } } // namespace v8::internal 4974 } } // namespace v8::internal
4975 4975
4976 #endif // V8_TARGET_ARCH_MIPS 4976 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « src/mips/deoptimizer-mips.cc ('k') | src/mips/ic-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698