OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 MacroAssembler* masm, | 21 MacroAssembler* masm, |
22 Code::Flags flags, | 22 Code::Flags flags, |
23 StubCache::Table table, | 23 StubCache::Table table, |
24 Register receiver, | 24 Register receiver, |
25 Register name, | 25 Register name, |
26 // The offset is scaled by 4, based on | 26 // The offset is scaled by 4, based on |
27 // kCacheIndexShift, which is two bits | 27 // kCacheIndexShift, which is two bits |
28 Register offset) { | 28 Register offset) { |
29 // We need to scale up the pointer by 2 when the offset is scaled by less | 29 // We need to scale up the pointer by 2 when the offset is scaled by less |
30 // than the pointer size. | 30 // than the pointer size. |
31 ASSERT(kPointerSize == kInt64Size | 31 DCHECK(kPointerSize == kInt64Size |
32 ? kPointerSizeLog2 == StubCache::kCacheIndexShift + 1 | 32 ? kPointerSizeLog2 == StubCache::kCacheIndexShift + 1 |
33 : kPointerSizeLog2 == StubCache::kCacheIndexShift); | 33 : kPointerSizeLog2 == StubCache::kCacheIndexShift); |
34 ScaleFactor scale_factor = kPointerSize == kInt64Size ? times_2 : times_1; | 34 ScaleFactor scale_factor = kPointerSize == kInt64Size ? times_2 : times_1; |
35 | 35 |
36 ASSERT_EQ(3 * kPointerSize, sizeof(StubCache::Entry)); | 36 DCHECK_EQ(3 * kPointerSize, sizeof(StubCache::Entry)); |
37 // The offset register holds the entry offset times four (due to masking | 37 // The offset register holds the entry offset times four (due to masking |
38 // and shifting optimizations). | 38 // and shifting optimizations). |
39 ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); | 39 ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); |
40 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); | 40 ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); |
41 Label miss; | 41 Label miss; |
42 | 42 |
43 // Multiply by 3 because there are 3 fields per entry (name, code, map). | 43 // Multiply by 3 because there are 3 fields per entry (name, code, map). |
44 __ leap(offset, Operand(offset, offset, times_2, 0)); | 44 __ leap(offset, Operand(offset, offset, times_2, 0)); |
45 | 45 |
46 __ LoadAddress(kScratchRegister, key_offset); | 46 __ LoadAddress(kScratchRegister, key_offset); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 __ addp(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag)); | 82 __ addp(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
83 __ jmp(kScratchRegister); | 83 __ jmp(kScratchRegister); |
84 | 84 |
85 __ bind(&miss); | 85 __ bind(&miss); |
86 } | 86 } |
87 | 87 |
88 | 88 |
89 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( | 89 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
90 MacroAssembler* masm, Label* miss_label, Register receiver, | 90 MacroAssembler* masm, Label* miss_label, Register receiver, |
91 Handle<Name> name, Register scratch0, Register scratch1) { | 91 Handle<Name> name, Register scratch0, Register scratch1) { |
92 ASSERT(name->IsUniqueName()); | 92 DCHECK(name->IsUniqueName()); |
93 ASSERT(!receiver.is(scratch0)); | 93 DCHECK(!receiver.is(scratch0)); |
94 Counters* counters = masm->isolate()->counters(); | 94 Counters* counters = masm->isolate()->counters(); |
95 __ IncrementCounter(counters->negative_lookups(), 1); | 95 __ IncrementCounter(counters->negative_lookups(), 1); |
96 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 96 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
97 | 97 |
98 __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); | 98 __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); |
99 | 99 |
100 const int kInterceptorOrAccessCheckNeededMask = | 100 const int kInterceptorOrAccessCheckNeededMask = |
101 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 101 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
102 | 102 |
103 // Bail out if the receiver has a named interceptor or requires access checks. | 103 // Bail out if the receiver has a named interceptor or requires access checks. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 Register extra, | 138 Register extra, |
139 Register extra2, | 139 Register extra2, |
140 Register extra3) { | 140 Register extra3) { |
141 Isolate* isolate = masm->isolate(); | 141 Isolate* isolate = masm->isolate(); |
142 Label miss; | 142 Label miss; |
143 USE(extra); // The register extra is not used on the X64 platform. | 143 USE(extra); // The register extra is not used on the X64 platform. |
144 USE(extra2); // The register extra2 is not used on the X64 platform. | 144 USE(extra2); // The register extra2 is not used on the X64 platform. |
145 USE(extra3); // The register extra2 is not used on the X64 platform. | 145 USE(extra3); // The register extra2 is not used on the X64 platform. |
146 // Make sure that code is valid. The multiplying code relies on the | 146 // Make sure that code is valid. The multiplying code relies on the |
147 // entry size being 3 * kPointerSize. | 147 // entry size being 3 * kPointerSize. |
148 ASSERT(sizeof(Entry) == 3 * kPointerSize); | 148 DCHECK(sizeof(Entry) == 3 * kPointerSize); |
149 | 149 |
150 // Make sure the flags do not name a specific type. | 150 // Make sure the flags do not name a specific type. |
151 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 151 DCHECK(Code::ExtractTypeFromFlags(flags) == 0); |
152 | 152 |
153 // Make sure that there are no register conflicts. | 153 // Make sure that there are no register conflicts. |
154 ASSERT(!scratch.is(receiver)); | 154 DCHECK(!scratch.is(receiver)); |
155 ASSERT(!scratch.is(name)); | 155 DCHECK(!scratch.is(name)); |
156 | 156 |
157 // Check scratch register is valid, extra and extra2 are unused. | 157 // Check scratch register is valid, extra and extra2 are unused. |
158 ASSERT(!scratch.is(no_reg)); | 158 DCHECK(!scratch.is(no_reg)); |
159 ASSERT(extra2.is(no_reg)); | 159 DCHECK(extra2.is(no_reg)); |
160 ASSERT(extra3.is(no_reg)); | 160 DCHECK(extra3.is(no_reg)); |
161 | 161 |
162 Counters* counters = masm->isolate()->counters(); | 162 Counters* counters = masm->isolate()->counters(); |
163 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); | 163 __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); |
164 | 164 |
165 // Check that the receiver isn't a smi. | 165 // Check that the receiver isn't a smi. |
166 __ JumpIfSmi(receiver, &miss); | 166 __ JumpIfSmi(receiver, &miss); |
167 | 167 |
168 // Get the map of the receiver and compute the hash. | 168 // Get the map of the receiver and compute the hash. |
169 __ movl(scratch, FieldOperand(name, Name::kHashFieldOffset)); | 169 __ movl(scratch, FieldOperand(name, Name::kHashFieldOffset)); |
170 // Use only the low 32 bits of the map pointer. | 170 // Use only the low 32 bits of the map pointer. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 Register holder, | 232 Register holder, |
233 Register name, | 233 Register name, |
234 Handle<JSObject> holder_obj) { | 234 Handle<JSObject> holder_obj) { |
235 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); | 235 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0); |
236 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); | 236 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1); |
237 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); | 237 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2); |
238 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); | 238 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3); |
239 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); | 239 STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4); |
240 __ Push(name); | 240 __ Push(name); |
241 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); | 241 Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); |
242 ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); | 242 DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor)); |
243 __ Move(kScratchRegister, interceptor); | 243 __ Move(kScratchRegister, interceptor); |
244 __ Push(kScratchRegister); | 244 __ Push(kScratchRegister); |
245 __ Push(receiver); | 245 __ Push(receiver); |
246 __ Push(holder); | 246 __ Push(holder); |
247 } | 247 } |
248 | 248 |
249 | 249 |
250 static void CompileCallLoadPropertyWithInterceptor( | 250 static void CompileCallLoadPropertyWithInterceptor( |
251 MacroAssembler* masm, | 251 MacroAssembler* masm, |
252 Register receiver, | 252 Register receiver, |
253 Register holder, | 253 Register holder, |
254 Register name, | 254 Register name, |
255 Handle<JSObject> holder_obj, | 255 Handle<JSObject> holder_obj, |
256 IC::UtilityId id) { | 256 IC::UtilityId id) { |
257 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 257 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
258 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), | 258 __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()), |
259 NamedLoadHandlerCompiler::kInterceptorArgsLength); | 259 NamedLoadHandlerCompiler::kInterceptorArgsLength); |
260 } | 260 } |
261 | 261 |
262 | 262 |
263 // Generate call to api function. | 263 // Generate call to api function. |
264 void PropertyHandlerCompiler::GenerateFastApiCall( | 264 void PropertyHandlerCompiler::GenerateFastApiCall( |
265 MacroAssembler* masm, const CallOptimization& optimization, | 265 MacroAssembler* masm, const CallOptimization& optimization, |
266 Handle<Map> receiver_map, Register receiver, Register scratch_in, | 266 Handle<Map> receiver_map, Register receiver, Register scratch_in, |
267 bool is_store, int argc, Register* values) { | 267 bool is_store, int argc, Register* values) { |
268 ASSERT(optimization.is_simple_api_call()); | 268 DCHECK(optimization.is_simple_api_call()); |
269 | 269 |
270 __ PopReturnAddressTo(scratch_in); | 270 __ PopReturnAddressTo(scratch_in); |
271 // receiver | 271 // receiver |
272 __ Push(receiver); | 272 __ Push(receiver); |
273 // Write the arguments to stack frame. | 273 // Write the arguments to stack frame. |
274 for (int i = 0; i < argc; i++) { | 274 for (int i = 0; i < argc; i++) { |
275 Register arg = values[argc-1-i]; | 275 Register arg = values[argc-1-i]; |
276 ASSERT(!receiver.is(arg)); | 276 DCHECK(!receiver.is(arg)); |
277 ASSERT(!scratch_in.is(arg)); | 277 DCHECK(!scratch_in.is(arg)); |
278 __ Push(arg); | 278 __ Push(arg); |
279 } | 279 } |
280 __ PushReturnAddressFrom(scratch_in); | 280 __ PushReturnAddressFrom(scratch_in); |
281 // Stack now matches JSFunction abi. | 281 // Stack now matches JSFunction abi. |
282 | 282 |
283 // Abi for CallApiFunctionStub. | 283 // Abi for CallApiFunctionStub. |
284 Register callee = rax; | 284 Register callee = rax; |
285 Register call_data = rbx; | 285 Register call_data = rbx; |
286 Register holder = rcx; | 286 Register holder = rcx; |
287 Register api_function_address = rdx; | 287 Register api_function_address = rdx; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 333 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
334 __ TailCallStub(&stub); | 334 __ TailCallStub(&stub); |
335 } | 335 } |
336 | 336 |
337 | 337 |
338 void PropertyHandlerCompiler::GenerateCheckPropertyCell( | 338 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
339 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, | 339 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
340 Register scratch, Label* miss) { | 340 Register scratch, Label* miss) { |
341 Handle<PropertyCell> cell = | 341 Handle<PropertyCell> cell = |
342 JSGlobalObject::EnsurePropertyCell(global, name); | 342 JSGlobalObject::EnsurePropertyCell(global, name); |
343 ASSERT(cell->value()->IsTheHole()); | 343 DCHECK(cell->value()->IsTheHole()); |
344 __ Move(scratch, cell); | 344 __ Move(scratch, cell); |
345 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), | 345 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), |
346 masm->isolate()->factory()->the_hole_value()); | 346 masm->isolate()->factory()->the_hole_value()); |
347 __ j(not_equal, miss); | 347 __ j(not_equal, miss); |
348 } | 348 } |
349 | 349 |
350 | 350 |
351 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, | 351 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
352 Handle<Code> code) { | 352 Handle<Code> code) { |
353 __ jmp(code, RelocInfo::CODE_TARGET); | 353 __ jmp(code, RelocInfo::CODE_TARGET); |
(...skipping 16 matching lines...) Expand all Loading... |
370 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 370 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
371 // store is successful. | 371 // store is successful. |
372 void NamedStoreHandlerCompiler::GenerateStoreTransition( | 372 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
373 Handle<Map> transition, Handle<Name> name, Register receiver_reg, | 373 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
374 Register storage_reg, Register value_reg, Register scratch1, | 374 Register storage_reg, Register value_reg, Register scratch1, |
375 Register scratch2, Register unused, Label* miss_label, Label* slow) { | 375 Register scratch2, Register unused, Label* miss_label, Label* slow) { |
376 int descriptor = transition->LastAdded(); | 376 int descriptor = transition->LastAdded(); |
377 DescriptorArray* descriptors = transition->instance_descriptors(); | 377 DescriptorArray* descriptors = transition->instance_descriptors(); |
378 PropertyDetails details = descriptors->GetDetails(descriptor); | 378 PropertyDetails details = descriptors->GetDetails(descriptor); |
379 Representation representation = details.representation(); | 379 Representation representation = details.representation(); |
380 ASSERT(!representation.IsNone()); | 380 DCHECK(!representation.IsNone()); |
381 | 381 |
382 if (details.type() == CONSTANT) { | 382 if (details.type() == CONSTANT) { |
383 Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); | 383 Handle<Object> constant(descriptors->GetValue(descriptor), isolate()); |
384 __ Cmp(value_reg, constant); | 384 __ Cmp(value_reg, constant); |
385 __ j(not_equal, miss_label); | 385 __ j(not_equal, miss_label); |
386 } else if (representation.IsSmi()) { | 386 } else if (representation.IsSmi()) { |
387 __ JumpIfNotSmi(value_reg, miss_label); | 387 __ JumpIfNotSmi(value_reg, miss_label); |
388 } else if (representation.IsHeapObject()) { | 388 } else if (representation.IsHeapObject()) { |
389 __ JumpIfSmi(value_reg, miss_label); | 389 __ JumpIfSmi(value_reg, miss_label); |
390 HeapType* field_type = descriptors->GetFieldType(descriptor); | 390 HeapType* field_type = descriptors->GetFieldType(descriptor); |
(...skipping 23 matching lines...) Expand all Loading... |
414 __ bind(&heap_number); | 414 __ bind(&heap_number); |
415 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, | 415 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, |
416 DONT_DO_SMI_CHECK); | 416 DONT_DO_SMI_CHECK); |
417 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 417 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
418 | 418 |
419 __ bind(&do_store); | 419 __ bind(&do_store); |
420 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); | 420 __ movsd(FieldOperand(storage_reg, HeapNumber::kValueOffset), xmm0); |
421 } | 421 } |
422 | 422 |
423 // Stub never generated for objects that require access checks. | 423 // Stub never generated for objects that require access checks. |
424 ASSERT(!transition->is_access_check_needed()); | 424 DCHECK(!transition->is_access_check_needed()); |
425 | 425 |
426 // Perform map transition for the receiver if necessary. | 426 // Perform map transition for the receiver if necessary. |
427 if (details.type() == FIELD && | 427 if (details.type() == FIELD && |
428 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { | 428 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) { |
429 // The properties must be extended before we can store the value. | 429 // The properties must be extended before we can store the value. |
430 // We jump to a runtime call that extends the properties array. | 430 // We jump to a runtime call that extends the properties array. |
431 __ PopReturnAddressTo(scratch1); | 431 __ PopReturnAddressTo(scratch1); |
432 __ Push(receiver_reg); | 432 __ Push(receiver_reg); |
433 __ Push(transition); | 433 __ Push(transition); |
434 __ Push(value_reg); | 434 __ Push(value_reg); |
(...skipping 12 matching lines...) Expand all Loading... |
447 // Update the write barrier for the map field. | 447 // Update the write barrier for the map field. |
448 __ RecordWriteField(receiver_reg, | 448 __ RecordWriteField(receiver_reg, |
449 HeapObject::kMapOffset, | 449 HeapObject::kMapOffset, |
450 scratch1, | 450 scratch1, |
451 scratch2, | 451 scratch2, |
452 kDontSaveFPRegs, | 452 kDontSaveFPRegs, |
453 OMIT_REMEMBERED_SET, | 453 OMIT_REMEMBERED_SET, |
454 OMIT_SMI_CHECK); | 454 OMIT_SMI_CHECK); |
455 | 455 |
456 if (details.type() == CONSTANT) { | 456 if (details.type() == CONSTANT) { |
457 ASSERT(value_reg.is(rax)); | 457 DCHECK(value_reg.is(rax)); |
458 __ ret(0); | 458 __ ret(0); |
459 return; | 459 return; |
460 } | 460 } |
461 | 461 |
462 int index = transition->instance_descriptors()->GetFieldIndex( | 462 int index = transition->instance_descriptors()->GetFieldIndex( |
463 transition->LastAdded()); | 463 transition->LastAdded()); |
464 | 464 |
465 // Adjust for the number of properties stored in the object. Even in the | 465 // Adjust for the number of properties stored in the object. Even in the |
466 // face of a transition we can use the old map here because the size of the | 466 // face of a transition we can use the old map here because the size of the |
467 // object and the number of in-object properties is not going to change. | 467 // object and the number of in-object properties is not going to change. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
504 if (!representation.IsDouble()) { | 504 if (!representation.IsDouble()) { |
505 __ movp(storage_reg, value_reg); | 505 __ movp(storage_reg, value_reg); |
506 } | 506 } |
507 __ RecordWriteField( | 507 __ RecordWriteField( |
508 scratch1, offset, storage_reg, receiver_reg, kDontSaveFPRegs, | 508 scratch1, offset, storage_reg, receiver_reg, kDontSaveFPRegs, |
509 EMIT_REMEMBERED_SET, smi_check); | 509 EMIT_REMEMBERED_SET, smi_check); |
510 } | 510 } |
511 } | 511 } |
512 | 512 |
513 // Return the value (register rax). | 513 // Return the value (register rax). |
514 ASSERT(value_reg.is(rax)); | 514 DCHECK(value_reg.is(rax)); |
515 __ ret(0); | 515 __ ret(0); |
516 } | 516 } |
517 | 517 |
518 | 518 |
519 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 519 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
520 // but may be destroyed if store is successful. | 520 // but may be destroyed if store is successful. |
521 void NamedStoreHandlerCompiler::GenerateStoreField( | 521 void NamedStoreHandlerCompiler::GenerateStoreField( |
522 Handle<JSObject> object, LookupResult* lookup, Register receiver_reg, | 522 Handle<JSObject> object, LookupResult* lookup, Register receiver_reg, |
523 Register name_reg, Register value_reg, Register scratch1, Register scratch2, | 523 Register name_reg, Register value_reg, Register scratch1, Register scratch2, |
524 Label* miss_label) { | 524 Label* miss_label) { |
525 // Stub never generated for objects that require access checks. | 525 // Stub never generated for objects that require access checks. |
526 ASSERT(!object->IsAccessCheckNeeded()); | 526 DCHECK(!object->IsAccessCheckNeeded()); |
527 ASSERT(!object->IsJSGlobalProxy()); | 527 DCHECK(!object->IsJSGlobalProxy()); |
528 | 528 |
529 FieldIndex index = lookup->GetFieldIndex(); | 529 FieldIndex index = lookup->GetFieldIndex(); |
530 | 530 |
531 Representation representation = lookup->representation(); | 531 Representation representation = lookup->representation(); |
532 ASSERT(!representation.IsNone()); | 532 DCHECK(!representation.IsNone()); |
533 if (representation.IsSmi()) { | 533 if (representation.IsSmi()) { |
534 __ JumpIfNotSmi(value_reg, miss_label); | 534 __ JumpIfNotSmi(value_reg, miss_label); |
535 } else if (representation.IsHeapObject()) { | 535 } else if (representation.IsHeapObject()) { |
536 __ JumpIfSmi(value_reg, miss_label); | 536 __ JumpIfSmi(value_reg, miss_label); |
537 HeapType* field_type = lookup->GetFieldType(); | 537 HeapType* field_type = lookup->GetFieldType(); |
538 HeapType::Iterator<Map> it = field_type->Classes(); | 538 HeapType::Iterator<Map> it = field_type->Classes(); |
539 if (!it.Done()) { | 539 if (!it.Done()) { |
540 Label do_store; | 540 Label do_store; |
541 while (true) { | 541 while (true) { |
542 __ CompareMap(value_reg, it.Current()); | 542 __ CompareMap(value_reg, it.Current()); |
(...skipping 23 matching lines...) Expand all Loading... |
566 __ Cvtlsi2sd(xmm0, scratch2); | 566 __ Cvtlsi2sd(xmm0, scratch2); |
567 __ jmp(&do_store); | 567 __ jmp(&do_store); |
568 | 568 |
569 __ bind(&heap_number); | 569 __ bind(&heap_number); |
570 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, | 570 __ CheckMap(value_reg, isolate()->factory()->heap_number_map(), miss_label, |
571 DONT_DO_SMI_CHECK); | 571 DONT_DO_SMI_CHECK); |
572 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); | 572 __ movsd(xmm0, FieldOperand(value_reg, HeapNumber::kValueOffset)); |
573 __ bind(&do_store); | 573 __ bind(&do_store); |
574 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); | 574 __ movsd(FieldOperand(scratch1, HeapNumber::kValueOffset), xmm0); |
575 // Return the value (register rax). | 575 // Return the value (register rax). |
576 ASSERT(value_reg.is(rax)); | 576 DCHECK(value_reg.is(rax)); |
577 __ ret(0); | 577 __ ret(0); |
578 return; | 578 return; |
579 } | 579 } |
580 | 580 |
581 // TODO(verwaest): Share this code as a code stub. | 581 // TODO(verwaest): Share this code as a code stub. |
582 SmiCheck smi_check = representation.IsTagged() | 582 SmiCheck smi_check = representation.IsTagged() |
583 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; | 583 ? INLINE_SMI_CHECK : OMIT_SMI_CHECK; |
584 if (index.is_inobject()) { | 584 if (index.is_inobject()) { |
585 // Set the property straight into the object. | 585 // Set the property straight into the object. |
586 __ movp(FieldOperand(receiver_reg, index.offset()), value_reg); | 586 __ movp(FieldOperand(receiver_reg, index.offset()), value_reg); |
(...skipping 16 matching lines...) Expand all Loading... |
603 // Update the write barrier for the array address. | 603 // Update the write barrier for the array address. |
604 // Pass the value being stored in the now unused name_reg. | 604 // Pass the value being stored in the now unused name_reg. |
605 __ movp(name_reg, value_reg); | 605 __ movp(name_reg, value_reg); |
606 __ RecordWriteField( | 606 __ RecordWriteField( |
607 scratch1, index.offset(), name_reg, receiver_reg, kDontSaveFPRegs, | 607 scratch1, index.offset(), name_reg, receiver_reg, kDontSaveFPRegs, |
608 EMIT_REMEMBERED_SET, smi_check); | 608 EMIT_REMEMBERED_SET, smi_check); |
609 } | 609 } |
610 } | 610 } |
611 | 611 |
612 // Return the value (register rax). | 612 // Return the value (register rax). |
613 ASSERT(value_reg.is(rax)); | 613 DCHECK(value_reg.is(rax)); |
614 __ ret(0); | 614 __ ret(0); |
615 } | 615 } |
616 | 616 |
617 | 617 |
618 Register PropertyHandlerCompiler::CheckPrototypes( | 618 Register PropertyHandlerCompiler::CheckPrototypes( |
619 Register object_reg, Register holder_reg, Register scratch1, | 619 Register object_reg, Register holder_reg, Register scratch1, |
620 Register scratch2, Handle<Name> name, Label* miss, | 620 Register scratch2, Handle<Name> name, Label* miss, |
621 PrototypeCheckType check) { | 621 PrototypeCheckType check) { |
622 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); | 622 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); |
623 | 623 |
624 // Make sure there's no overlap between holder and object registers. | 624 // Make sure there's no overlap between holder and object registers. |
625 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 625 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
626 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 626 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
627 && !scratch2.is(scratch1)); | 627 && !scratch2.is(scratch1)); |
628 | 628 |
629 // Keep track of the current object in register reg. On the first | 629 // Keep track of the current object in register reg. On the first |
630 // iteration, reg is an alias for object_reg, on later iterations, | 630 // iteration, reg is an alias for object_reg, on later iterations, |
631 // it is an alias for holder_reg. | 631 // it is an alias for holder_reg. |
632 Register reg = object_reg; | 632 Register reg = object_reg; |
633 int depth = 0; | 633 int depth = 0; |
634 | 634 |
635 Handle<JSObject> current = Handle<JSObject>::null(); | 635 Handle<JSObject> current = Handle<JSObject>::null(); |
636 if (type()->IsConstant()) { | 636 if (type()->IsConstant()) { |
637 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); | 637 current = Handle<JSObject>::cast(type()->AsConstant()->Value()); |
638 } | 638 } |
639 Handle<JSObject> prototype = Handle<JSObject>::null(); | 639 Handle<JSObject> prototype = Handle<JSObject>::null(); |
640 Handle<Map> current_map = receiver_map; | 640 Handle<Map> current_map = receiver_map; |
641 Handle<Map> holder_map(holder()->map()); | 641 Handle<Map> holder_map(holder()->map()); |
642 // Traverse the prototype chain and check the maps in the prototype chain for | 642 // Traverse the prototype chain and check the maps in the prototype chain for |
643 // fast and global objects or do negative lookup for normal objects. | 643 // fast and global objects or do negative lookup for normal objects. |
644 while (!current_map.is_identical_to(holder_map)) { | 644 while (!current_map.is_identical_to(holder_map)) { |
645 ++depth; | 645 ++depth; |
646 | 646 |
647 // Only global objects and objects that do not require access | 647 // Only global objects and objects that do not require access |
648 // checks are allowed in stubs. | 648 // checks are allowed in stubs. |
649 ASSERT(current_map->IsJSGlobalProxyMap() || | 649 DCHECK(current_map->IsJSGlobalProxyMap() || |
650 !current_map->is_access_check_needed()); | 650 !current_map->is_access_check_needed()); |
651 | 651 |
652 prototype = handle(JSObject::cast(current_map->prototype())); | 652 prototype = handle(JSObject::cast(current_map->prototype())); |
653 if (current_map->is_dictionary_map() && | 653 if (current_map->is_dictionary_map() && |
654 !current_map->IsJSGlobalObjectMap() && | 654 !current_map->IsJSGlobalObjectMap() && |
655 !current_map->IsJSGlobalProxyMap()) { | 655 !current_map->IsJSGlobalProxyMap()) { |
656 if (!name->IsUniqueName()) { | 656 if (!name->IsUniqueName()) { |
657 ASSERT(name->IsString()); | 657 DCHECK(name->IsString()); |
658 name = factory()->InternalizeString(Handle<String>::cast(name)); | 658 name = factory()->InternalizeString(Handle<String>::cast(name)); |
659 } | 659 } |
660 ASSERT(current.is_null() || | 660 DCHECK(current.is_null() || |
661 current->property_dictionary()->FindEntry(name) == | 661 current->property_dictionary()->FindEntry(name) == |
662 NameDictionary::kNotFound); | 662 NameDictionary::kNotFound); |
663 | 663 |
664 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, | 664 GenerateDictionaryNegativeLookup(masm(), miss, reg, name, |
665 scratch1, scratch2); | 665 scratch1, scratch2); |
666 | 666 |
667 __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); | 667 __ movp(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); |
668 reg = holder_reg; // From now on the object will be in holder_reg. | 668 reg = holder_reg; // From now on the object will be in holder_reg. |
669 __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); | 669 __ movp(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); |
670 } else { | 670 } else { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
708 | 708 |
709 // Log the check depth. | 709 // Log the check depth. |
710 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); | 710 LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); |
711 | 711 |
712 if (depth != 0 || check == CHECK_ALL_MAPS) { | 712 if (depth != 0 || check == CHECK_ALL_MAPS) { |
713 // Check the holder map. | 713 // Check the holder map. |
714 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); | 714 __ CheckMap(reg, current_map, miss, DONT_DO_SMI_CHECK); |
715 } | 715 } |
716 | 716 |
717 // Perform security check for access to the global object. | 717 // Perform security check for access to the global object. |
718 ASSERT(current_map->IsJSGlobalProxyMap() || | 718 DCHECK(current_map->IsJSGlobalProxyMap() || |
719 !current_map->is_access_check_needed()); | 719 !current_map->is_access_check_needed()); |
720 if (current_map->IsJSGlobalProxyMap()) { | 720 if (current_map->IsJSGlobalProxyMap()) { |
721 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 721 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
722 } | 722 } |
723 | 723 |
724 // Return the register containing the holder. | 724 // Return the register containing the holder. |
725 return reg; | 725 return reg; |
726 } | 726 } |
727 | 727 |
728 | 728 |
(...skipping 20 matching lines...) Expand all Loading... |
749 | 749 |
750 | 750 |
751 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, | 751 Register NamedLoadHandlerCompiler::CallbackFrontend(Register object_reg, |
752 Handle<Name> name, | 752 Handle<Name> name, |
753 Handle<Object> callback) { | 753 Handle<Object> callback) { |
754 Label miss; | 754 Label miss; |
755 | 755 |
756 Register reg = FrontendHeader(object_reg, name, &miss); | 756 Register reg = FrontendHeader(object_reg, name, &miss); |
757 | 757 |
758 if (!holder()->HasFastProperties()) { | 758 if (!holder()->HasFastProperties()) { |
759 ASSERT(!holder()->IsGlobalObject()); | 759 DCHECK(!holder()->IsGlobalObject()); |
760 ASSERT(!reg.is(scratch2())); | 760 DCHECK(!reg.is(scratch2())); |
761 ASSERT(!reg.is(scratch3())); | 761 DCHECK(!reg.is(scratch3())); |
762 ASSERT(!reg.is(scratch4())); | 762 DCHECK(!reg.is(scratch4())); |
763 | 763 |
764 // Load the properties dictionary. | 764 // Load the properties dictionary. |
765 Register dictionary = scratch4(); | 765 Register dictionary = scratch4(); |
766 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 766 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
767 | 767 |
768 // Probe the dictionary. | 768 // Probe the dictionary. |
769 Label probe_done; | 769 Label probe_done; |
770 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), | 770 NameDictionaryLookupStub::GeneratePositiveLookup(masm(), |
771 &miss, | 771 &miss, |
772 &probe_done, | 772 &probe_done, |
(...skipping 27 matching lines...) Expand all Loading... |
800 Register reg, FieldIndex field, Representation representation) { | 800 Register reg, FieldIndex field, Representation representation) { |
801 if (!reg.is(receiver())) __ movp(receiver(), reg); | 801 if (!reg.is(receiver())) __ movp(receiver(), reg); |
802 LoadFieldStub stub(isolate(), field); | 802 LoadFieldStub stub(isolate(), field); |
803 GenerateTailCall(masm(), stub.GetCode()); | 803 GenerateTailCall(masm(), stub.GetCode()); |
804 } | 804 } |
805 | 805 |
806 | 806 |
807 void NamedLoadHandlerCompiler::GenerateLoadCallback( | 807 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
808 Register reg, Handle<ExecutableAccessorInfo> callback) { | 808 Register reg, Handle<ExecutableAccessorInfo> callback) { |
809 // Insert additional parameters into the stack frame above return address. | 809 // Insert additional parameters into the stack frame above return address. |
810 ASSERT(!scratch4().is(reg)); | 810 DCHECK(!scratch4().is(reg)); |
811 __ PopReturnAddressTo(scratch4()); | 811 __ PopReturnAddressTo(scratch4()); |
812 | 812 |
813 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 813 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
814 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 814 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
815 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 815 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
816 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 816 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
817 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 817 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
818 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 818 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
819 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); | 819 STATIC_ASSERT(PropertyCallbackArguments::kArgsLength == 6); |
820 __ Push(receiver()); // receiver | 820 __ Push(receiver()); // receiver |
821 if (heap()->InNewSpace(callback->data())) { | 821 if (heap()->InNewSpace(callback->data())) { |
822 ASSERT(!scratch2().is(reg)); | 822 DCHECK(!scratch2().is(reg)); |
823 __ Move(scratch2(), callback); | 823 __ Move(scratch2(), callback); |
824 __ Push(FieldOperand(scratch2(), | 824 __ Push(FieldOperand(scratch2(), |
825 ExecutableAccessorInfo::kDataOffset)); // data | 825 ExecutableAccessorInfo::kDataOffset)); // data |
826 } else { | 826 } else { |
827 __ Push(Handle<Object>(callback->data(), isolate())); | 827 __ Push(Handle<Object>(callback->data(), isolate())); |
828 } | 828 } |
829 ASSERT(!kScratchRegister.is(reg)); | 829 DCHECK(!kScratchRegister.is(reg)); |
830 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); | 830 __ LoadRoot(kScratchRegister, Heap::kUndefinedValueRootIndex); |
831 __ Push(kScratchRegister); // return value | 831 __ Push(kScratchRegister); // return value |
832 __ Push(kScratchRegister); // return value default | 832 __ Push(kScratchRegister); // return value default |
833 __ PushAddress(ExternalReference::isolate_address(isolate())); | 833 __ PushAddress(ExternalReference::isolate_address(isolate())); |
834 __ Push(reg); // holder | 834 __ Push(reg); // holder |
835 __ Push(name()); // name | 835 __ Push(name()); // name |
836 // Save a pointer to where we pushed the arguments pointer. This will be | 836 // Save a pointer to where we pushed the arguments pointer. This will be |
837 // passed as the const PropertyAccessorInfo& to the C++ callback. | 837 // passed as the const PropertyAccessorInfo& to the C++ callback. |
838 | 838 |
839 __ PushReturnAddressFrom(scratch4()); | 839 __ PushReturnAddressFrom(scratch4()); |
(...skipping 11 matching lines...) Expand all Loading... |
851 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { | 851 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
852 // Return the constant value. | 852 // Return the constant value. |
853 __ Move(rax, value); | 853 __ Move(rax, value); |
854 __ ret(0); | 854 __ ret(0); |
855 } | 855 } |
856 | 856 |
857 | 857 |
858 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, | 858 void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg, |
859 LookupResult* lookup, | 859 LookupResult* lookup, |
860 Handle<Name> name) { | 860 Handle<Name> name) { |
861 ASSERT(holder()->HasNamedInterceptor()); | 861 DCHECK(holder()->HasNamedInterceptor()); |
862 ASSERT(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); | 862 DCHECK(!holder()->GetNamedInterceptor()->getter()->IsUndefined()); |
863 | 863 |
864 // So far the most popular follow ups for interceptor loads are FIELD | 864 // So far the most popular follow ups for interceptor loads are FIELD |
865 // and CALLBACKS, so inline only them, other cases may be added | 865 // and CALLBACKS, so inline only them, other cases may be added |
866 // later. | 866 // later. |
867 bool compile_followup_inline = false; | 867 bool compile_followup_inline = false; |
868 if (lookup->IsFound() && lookup->IsCacheable()) { | 868 if (lookup->IsFound() && lookup->IsCacheable()) { |
869 if (lookup->IsField()) { | 869 if (lookup->IsField()) { |
870 compile_followup_inline = true; | 870 compile_followup_inline = true; |
871 } else if (lookup->type() == CALLBACKS && | 871 } else if (lookup->type() == CALLBACKS && |
872 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { | 872 lookup->GetCallbackObject()->IsExecutableAccessorInfo()) { |
873 Handle<ExecutableAccessorInfo> callback( | 873 Handle<ExecutableAccessorInfo> callback( |
874 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 874 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
875 compile_followup_inline = | 875 compile_followup_inline = |
876 callback->getter() != NULL && | 876 callback->getter() != NULL && |
877 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, | 877 ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), callback, |
878 type()); | 878 type()); |
879 } | 879 } |
880 } | 880 } |
881 | 881 |
882 if (compile_followup_inline) { | 882 if (compile_followup_inline) { |
883 // Compile the interceptor call, followed by inline code to load the | 883 // Compile the interceptor call, followed by inline code to load the |
884 // property from further up the prototype chain if the call fails. | 884 // property from further up the prototype chain if the call fails. |
885 // Check that the maps haven't changed. | 885 // Check that the maps haven't changed. |
886 ASSERT(holder_reg.is(receiver()) || holder_reg.is(scratch1())); | 886 DCHECK(holder_reg.is(receiver()) || holder_reg.is(scratch1())); |
887 | 887 |
888 // Preserve the receiver register explicitly whenever it is different from | 888 // Preserve the receiver register explicitly whenever it is different from |
889 // the holder and it is needed should the interceptor return without any | 889 // the holder and it is needed should the interceptor return without any |
890 // result. The CALLBACKS case needs the receiver to be passed into C++ code, | 890 // result. The CALLBACKS case needs the receiver to be passed into C++ code, |
891 // the FIELD case might cause a miss during the prototype check. | 891 // the FIELD case might cause a miss during the prototype check. |
892 bool must_perfrom_prototype_check = *holder() != lookup->holder(); | 892 bool must_perfrom_prototype_check = *holder() != lookup->holder(); |
893 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && | 893 bool must_preserve_receiver_reg = !receiver().is(holder_reg) && |
894 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); | 894 (lookup->type() == CALLBACKS || must_perfrom_prototype_check); |
895 | 895 |
896 // Save necessary data before invoking an interceptor. | 896 // Save necessary data before invoking an interceptor. |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1075 Register name = LoadIC::NameRegister(); | 1075 Register name = LoadIC::NameRegister(); |
1076 static Register registers[] = { receiver, name, rax, rbx, rdi, r8 }; | 1076 static Register registers[] = { receiver, name, rax, rbx, rdi, r8 }; |
1077 return registers; | 1077 return registers; |
1078 } | 1078 } |
1079 | 1079 |
1080 | 1080 |
1081 Register* PropertyAccessCompiler::store_calling_convention() { | 1081 Register* PropertyAccessCompiler::store_calling_convention() { |
1082 // receiver, name, scratch1, scratch2, scratch3. | 1082 // receiver, name, scratch1, scratch2, scratch3. |
1083 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1083 Register receiver = KeyedStoreIC::ReceiverRegister(); |
1084 Register name = KeyedStoreIC::NameRegister(); | 1084 Register name = KeyedStoreIC::NameRegister(); |
1085 ASSERT(rbx.is(KeyedStoreIC::MapRegister())); | 1085 DCHECK(rbx.is(KeyedStoreIC::MapRegister())); |
1086 static Register registers[] = { receiver, name, rbx, rdi, r8 }; | 1086 static Register registers[] = { receiver, name, rbx, rdi, r8 }; |
1087 return registers; | 1087 return registers; |
1088 } | 1088 } |
1089 | 1089 |
1090 | 1090 |
1091 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } | 1091 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
1092 | 1092 |
1093 | 1093 |
1094 #undef __ | 1094 #undef __ |
1095 #define __ ACCESS_MASM(masm) | 1095 #define __ ACCESS_MASM(masm) |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1183 __ j(not_equal, &miss); | 1183 __ j(not_equal, &miss); |
1184 } | 1184 } |
1185 } | 1185 } |
1186 | 1186 |
1187 Label number_case; | 1187 Label number_case; |
1188 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1188 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
1189 __ JumpIfSmi(receiver(), smi_target); | 1189 __ JumpIfSmi(receiver(), smi_target); |
1190 | 1190 |
1191 // Polymorphic keyed stores may use the map register | 1191 // Polymorphic keyed stores may use the map register |
1192 Register map_reg = scratch1(); | 1192 Register map_reg = scratch1(); |
1193 ASSERT(kind() != Code::KEYED_STORE_IC || | 1193 DCHECK(kind() != Code::KEYED_STORE_IC || |
1194 map_reg.is(KeyedStoreIC::MapRegister())); | 1194 map_reg.is(KeyedStoreIC::MapRegister())); |
1195 __ movp(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); | 1195 __ movp(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset)); |
1196 int receiver_count = types->length(); | 1196 int receiver_count = types->length(); |
1197 int number_of_handled_maps = 0; | 1197 int number_of_handled_maps = 0; |
1198 for (int current = 0; current < receiver_count; ++current) { | 1198 for (int current = 0; current < receiver_count; ++current) { |
1199 Handle<HeapType> type = types->at(current); | 1199 Handle<HeapType> type = types->at(current); |
1200 Handle<Map> map = IC::TypeToMap(*type, isolate()); | 1200 Handle<Map> map = IC::TypeToMap(*type, isolate()); |
1201 if (!map->is_deprecated()) { | 1201 if (!map->is_deprecated()) { |
1202 number_of_handled_maps++; | 1202 number_of_handled_maps++; |
1203 // Check map and tail call if there's a match | 1203 // Check map and tail call if there's a match |
1204 __ Cmp(map_reg, map); | 1204 __ Cmp(map_reg, map); |
1205 if (type->Is(HeapType::Number())) { | 1205 if (type->Is(HeapType::Number())) { |
1206 ASSERT(!number_case.is_unused()); | 1206 DCHECK(!number_case.is_unused()); |
1207 __ bind(&number_case); | 1207 __ bind(&number_case); |
1208 } | 1208 } |
1209 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); | 1209 __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET); |
1210 } | 1210 } |
1211 } | 1211 } |
1212 ASSERT(number_of_handled_maps > 0); | 1212 DCHECK(number_of_handled_maps > 0); |
1213 | 1213 |
1214 __ bind(&miss); | 1214 __ bind(&miss); |
1215 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1215 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1216 | 1216 |
1217 // Return the generated code. | 1217 // Return the generated code. |
1218 InlineCacheState state = | 1218 InlineCacheState state = |
1219 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 1219 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
1220 return GetCode(kind(), type, name, state); | 1220 return GetCode(kind(), type, name, state); |
1221 } | 1221 } |
1222 | 1222 |
1223 | 1223 |
1224 #undef __ | 1224 #undef __ |
1225 #define __ ACCESS_MASM(masm) | 1225 #define __ ACCESS_MASM(masm) |
1226 | 1226 |
1227 | 1227 |
1228 void ElementHandlerCompiler::GenerateLoadDictionaryElement( | 1228 void ElementHandlerCompiler::GenerateLoadDictionaryElement( |
1229 MacroAssembler* masm) { | 1229 MacroAssembler* masm) { |
1230 // ----------- S t a t e ------------- | 1230 // ----------- S t a t e ------------- |
1231 // -- rcx : key | 1231 // -- rcx : key |
1232 // -- rdx : receiver | 1232 // -- rdx : receiver |
1233 // -- rsp[0] : return address | 1233 // -- rsp[0] : return address |
1234 // ----------------------------------- | 1234 // ----------------------------------- |
1235 ASSERT(rdx.is(LoadIC::ReceiverRegister())); | 1235 DCHECK(rdx.is(LoadIC::ReceiverRegister())); |
1236 ASSERT(rcx.is(LoadIC::NameRegister())); | 1236 DCHECK(rcx.is(LoadIC::NameRegister())); |
1237 Label slow, miss; | 1237 Label slow, miss; |
1238 | 1238 |
1239 // This stub is meant to be tail-jumped to, the receiver must already | 1239 // This stub is meant to be tail-jumped to, the receiver must already |
1240 // have been verified by the caller to not be a smi. | 1240 // have been verified by the caller to not be a smi. |
1241 | 1241 |
1242 __ JumpIfNotSmi(rcx, &miss); | 1242 __ JumpIfNotSmi(rcx, &miss); |
1243 __ SmiToInteger32(rbx, rcx); | 1243 __ SmiToInteger32(rbx, rcx); |
1244 __ movp(rax, FieldOperand(rdx, JSObject::kElementsOffset)); | 1244 __ movp(rax, FieldOperand(rdx, JSObject::kElementsOffset)); |
1245 | 1245 |
1246 // Check whether the elements is a number dictionary. | 1246 // Check whether the elements is a number dictionary. |
(...skipping 20 matching lines...) Expand all Loading... |
1267 // ----------------------------------- | 1267 // ----------------------------------- |
1268 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1268 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1269 } | 1269 } |
1270 | 1270 |
1271 | 1271 |
1272 #undef __ | 1272 #undef __ |
1273 | 1273 |
1274 } } // namespace v8::internal | 1274 } } // namespace v8::internal |
1275 | 1275 |
1276 #endif // V8_TARGET_ARCH_X64 | 1276 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |