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

Side by Side Diff: src/ic/mips/ic-compiler-mips.cc

Issue 496393002: MIPS: Move IC code into a subdir and move ic-compilation related code from stub-cache into ic-compi… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix formatting Created 6 years, 4 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 | « BUILD.gn ('k') | src/ic/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 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_MIPS 7 #if V8_TARGET_ARCH_MIPS
8 8
9 #include "src/codegen.h" 9 #include "src/ic/ic-compiler.h"
10 #include "src/ic-inl.h"
11 #include "src/stub-cache.h"
12 10
13 namespace v8 { 11 namespace v8 {
14 namespace internal { 12 namespace internal {
15 13
16 #define __ ACCESS_MASM(masm) 14 #define __ ACCESS_MASM(masm)
17 15
18 16
19 static void ProbeTable(Isolate* isolate,
20 MacroAssembler* masm,
21 Code::Flags flags,
22 StubCache::Table table,
23 Register receiver,
24 Register name,
25 // Number of the cache entry, not scaled.
26 Register offset,
27 Register scratch,
28 Register scratch2,
29 Register offset_scratch) {
30 ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
31 ExternalReference value_offset(isolate->stub_cache()->value_reference(table));
32 ExternalReference map_offset(isolate->stub_cache()->map_reference(table));
33
34 uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address());
35 uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address());
36 uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address());
37
38 // Check the relative positions of the address fields.
39 DCHECK(value_off_addr > key_off_addr);
40 DCHECK((value_off_addr - key_off_addr) % 4 == 0);
41 DCHECK((value_off_addr - key_off_addr) < (256 * 4));
42 DCHECK(map_off_addr > key_off_addr);
43 DCHECK((map_off_addr - key_off_addr) % 4 == 0);
44 DCHECK((map_off_addr - key_off_addr) < (256 * 4));
45
46 Label miss;
47 Register base_addr = scratch;
48 scratch = no_reg;
49
50 // Multiply by 3 because there are 3 fields per entry (name, code, map).
51 __ sll(offset_scratch, offset, 1);
52 __ Addu(offset_scratch, offset_scratch, offset);
53
54 // Calculate the base address of the entry.
55 __ li(base_addr, Operand(key_offset));
56 __ sll(at, offset_scratch, kPointerSizeLog2);
57 __ Addu(base_addr, base_addr, at);
58
59 // Check that the key in the entry matches the name.
60 __ lw(at, MemOperand(base_addr, 0));
61 __ Branch(&miss, ne, name, Operand(at));
62
63 // Check the map matches.
64 __ lw(at, MemOperand(base_addr, map_off_addr - key_off_addr));
65 __ lw(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
66 __ Branch(&miss, ne, at, Operand(scratch2));
67
68 // Get the code entry from the cache.
69 Register code = scratch2;
70 scratch2 = no_reg;
71 __ lw(code, MemOperand(base_addr, value_off_addr - key_off_addr));
72
73 // Check that the flags match what we're looking for.
74 Register flags_reg = base_addr;
75 base_addr = no_reg;
76 __ lw(flags_reg, FieldMemOperand(code, Code::kFlagsOffset));
77 __ And(flags_reg, flags_reg, Operand(~Code::kFlagsNotUsedInLookup));
78 __ Branch(&miss, ne, flags_reg, Operand(flags));
79
80 #ifdef DEBUG
81 if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) {
82 __ jmp(&miss);
83 } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) {
84 __ jmp(&miss);
85 }
86 #endif
87
88 // Jump to the first instruction in the code stub.
89 __ Addu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag));
90 __ Jump(at);
91
92 // Miss: fall through.
93 __ bind(&miss);
94 }
95
96
97 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( 17 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
98 MacroAssembler* masm, Label* miss_label, Register receiver, 18 MacroAssembler* masm, Label* miss_label, Register receiver,
99 Handle<Name> name, Register scratch0, Register scratch1) { 19 Handle<Name> name, Register scratch0, Register scratch1) {
100 DCHECK(name->IsUniqueName()); 20 DCHECK(name->IsUniqueName());
101 DCHECK(!receiver.is(scratch0)); 21 DCHECK(!receiver.is(scratch0));
102 Counters* counters = masm->isolate()->counters(); 22 Counters* counters = masm->isolate()->counters();
103 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 23 __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
104 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 24 __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
105 25
106 Label done; 26 Label done;
(...skipping 18 matching lines...) Expand all
125 // Check that the properties array is a dictionary. 45 // Check that the properties array is a dictionary.
126 __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 46 __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset));
127 Register tmp = properties; 47 Register tmp = properties;
128 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 48 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
129 __ Branch(miss_label, ne, map, Operand(tmp)); 49 __ Branch(miss_label, ne, map, Operand(tmp));
130 50
131 // Restore the temporarily used register. 51 // Restore the temporarily used register.
132 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 52 __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
133 53
134 54
135 NameDictionaryLookupStub::GenerateNegativeLookup(masm, 55 NameDictionaryLookupStub::GenerateNegativeLookup(
136 miss_label, 56 masm, miss_label, &done, receiver, properties, name, scratch1);
137 &done,
138 receiver,
139 properties,
140 name,
141 scratch1);
142 __ bind(&done); 57 __ bind(&done);
143 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 58 __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
144 } 59 }
145 60
146 61
147 void StubCache::GenerateProbe(MacroAssembler* masm,
148 Code::Flags flags,
149 Register receiver,
150 Register name,
151 Register scratch,
152 Register extra,
153 Register extra2,
154 Register extra3) {
155 Isolate* isolate = masm->isolate();
156 Label miss;
157
158 // Make sure that code is valid. The multiplying code relies on the
159 // entry size being 12.
160 DCHECK(sizeof(Entry) == 12);
161
162 // Make sure the flags does not name a specific type.
163 DCHECK(Code::ExtractTypeFromFlags(flags) == 0);
164
165 // Make sure that there are no register conflicts.
166 DCHECK(!scratch.is(receiver));
167 DCHECK(!scratch.is(name));
168 DCHECK(!extra.is(receiver));
169 DCHECK(!extra.is(name));
170 DCHECK(!extra.is(scratch));
171 DCHECK(!extra2.is(receiver));
172 DCHECK(!extra2.is(name));
173 DCHECK(!extra2.is(scratch));
174 DCHECK(!extra2.is(extra));
175
176 // Check register validity.
177 DCHECK(!scratch.is(no_reg));
178 DCHECK(!extra.is(no_reg));
179 DCHECK(!extra2.is(no_reg));
180 DCHECK(!extra3.is(no_reg));
181
182 Counters* counters = masm->isolate()->counters();
183 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1,
184 extra2, extra3);
185
186 // Check that the receiver isn't a smi.
187 __ JumpIfSmi(receiver, &miss);
188
189 // Get the map of the receiver and compute the hash.
190 __ lw(scratch, FieldMemOperand(name, Name::kHashFieldOffset));
191 __ lw(at, FieldMemOperand(receiver, HeapObject::kMapOffset));
192 __ Addu(scratch, scratch, at);
193 uint32_t mask = kPrimaryTableSize - 1;
194 // We shift out the last two bits because they are not part of the hash and
195 // they are always 01 for maps.
196 __ srl(scratch, scratch, kCacheIndexShift);
197 __ Xor(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask));
198 __ And(scratch, scratch, Operand(mask));
199
200 // Probe the primary table.
201 ProbeTable(isolate,
202 masm,
203 flags,
204 kPrimary,
205 receiver,
206 name,
207 scratch,
208 extra,
209 extra2,
210 extra3);
211
212 // Primary miss: Compute hash for secondary probe.
213 __ srl(at, name, kCacheIndexShift);
214 __ Subu(scratch, scratch, at);
215 uint32_t mask2 = kSecondaryTableSize - 1;
216 __ Addu(scratch, scratch, Operand((flags >> kCacheIndexShift) & mask2));
217 __ And(scratch, scratch, Operand(mask2));
218
219 // Probe the secondary table.
220 ProbeTable(isolate,
221 masm,
222 flags,
223 kSecondary,
224 receiver,
225 name,
226 scratch,
227 extra,
228 extra2,
229 extra3);
230
231 // Cache miss: Fall-through and let caller handle the miss by
232 // entering the runtime system.
233 __ bind(&miss);
234 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1,
235 extra2, extra3);
236 }
237
238
239 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( 62 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
240 MacroAssembler* masm, int index, Register prototype, Label* miss) { 63 MacroAssembler* masm, int index, Register prototype, Label* miss) {
241 Isolate* isolate = masm->isolate(); 64 Isolate* isolate = masm->isolate();
242 // Get the global function with the given index. 65 // Get the global function with the given index.
243 Handle<JSFunction> function( 66 Handle<JSFunction> function(
244 JSFunction::cast(isolate->native_context()->get(index))); 67 JSFunction::cast(isolate->native_context()->get(index)));
245 68
246 // Check we're still in the same context. 69 // Check we're still in the same context.
247 Register scratch = prototype; 70 Register scratch = prototype;
248 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); 71 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
(...skipping 24 matching lines...) Expand all
273 Register scratch, Label* miss) { 96 Register scratch, Label* miss) {
274 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name); 97 Handle<Cell> cell = JSGlobalObject::EnsurePropertyCell(global, name);
275 DCHECK(cell->value()->IsTheHole()); 98 DCHECK(cell->value()->IsTheHole());
276 __ li(scratch, Operand(cell)); 99 __ li(scratch, Operand(cell));
277 __ lw(scratch, FieldMemOperand(scratch, Cell::kValueOffset)); 100 __ lw(scratch, FieldMemOperand(scratch, Cell::kValueOffset));
278 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 101 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
279 __ Branch(miss, ne, scratch, Operand(at)); 102 __ Branch(miss, ne, scratch, Operand(at));
280 } 103 }
281 104
282 105
283 static void PushInterceptorArguments(MacroAssembler* masm, 106 static void PushInterceptorArguments(MacroAssembler* masm, Register receiver,
284 Register receiver, 107 Register holder, Register name,
285 Register holder,
286 Register name,
287 Handle<JSObject> holder_obj) { 108 Handle<JSObject> holder_obj) {
288 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); 109 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0);
289 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); 110 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1);
290 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); 111 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2);
291 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); 112 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3);
292 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); 113 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4);
293 __ push(name); 114 __ push(name);
294 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 115 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
295 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); 116 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor));
296 Register scratch = name; 117 Register scratch = name;
297 __ li(scratch, Operand(interceptor)); 118 __ li(scratch, Operand(interceptor));
298 __ Push(scratch, receiver, holder); 119 __ Push(scratch, receiver, holder);
299 } 120 }
300 121
301 122
302 static void CompileCallLoadPropertyWithInterceptor( 123 static void CompileCallLoadPropertyWithInterceptor(
303 MacroAssembler* masm, 124 MacroAssembler* masm, Register receiver, Register holder, Register name,
304 Register receiver, 125 Handle<JSObject> holder_obj, IC::UtilityId id) {
305 Register holder,
306 Register name,
307 Handle<JSObject> holder_obj,
308 IC::UtilityId id) {
309 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 126 PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
310 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), 127 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()),
311 NamedLoadHandlerCompiler::kInterceptorArgsLength); 128 NamedLoadHandlerCompiler::kInterceptorArgsLength);
312 } 129 }
313 130
314 131
315 // Generate call to api function. 132 // Generate call to api function.
316 void PropertyHandlerCompiler::GenerateFastApiCall( 133 void PropertyHandlerCompiler::GenerateFastApiCall(
317 MacroAssembler* masm, const CallOptimization& optimization, 134 MacroAssembler* masm, const CallOptimization& optimization,
318 Handle<Map> receiver_map, Register receiver, Register scratch_in, 135 Handle<Map> receiver_map, Register receiver, Register scratch_in,
319 bool is_store, int argc, Register* values) { 136 bool is_store, int argc, Register* values) {
320 DCHECK(!receiver.is(scratch_in)); 137 DCHECK(!receiver.is(scratch_in));
321 // Preparing to push, adjust sp. 138 // Preparing to push, adjust sp.
322 __ Subu(sp, sp, Operand((argc + 1) * kPointerSize)); 139 __ Subu(sp, sp, Operand((argc + 1) * kPointerSize));
323 __ sw(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver. 140 __ sw(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver.
324 // Write the arguments to stack frame. 141 // Write the arguments to stack frame.
325 for (int i = 0; i < argc; i++) { 142 for (int i = 0; i < argc; i++) {
326 Register arg = values[argc-1-i]; 143 Register arg = values[argc - 1 - i];
327 DCHECK(!receiver.is(arg)); 144 DCHECK(!receiver.is(arg));
328 DCHECK(!scratch_in.is(arg)); 145 DCHECK(!scratch_in.is(arg));
329 __ sw(arg, MemOperand(sp, (argc-1-i) * kPointerSize)); // Push arg. 146 __ sw(arg, MemOperand(sp, (argc - 1 - i) * kPointerSize)); // Push arg.
330 } 147 }
331 DCHECK(optimization.is_simple_api_call()); 148 DCHECK(optimization.is_simple_api_call());
332 149
333 // Abi for CallApiFunctionStub. 150 // Abi for CallApiFunctionStub.
334 Register callee = a0; 151 Register callee = a0;
335 Register call_data = t0; 152 Register call_data = t0;
336 Register holder = a2; 153 Register holder = a2;
337 Register api_function_address = a1; 154 Register api_function_address = a1;
338 155
339 // Put holder in place. 156 // Put holder in place.
340 CallOptimization::HolderLookup holder_lookup; 157 CallOptimization::HolderLookup holder_lookup;
341 Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType( 158 Handle<JSObject> api_holder =
342 receiver_map, 159 optimization.LookupHolderOfExpectedType(receiver_map, &holder_lookup);
343 &holder_lookup);
344 switch (holder_lookup) { 160 switch (holder_lookup) {
345 case CallOptimization::kHolderIsReceiver: 161 case CallOptimization::kHolderIsReceiver:
346 __ Move(holder, receiver); 162 __ Move(holder, receiver);
347 break; 163 break;
348 case CallOptimization::kHolderFound: 164 case CallOptimization::kHolderFound:
349 __ li(holder, api_holder); 165 __ li(holder, api_holder);
350 break; 166 break;
351 case CallOptimization::kHolderNotFound: 167 case CallOptimization::kHolderNotFound:
352 UNREACHABLE(); 168 UNREACHABLE();
353 break; 169 break;
354 } 170 }
355 171
356 Isolate* isolate = masm->isolate(); 172 Isolate* isolate = masm->isolate();
357 Handle<JSFunction> function = optimization.constant_function(); 173 Handle<JSFunction> function = optimization.constant_function();
358 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 174 Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
359 Handle<Object> call_data_obj(api_call_info->data(), isolate); 175 Handle<Object> call_data_obj(api_call_info->data(), isolate);
360 176
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow, 268 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow,
453 TAG_RESULT, MUTABLE); 269 TAG_RESULT, MUTABLE);
454 270
455 __ JumpIfNotSmi(value_reg, &heap_number); 271 __ JumpIfNotSmi(value_reg, &heap_number);
456 __ SmiUntag(scratch1, value_reg); 272 __ SmiUntag(scratch1, value_reg);
457 __ mtc1(scratch1, f6); 273 __ mtc1(scratch1, f6);
458 __ cvt_d_w(f4, f6); 274 __ cvt_d_w(f4, f6);
459 __ jmp(&do_store); 275 __ jmp(&do_store);
460 276
461 __ bind(&heap_number); 277 __ bind(&heap_number);
462 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, 278 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, miss_label,
463 miss_label, DONT_DO_SMI_CHECK); 279 DONT_DO_SMI_CHECK);
464 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset)); 280 __ ldc1(f4, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
465 281
466 __ bind(&do_store); 282 __ bind(&do_store);
467 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset)); 283 __ sdc1(f4, FieldMemOperand(storage_reg, HeapNumber::kValueOffset));
468 } 284 }
469 285
470 // Stub never generated for objects that require access checks. 286 // Stub never generated for objects that require access checks.
471 DCHECK(!transition->is_access_check_needed()); 287 DCHECK(!transition->is_access_check_needed());
472 288
473 // Perform map transition for the receiver if necessary. 289 // Perform map transition for the receiver if necessary.
474 if (details.type() == FIELD && 290 if (details.type() == FIELD &&
475 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { 291 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
476 // The properties must be extended before we can store the value. 292 // The properties must be extended before we can store the value.
477 // We jump to a runtime call that extends the properties array. 293 // We jump to a runtime call that extends the properties array.
478 __ push(receiver_reg); 294 __ push(receiver_reg);
479 __ li(a2, Operand(transition)); 295 __ li(a2, Operand(transition));
480 __ Push(a2, a0); 296 __ Push(a2, a0);
481 __ TailCallExternalReference( 297 __ TailCallExternalReference(
482 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 298 ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage),
483 isolate()), 299 isolate()),
484 3, 1); 300 3, 1);
485 return; 301 return;
486 } 302 }
487 303
488 // Update the map of the object. 304 // Update the map of the object.
489 __ li(scratch1, Operand(transition)); 305 __ li(scratch1, Operand(transition));
490 __ sw(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 306 __ sw(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
491 307
492 // Update the write barrier for the map field. 308 // Update the write barrier for the map field.
493 __ RecordWriteField(receiver_reg, 309 __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2,
494 HeapObject::kMapOffset, 310 kRAHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET,
495 scratch1,
496 scratch2,
497 kRAHasNotBeenSaved,
498 kDontSaveFPRegs,
499 OMIT_REMEMBERED_SET,
500 OMIT_SMI_CHECK); 311 OMIT_SMI_CHECK);
501 312
502 if (details.type() == CONSTANT) { 313 if (details.type() == CONSTANT) {
503 DCHECK(value_reg.is(a0)); 314 DCHECK(value_reg.is(a0));
504 __ Ret(USE_DELAY_SLOT); 315 __ Ret(USE_DELAY_SLOT);
505 __ mov(v0, a0); 316 __ mov(v0, a0);
506 return; 317 return;
507 } 318 }
508 319
509 int index = transition->instance_descriptors()->GetFieldIndex( 320 int index = transition->instance_descriptors()->GetFieldIndex(
510 transition->LastAdded()); 321 transition->LastAdded());
511 322
512 // Adjust for the number of properties stored in the object. Even in the 323 // Adjust for the number of properties stored in the object. Even in the
513 // face of a transition we can use the old map here because the size of the 324 // face of a transition we can use the old map here because the size of the
514 // object and the number of in-object properties is not going to change. 325 // object and the number of in-object properties is not going to change.
515 index -= transition->inobject_properties(); 326 index -= transition->inobject_properties();
516 327
517 // TODO(verwaest): Share this code as a code stub. 328 // TODO(verwaest): Share this code as a code stub.
518 SmiCheck smi_check = representation.IsTagged() 329 SmiCheck smi_check =
519 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; 330 representation.IsTagged() ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
520 if (index < 0) { 331 if (index < 0) {
521 // Set the property straight into the object. 332 // Set the property straight into the object.
522 int offset = transition->instance_size() + (index * kPointerSize); 333 int offset = transition->instance_size() + (index * kPointerSize);
523 if (representation.IsDouble()) { 334 if (representation.IsDouble()) {
524 __ sw(storage_reg, FieldMemOperand(receiver_reg, offset)); 335 __ sw(storage_reg, FieldMemOperand(receiver_reg, offset));
525 } else { 336 } else {
526 __ sw(value_reg, FieldMemOperand(receiver_reg, offset)); 337 __ sw(value_reg, FieldMemOperand(receiver_reg, offset));
527 } 338 }
528 339
529 if (!representation.IsSmi()) { 340 if (!representation.IsSmi()) {
530 // Update the write barrier for the array address. 341 // Update the write barrier for the array address.
531 if (!representation.IsDouble()) { 342 if (!representation.IsDouble()) {
532 __ mov(storage_reg, value_reg); 343 __ mov(storage_reg, value_reg);
533 } 344 }
534 __ RecordWriteField(receiver_reg, 345 __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1,
535 offset, 346 kRAHasNotBeenSaved, kDontSaveFPRegs,
536 storage_reg, 347 EMIT_REMEMBERED_SET, smi_check);
537 scratch1,
538 kRAHasNotBeenSaved,
539 kDontSaveFPRegs,
540 EMIT_REMEMBERED_SET,
541 smi_check);
542 } 348 }
543 } else { 349 } else {
544 // Write to the properties array. 350 // Write to the properties array.
545 int offset = index * kPointerSize + FixedArray::kHeaderSize; 351 int offset = index * kPointerSize + FixedArray::kHeaderSize;
546 // Get the properties array 352 // Get the properties array
547 __ lw(scratch1, 353 __ lw(scratch1, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
548 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
549 if (representation.IsDouble()) { 354 if (representation.IsDouble()) {
550 __ sw(storage_reg, FieldMemOperand(scratch1, offset)); 355 __ sw(storage_reg, FieldMemOperand(scratch1, offset));
551 } else { 356 } else {
552 __ sw(value_reg, FieldMemOperand(scratch1, offset)); 357 __ sw(value_reg, FieldMemOperand(scratch1, offset));
553 } 358 }
554 359
555 if (!representation.IsSmi()) { 360 if (!representation.IsSmi()) {
556 // Update the write barrier for the array address. 361 // Update the write barrier for the array address.
557 if (!representation.IsDouble()) { 362 if (!representation.IsDouble()) {
558 __ mov(storage_reg, value_reg); 363 __ mov(storage_reg, value_reg);
559 } 364 }
560 __ RecordWriteField(scratch1, 365 __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg,
561 offset, 366 kRAHasNotBeenSaved, kDontSaveFPRegs,
562 storage_reg, 367 EMIT_REMEMBERED_SET, smi_check);
563 receiver_reg,
564 kRAHasNotBeenSaved,
565 kDontSaveFPRegs,
566 EMIT_REMEMBERED_SET,
567 smi_check);
568 } 368 }
569 } 369 }
570 370
571 // Return the value (register v0). 371 // Return the value (register v0).
572 DCHECK(value_reg.is(a0)); 372 DCHECK(value_reg.is(a0));
573 __ bind(&exit); 373 __ bind(&exit);
574 __ Ret(USE_DELAY_SLOT); 374 __ Ret(USE_DELAY_SLOT);
575 __ mov(v0, a0); 375 __ mov(v0, a0);
576 } 376 }
577 377
(...skipping 26 matching lines...) Expand all
604 404
605 405
606 Register PropertyHandlerCompiler::CheckPrototypes( 406 Register PropertyHandlerCompiler::CheckPrototypes(
607 Register object_reg, Register holder_reg, Register scratch1, 407 Register object_reg, Register holder_reg, Register scratch1,
608 Register scratch2, Handle<Name> name, Label* miss, 408 Register scratch2, Handle<Name> name, Label* miss,
609 PrototypeCheckType check) { 409 PrototypeCheckType check) {
610 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); 410 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
611 411
612 // Make sure there's no overlap between holder and object registers. 412 // Make sure there's no overlap between holder and object registers.
613 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 413 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
614 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 414 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
615 && !scratch2.is(scratch1)); 415 !scratch2.is(scratch1));
616 416
617 // Keep track of the current object in register reg. 417 // Keep track of the current object in register reg.
618 Register reg = object_reg; 418 Register reg = object_reg;
619 int depth = 0; 419 int depth = 0;
620 420
621 Handle<JSObject> current = Handle<JSObject>::null(); 421 Handle<JSObject> current = Handle<JSObject>::null();
622 if (type()->IsConstant()) { 422 if (type()->IsConstant()) {
623 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); 423 current = Handle<JSObject>::cast(type()->AsConstant()->Value());
624 } 424 }
625 Handle<JSObject> prototype = Handle<JSObject>::null(); 425 Handle<JSObject> prototype = Handle<JSObject>::null();
(...skipping 12 matching lines...) Expand all
638 prototype = handle(JSObject::cast(current_map->prototype())); 438 prototype = handle(JSObject::cast(current_map->prototype()));
639 if (current_map->is_dictionary_map() && 439 if (current_map->is_dictionary_map() &&
640 !current_map->IsJSGlobalObjectMap()) { 440 !current_map->IsJSGlobalObjectMap()) {
641 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast. 441 DCHECK(!current_map->IsJSGlobalProxyMap()); // Proxy maps are fast.
642 if (!name->IsUniqueName()) { 442 if (!name->IsUniqueName()) {
643 DCHECK(name->IsString()); 443 DCHECK(name->IsString());
644 name = factory()->InternalizeString(Handle<String>::cast(name)); 444 name = factory()->InternalizeString(Handle<String>::cast(name));
645 } 445 }
646 DCHECK(current.is_null() || 446 DCHECK(current.is_null() ||
647 current->property_dictionary()->FindEntry(name) == 447 current->property_dictionary()->FindEntry(name) ==
648 NameDictionary::kNotFound); 448 NameDictionary::kNotFound);
649 449
650 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, 450 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, scratch1,
651 scratch1, scratch2); 451 scratch2);
652 452
653 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 453 __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
654 reg = holder_reg; // From now on the object will be in holder_reg. 454 reg = holder_reg; // From now on the object will be in holder_reg.
655 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 455 __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
656 } else { 456 } else {
657 Register map_reg = scratch1; 457 Register map_reg = scratch1;
658 if (depth != 1 || check == CHECK_ALL_MAPS) { 458 if (depth != 1 || check == CHECK_ALL_MAPS) {
659 // CheckMap implicitly loads the map of |reg| into |map_reg|. 459 // CheckMap implicitly loads the map of |reg| into |map_reg|.
660 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK); 460 __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK);
661 } else { 461 } else {
662 __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); 462 __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset));
663 } 463 }
664 464
665 // Check access rights to the global object. This has to happen after 465 // Check access rights to the global object. This has to happen after
666 // the map check so that we know that the object is actually a global 466 // the map check so that we know that the object is actually a global
667 // object. 467 // object.
668 // This allows us to install generated handlers for accesses to the 468 // This allows us to install generated handlers for accesses to the
669 // global proxy (as opposed to using slow ICs). See corresponding code 469 // global proxy (as opposed to using slow ICs). See corresponding code
670 // in LookupForRead(). 470 // in LookupForRead().
671 if (current_map->IsJSGlobalProxyMap()) { 471 if (current_map->IsJSGlobalProxyMap()) {
672 __ CheckAccessGlobalProxy(reg, scratch2, miss); 472 __ CheckAccessGlobalProxy(reg, scratch2, miss);
673 } else if (current_map->IsJSGlobalObjectMap()) { 473 } else if (current_map->IsJSGlobalObjectMap()) {
674 GenerateCheckPropertyCell( 474 GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
675 masm(), Handle<JSGlobalObject>::cast(current), name, 475 name, scratch2, miss);
676 scratch2, miss);
677 } 476 }
678 477
679 reg = holder_reg; // From now on the object will be in holder_reg. 478 reg = holder_reg; // From now on the object will be in holder_reg.
680 479
681 // Two possible reasons for loading the prototype from the map: 480 // Two possible reasons for loading the prototype from the map:
682 // (1) Can't store references to new space in code. 481 // (1) Can't store references to new space in code.
683 // (2) Handler is shared for all receivers with the same prototype 482 // (2) Handler is shared for all receivers with the same prototype
684 // map (but not necessarily the same prototype instance). 483 // map (but not necessarily the same prototype instance).
685 bool load_prototype_from_map = 484 bool load_prototype_from_map =
686 heap()->InNewSpace(*prototype) || depth == 1; 485 heap()->InNewSpace(*prototype) || depth == 1;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); 554 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3);
756 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); 555 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4);
757 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); 556 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5);
758 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); 557 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6);
759 DCHECK(!scratch2().is(reg)); 558 DCHECK(!scratch2().is(reg));
760 DCHECK(!scratch3().is(reg)); 559 DCHECK(!scratch3().is(reg));
761 DCHECK(!scratch4().is(reg)); 560 DCHECK(!scratch4().is(reg));
762 __ push(receiver()); 561 __ push(receiver());
763 if (heap()->InNewSpace(callback->data())) { 562 if (heap()->InNewSpace(callback->data())) {
764 __ li(scratch3(), callback); 563 __ li(scratch3(), callback);
765 __ lw(scratch3(), FieldMemOperand(scratch3(), 564 __ lw(scratch3(),
766 ExecutableAccessorInfo::kDataOffset)); 565 FieldMemOperand(scratch3(), ExecutableAccessorInfo::kDataOffset));
767 } else { 566 } else {
768 __ li(scratch3(), Handle<Object>(callback->data(), isolate())); 567 __ li(scratch3(), Handle<Object>(callback->data(), isolate()));
769 } 568 }
770 __ Subu(sp, sp, 6 * kPointerSize); 569 __ Subu(sp, sp, 6 * kPointerSize);
771 __ sw(scratch3(), MemOperand(sp, 5 * kPointerSize)); 570 __ sw(scratch3(), MemOperand(sp, 5 * kPointerSize));
772 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex); 571 __ LoadRoot(scratch3(), Heap::kUndefinedValueRootIndex);
773 __ sw(scratch3(), MemOperand(sp, 4 * kPointerSize)); 572 __ sw(scratch3(), MemOperand(sp, 4 * kPointerSize));
774 __ sw(scratch3(), MemOperand(sp, 3 * kPointerSize)); 573 __ sw(scratch3(), MemOperand(sp, 3 * kPointerSize));
775 __ li(scratch4(), 574 __ li(scratch4(), Operand(ExternalReference::isolate_address(isolate())));
776 Operand(ExternalReference::isolate_address(isolate())));
777 __ sw(scratch4(), MemOperand(sp, 2 * kPointerSize)); 575 __ sw(scratch4(), MemOperand(sp, 2 * kPointerSize));
778 __ sw(reg, MemOperand(sp, 1 * kPointerSize)); 576 __ sw(reg, MemOperand(sp, 1 * kPointerSize));
779 __ sw(name(), MemOperand(sp, 0 * kPointerSize)); 577 __ sw(name(), MemOperand(sp, 0 * kPointerSize));
780 __ Addu(scratch2(), sp, 1 * kPointerSize); 578 __ Addu(scratch2(), sp, 1 * kPointerSize);
781 579
782 __ mov(a2, scratch2()); // Saved in case scratch2 == a1. 580 __ mov(a2, scratch2()); // Saved in case scratch2 == a1.
783 // Abi for CallApiGetter. 581 // Abi for CallApiGetter.
784 Register getter_address_reg = a2; 582 Register getter_address_reg = a2;
785 583
786 Address getter_address = v8::ToCData<Address>(callback->getter()); 584 Address getter_address = v8::ToCData<Address>(callback->getter());
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1); 663 ref, NamedLoadHandlerCompiler::kInterceptorArgsLength, 1);
866 } 664 }
867 665
868 666
869 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( 667 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
870 Handle<JSObject> object, Handle<Name> name, 668 Handle<JSObject> object, Handle<Name> name,
871 Handle<ExecutableAccessorInfo> callback) { 669 Handle<ExecutableAccessorInfo> callback) {
872 Register holder_reg = Frontend(receiver(), name); 670 Register holder_reg = Frontend(receiver(), name);
873 671
874 __ Push(receiver(), holder_reg); // Receiver. 672 __ Push(receiver(), holder_reg); // Receiver.
875 __ li(at, Operand(callback)); // Callback info. 673 __ li(at, Operand(callback)); // Callback info.
876 __ push(at); 674 __ push(at);
877 __ li(at, Operand(name)); 675 __ li(at, Operand(name));
878 __ Push(at, value()); 676 __ Push(at, value());
879 677
880 // Do tail-call to the runtime system. 678 // Do tail-call to the runtime system.
881 ExternalReference store_callback_property = 679 ExternalReference store_callback_property =
882 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 680 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate());
883 __ TailCallExternalReference(store_callback_property, 5, 1); 681 __ TailCallExternalReference(store_callback_property, 5, 1);
884 682
885 // Return the generated code. 683 // Return the generated code.
(...skipping 15 matching lines...) Expand all
901 FrameScope scope(masm, StackFrame::INTERNAL); 699 FrameScope scope(masm, StackFrame::INTERNAL);
902 700
903 // Save value register, so we can restore it later. 701 // Save value register, so we can restore it later.
904 __ push(value()); 702 __ push(value());
905 703
906 if (!setter.is_null()) { 704 if (!setter.is_null()) {
907 // Call the JavaScript setter with receiver and value on the stack. 705 // Call the JavaScript setter with receiver and value on the stack.
908 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 706 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
909 // Swap in the global receiver. 707 // Swap in the global receiver.
910 __ lw(receiver, 708 __ lw(receiver,
911 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 709 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
912 } 710 }
913 __ Push(receiver, value()); 711 __ Push(receiver, value());
914 ParameterCount actual(1); 712 ParameterCount actual(1);
915 ParameterCount expected(setter); 713 ParameterCount expected(setter);
916 __ InvokeFunction(setter, expected, actual, 714 __ InvokeFunction(setter, expected, actual, CALL_FUNCTION,
917 CALL_FUNCTION, NullCallWrapper()); 715 NullCallWrapper());
918 } else { 716 } else {
919 // If we generate a global code snippet for deoptimization only, remember 717 // If we generate a global code snippet for deoptimization only, remember
920 // the place to continue after deoptimization. 718 // the place to continue after deoptimization.
921 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset()); 719 masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
922 } 720 }
923 721
924 // We have to return the passed value, not the return value of the setter. 722 // We have to return the passed value, not the return value of the setter.
925 __ pop(v0); 723 __ pop(v0);
926 724
927 // Restore context register. 725 // Restore context register.
(...skipping 18 matching lines...) Expand all
946 744
947 // Return the generated code. 745 // Return the generated code.
948 return GetCode(kind(), Code::FAST, name); 746 return GetCode(kind(), Code::FAST, name);
949 } 747 }
950 748
951 749
952 Register* PropertyAccessCompiler::load_calling_convention() { 750 Register* PropertyAccessCompiler::load_calling_convention() {
953 // receiver, name, scratch1, scratch2, scratch3, scratch4. 751 // receiver, name, scratch1, scratch2, scratch3, scratch4.
954 Register receiver = LoadIC::ReceiverRegister(); 752 Register receiver = LoadIC::ReceiverRegister();
955 Register name = LoadIC::NameRegister(); 753 Register name = LoadIC::NameRegister();
956 static Register registers[] = { receiver, name, a3, a0, t0, t1 }; 754 static Register registers[] = {receiver, name, a3, a0, t0, t1};
957 return registers; 755 return registers;
958 } 756 }
959 757
960 758
961 Register* PropertyAccessCompiler::store_calling_convention() { 759 Register* PropertyAccessCompiler::store_calling_convention() {
962 // receiver, name, scratch1, scratch2, scratch3. 760 // receiver, name, scratch1, scratch2, scratch3.
963 Register receiver = StoreIC::ReceiverRegister(); 761 Register receiver = StoreIC::ReceiverRegister();
964 Register name = StoreIC::NameRegister(); 762 Register name = StoreIC::NameRegister();
965 DCHECK(a3.is(KeyedStoreIC::MapRegister())); 763 DCHECK(a3.is(KeyedStoreIC::MapRegister()));
966 static Register registers[] = { receiver, name, a3, t0, t1 }; 764 static Register registers[] = {receiver, name, a3, t0, t1};
967 return registers; 765 return registers;
968 } 766 }
969 767
970 768
971 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } 769 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
972 770
973 771
974 #undef __ 772 #undef __
975 #define __ ACCESS_MASM(masm) 773 #define __ ACCESS_MASM(masm)
976 774
977 775
978 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( 776 void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
979 MacroAssembler* masm, Handle<HeapType> type, Register receiver, 777 MacroAssembler* masm, Handle<HeapType> type, Register receiver,
980 Handle<JSFunction> getter) { 778 Handle<JSFunction> getter) {
981 // ----------- S t a t e ------------- 779 // ----------- S t a t e -------------
982 // -- a0 : receiver 780 // -- a0 : receiver
983 // -- a2 : name 781 // -- a2 : name
984 // -- ra : return address 782 // -- ra : return address
985 // ----------------------------------- 783 // -----------------------------------
986 { 784 {
987 FrameScope scope(masm, StackFrame::INTERNAL); 785 FrameScope scope(masm, StackFrame::INTERNAL);
988 786
989 if (!getter.is_null()) { 787 if (!getter.is_null()) {
990 // Call the JavaScript getter with the receiver on the stack. 788 // Call the JavaScript getter with the receiver on the stack.
991 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) { 789 if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
992 // Swap in the global receiver. 790 // Swap in the global receiver.
993 __ lw(receiver, 791 __ lw(receiver,
994 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset)); 792 FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
995 } 793 }
996 __ push(receiver); 794 __ push(receiver);
997 ParameterCount actual(0); 795 ParameterCount actual(0);
998 ParameterCount expected(getter); 796 ParameterCount expected(getter);
999 __ InvokeFunction(getter, expected, actual, 797 __ InvokeFunction(getter, expected, actual, CALL_FUNCTION,
1000 CALL_FUNCTION, NullCallWrapper()); 798 NullCallWrapper());
1001 } else { 799 } else {
1002 // If we generate a global code snippet for deoptimization only, remember 800 // If we generate a global code snippet for deoptimization only, remember
1003 // the place to continue after deoptimization. 801 // the place to continue after deoptimization.
1004 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset()); 802 masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
1005 } 803 }
1006 804
1007 // Restore context register. 805 // Restore context register.
1008 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 806 __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
1009 } 807 }
1010 __ Ret(); 808 __ Ret();
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1080 Handle<Map> map = IC::TypeToMap(*type, isolate()); 878 Handle<Map> map = IC::TypeToMap(*type, isolate());
1081 if (!map->is_deprecated()) { 879 if (!map->is_deprecated()) {
1082 number_of_handled_maps++; 880 number_of_handled_maps++;
1083 // Check map and tail call if there's a match. 881 // Check map and tail call if there's a match.
1084 // Separate compare from branch, to provide path for above JumpIfSmi(). 882 // Separate compare from branch, to provide path for above JumpIfSmi().
1085 __ Subu(match, map_reg, Operand(map)); 883 __ Subu(match, map_reg, Operand(map));
1086 if (type->Is(HeapType::Number())) { 884 if (type->Is(HeapType::Number())) {
1087 DCHECK(!number_case.is_unused()); 885 DCHECK(!number_case.is_unused());
1088 __ bind(&number_case); 886 __ bind(&number_case);
1089 } 887 }
1090 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, 888 __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq, match,
1091 eq, match, Operand(zero_reg)); 889 Operand(zero_reg));
1092 } 890 }
1093 } 891 }
1094 DCHECK(number_of_handled_maps != 0); 892 DCHECK(number_of_handled_maps != 0);
1095 893
1096 __ bind(&miss); 894 __ bind(&miss);
1097 TailCallBuiltin(masm(), MissBuiltin(kind())); 895 TailCallBuiltin(masm(), MissBuiltin(kind()));
1098 896
1099 // Return the generated code. 897 // Return the generated code.
1100 InlineCacheState state = 898 InlineCacheState state =
1101 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; 899 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC;
1102 return GetCode(kind(), type, name, state); 900 return GetCode(kind(), type, name, state);
1103 } 901 }
1104 902
1105 903
1106 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic( 904 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
1107 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, 905 MapHandleList* receiver_maps, CodeHandleList* handler_stubs,
1108 MapHandleList* transitioned_maps) { 906 MapHandleList* transitioned_maps) {
1109 Label miss; 907 Label miss;
1110 __ JumpIfSmi(receiver(), &miss); 908 __ JumpIfSmi(receiver(), &miss);
1111 909
1112 int receiver_count = receiver_maps->length(); 910 int receiver_count = receiver_maps->length();
1113 __ lw(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset)); 911 __ lw(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
1114 for (int i = 0; i < receiver_count; ++i) { 912 for (int i = 0; i < receiver_count; ++i) {
1115 if (transitioned_maps->at(i).is_null()) { 913 if (transitioned_maps->at(i).is_null()) {
1116 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq, 914 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq, scratch1(),
1117 scratch1(), Operand(receiver_maps->at(i))); 915 Operand(receiver_maps->at(i)));
1118 } else { 916 } else {
1119 Label next_map; 917 Label next_map;
1120 __ Branch(&next_map, ne, scratch1(), Operand(receiver_maps->at(i))); 918 __ Branch(&next_map, ne, scratch1(), Operand(receiver_maps->at(i)));
1121 __ li(transition_map(), Operand(transitioned_maps->at(i))); 919 __ li(transition_map(), Operand(transitioned_maps->at(i)));
1122 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); 920 __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET);
1123 __ bind(&next_map); 921 __ bind(&next_map);
1124 } 922 }
1125 } 923 }
1126 924
1127 __ bind(&miss); 925 __ bind(&miss);
(...skipping 19 matching lines...) Expand all
1147 DCHECK(key.is(a2)); 945 DCHECK(key.is(a2));
1148 946
1149 __ UntagAndJumpIfNotSmi(t2, key, &miss); 947 __ UntagAndJumpIfNotSmi(t2, key, &miss);
1150 __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset)); 948 __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset));
1151 __ LoadFromNumberDictionary(&slow, t0, key, v0, t2, a3, t1); 949 __ LoadFromNumberDictionary(&slow, t0, key, v0, t2, a3, t1);
1152 __ Ret(); 950 __ Ret();
1153 951
1154 // Slow case, key and receiver still unmodified. 952 // Slow case, key and receiver still unmodified.
1155 __ bind(&slow); 953 __ bind(&slow);
1156 __ IncrementCounter( 954 __ IncrementCounter(
1157 masm->isolate()->counters()->keyed_load_external_array_slow(), 955 masm->isolate()->counters()->keyed_load_external_array_slow(), 1, a2, a3);
1158 1, a2, a3);
1159 956
1160 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow); 957 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
1161 958
1162 // Miss case, call the runtime. 959 // Miss case, call the runtime.
1163 __ bind(&miss); 960 __ bind(&miss);
1164 961
1165 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); 962 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
1166 } 963 }
1167 964
1168 965
1169 #undef __ 966 #undef __
1170 967 }
1171 } } // namespace v8::internal 968 } // namespace v8::internal
1172 969
1173 #endif // V8_TARGET_ARCH_MIPS 970 #endif // V8_TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « BUILD.gn ('k') | src/ic/mips/ic-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698