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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 #endif | 79 #endif |
80 | 80 |
81 // Jump to the first instruction in the code stub. | 81 // Jump to the first instruction in the code stub. |
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 StubCompiler::GenerateDictionaryNegativeLookup(MacroAssembler* masm, | 89 void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( |
90 Label* miss_label, | 90 MacroAssembler* masm, Label* miss_label, Register receiver, |
91 Register receiver, | 91 Handle<Name> name, Register scratch0, Register scratch1) { |
92 Handle<Name> name, | |
93 Register scratch0, | |
94 Register scratch1) { | |
95 ASSERT(name->IsUniqueName()); | 92 ASSERT(name->IsUniqueName()); |
96 ASSERT(!receiver.is(scratch0)); | 93 ASSERT(!receiver.is(scratch0)); |
97 Counters* counters = masm->isolate()->counters(); | 94 Counters* counters = masm->isolate()->counters(); |
98 __ IncrementCounter(counters->negative_lookups(), 1); | 95 __ IncrementCounter(counters->negative_lookups(), 1); |
99 __ IncrementCounter(counters->negative_lookups_miss(), 1); | 96 __ IncrementCounter(counters->negative_lookups_miss(), 1); |
100 | 97 |
101 __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); | 98 __ movp(scratch0, FieldOperand(receiver, HeapObject::kMapOffset)); |
102 | 99 |
103 const int kInterceptorOrAccessCheckNeededMask = | 100 const int kInterceptorOrAccessCheckNeededMask = |
104 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); | 101 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 // Probe the secondary table. | 189 // Probe the secondary table. |
193 ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch); | 190 ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch); |
194 | 191 |
195 // Cache miss: Fall-through and let caller handle the miss by | 192 // Cache miss: Fall-through and let caller handle the miss by |
196 // entering the runtime system. | 193 // entering the runtime system. |
197 __ bind(&miss); | 194 __ bind(&miss); |
198 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 195 __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
199 } | 196 } |
200 | 197 |
201 | 198 |
202 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, | 199 void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype( |
203 int index, | 200 MacroAssembler* masm, int index, Register prototype, Label* miss) { |
204 Register prototype) { | |
205 // Load the global or builtins object from the current context. | |
206 __ movp(prototype, | |
207 Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
208 // Load the native context from the global or builtins object. | |
209 __ movp(prototype, | |
210 FieldOperand(prototype, GlobalObject::kNativeContextOffset)); | |
211 // Load the function from the native context. | |
212 __ movp(prototype, Operand(prototype, Context::SlotOffset(index))); | |
213 // Load the initial map. The global functions all have initial maps. | |
214 __ movp(prototype, | |
215 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); | |
216 // Load the prototype from the initial map. | |
217 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | |
218 } | |
219 | |
220 | |
221 void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( | |
222 MacroAssembler* masm, | |
223 int index, | |
224 Register prototype, | |
225 Label* miss) { | |
226 Isolate* isolate = masm->isolate(); | 201 Isolate* isolate = masm->isolate(); |
227 // Get the global function with the given index. | 202 // Get the global function with the given index. |
228 Handle<JSFunction> function( | 203 Handle<JSFunction> function( |
229 JSFunction::cast(isolate->native_context()->get(index))); | 204 JSFunction::cast(isolate->native_context()->get(index))); |
230 | 205 |
231 // Check we're still in the same context. | 206 // Check we're still in the same context. |
232 Register scratch = prototype; | 207 Register scratch = prototype; |
233 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); | 208 const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
234 __ movp(scratch, Operand(rsi, offset)); | 209 __ movp(scratch, Operand(rsi, offset)); |
235 __ movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); | 210 __ movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset)); |
236 __ Cmp(Operand(scratch, Context::SlotOffset(index)), function); | 211 __ Cmp(Operand(scratch, Context::SlotOffset(index)), function); |
237 __ j(not_equal, miss); | 212 __ j(not_equal, miss); |
238 | 213 |
239 // Load its initial map. The global functions all have initial maps. | 214 // Load its initial map. The global functions all have initial maps. |
240 __ Move(prototype, Handle<Map>(function->initial_map())); | 215 __ Move(prototype, Handle<Map>(function->initial_map())); |
241 // Load the prototype from the initial map. | 216 // Load the prototype from the initial map. |
242 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); | 217 __ movp(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); |
243 } | 218 } |
244 | 219 |
245 | 220 |
246 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, | 221 void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( |
247 Register receiver, | 222 MacroAssembler* masm, Register receiver, Register result, Register scratch, |
248 Register scratch, | 223 Label* miss_label) { |
249 Label* miss_label) { | |
250 // Check that the receiver isn't a smi. | |
251 __ JumpIfSmi(receiver, miss_label); | |
252 | |
253 // Check that the object is a JS array. | |
254 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); | |
255 __ j(not_equal, miss_label); | |
256 | |
257 // Load length directly from the JS array. | |
258 __ movp(rax, FieldOperand(receiver, JSArray::kLengthOffset)); | |
259 __ ret(0); | |
260 } | |
261 | |
262 | |
263 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, | |
264 Register receiver, | |
265 Register result, | |
266 Register scratch, | |
267 Label* miss_label) { | |
268 __ TryGetFunctionPrototype(receiver, result, miss_label); | 224 __ TryGetFunctionPrototype(receiver, result, miss_label); |
269 if (!result.is(rax)) __ movp(rax, result); | 225 if (!result.is(rax)) __ movp(rax, result); |
270 __ ret(0); | 226 __ ret(0); |
271 } | 227 } |
272 | 228 |
273 | 229 |
274 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, | |
275 Register dst, | |
276 Register src, | |
277 bool inobject, | |
278 int index, | |
279 Representation representation) { | |
280 ASSERT(!representation.IsDouble()); | |
281 int offset = index * kPointerSize; | |
282 if (!inobject) { | |
283 // Calculate the offset into the properties array. | |
284 offset = offset + FixedArray::kHeaderSize; | |
285 __ movp(dst, FieldOperand(src, JSObject::kPropertiesOffset)); | |
286 src = dst; | |
287 } | |
288 __ movp(dst, FieldOperand(src, offset)); | |
289 } | |
290 | |
291 | |
292 static void PushInterceptorArguments(MacroAssembler* masm, | 230 static void PushInterceptorArguments(MacroAssembler* masm, |
293 Register receiver, | 231 Register receiver, |
294 Register holder, | 232 Register holder, |
295 Register name, | 233 Register name, |
296 Handle<JSObject> holder_obj) { | 234 Handle<JSObject> holder_obj) { |
297 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); | 235 STATIC_ASSERT(StubCache::kInterceptorArgsNameIndex == 0); |
298 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); | 236 STATIC_ASSERT(StubCache::kInterceptorArgsInfoIndex == 1); |
299 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); | 237 STATIC_ASSERT(StubCache::kInterceptorArgsThisIndex == 2); |
300 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); | 238 STATIC_ASSERT(StubCache::kInterceptorArgsHolderIndex == 3); |
301 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); | 239 STATIC_ASSERT(StubCache::kInterceptorArgsLength == 4); |
(...skipping 15 matching lines...) Expand all Loading... |
317 Handle<JSObject> holder_obj, | 255 Handle<JSObject> holder_obj, |
318 IC::UtilityId id) { | 256 IC::UtilityId id) { |
319 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); | 257 PushInterceptorArguments(masm, receiver, holder, name, holder_obj); |
320 __ CallExternalReference( | 258 __ CallExternalReference( |
321 ExternalReference(IC_Utility(id), masm->isolate()), | 259 ExternalReference(IC_Utility(id), masm->isolate()), |
322 StubCache::kInterceptorArgsLength); | 260 StubCache::kInterceptorArgsLength); |
323 } | 261 } |
324 | 262 |
325 | 263 |
326 // Generate call to api function. | 264 // Generate call to api function. |
327 void StubCompiler::GenerateFastApiCall(MacroAssembler* masm, | 265 void PropertyHandlerCompiler::GenerateFastApiCall( |
328 const CallOptimization& optimization, | 266 MacroAssembler* masm, const CallOptimization& optimization, |
329 Handle<Map> receiver_map, | 267 Handle<Map> receiver_map, Register receiver, Register scratch_in, |
330 Register receiver, | 268 bool is_store, int argc, Register* values) { |
331 Register scratch_in, | |
332 bool is_store, | |
333 int argc, | |
334 Register* values) { | |
335 ASSERT(optimization.is_simple_api_call()); | 269 ASSERT(optimization.is_simple_api_call()); |
336 | 270 |
337 __ PopReturnAddressTo(scratch_in); | 271 __ PopReturnAddressTo(scratch_in); |
338 // receiver | 272 // receiver |
339 __ Push(receiver); | 273 __ Push(receiver); |
340 // Write the arguments to stack frame. | 274 // Write the arguments to stack frame. |
341 for (int i = 0; i < argc; i++) { | 275 for (int i = 0; i < argc; i++) { |
342 Register arg = values[argc-1-i]; | 276 Register arg = values[argc-1-i]; |
343 ASSERT(!receiver.is(arg)); | 277 ASSERT(!receiver.is(arg)); |
344 ASSERT(!scratch_in.is(arg)); | 278 ASSERT(!scratch_in.is(arg)); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 Address function_address = v8::ToCData<Address>(api_call_info->callback()); | 329 Address function_address = v8::ToCData<Address>(api_call_info->callback()); |
396 __ Move( | 330 __ Move( |
397 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); | 331 api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE); |
398 | 332 |
399 // Jump to stub. | 333 // Jump to stub. |
400 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); | 334 CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); |
401 __ TailCallStub(&stub); | 335 __ TailCallStub(&stub); |
402 } | 336 } |
403 | 337 |
404 | 338 |
405 void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm, | 339 void NamedStoreHandlerCompiler::GenerateRestoreName(MacroAssembler* masm, |
406 Label* label, | 340 Label* label, |
407 Handle<Name> name) { | 341 Handle<Name> name) { |
408 if (!label->is_unused()) { | 342 if (!label->is_unused()) { |
409 __ bind(label); | 343 __ bind(label); |
410 __ Move(this->name(), name); | 344 __ Move(this->name(), name); |
411 } | 345 } |
412 } | 346 } |
413 | 347 |
414 | 348 |
415 void StubCompiler::GenerateCheckPropertyCell(MacroAssembler* masm, | 349 void PropertyHandlerCompiler::GenerateCheckPropertyCell( |
416 Handle<JSGlobalObject> global, | 350 MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name, |
417 Handle<Name> name, | 351 Register scratch, Label* miss) { |
418 Register scratch, | |
419 Label* miss) { | |
420 Handle<PropertyCell> cell = | 352 Handle<PropertyCell> cell = |
421 JSGlobalObject::EnsurePropertyCell(global, name); | 353 JSGlobalObject::EnsurePropertyCell(global, name); |
422 ASSERT(cell->value()->IsTheHole()); | 354 ASSERT(cell->value()->IsTheHole()); |
423 __ Move(scratch, cell); | 355 __ Move(scratch, cell); |
424 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), | 356 __ Cmp(FieldOperand(scratch, Cell::kValueOffset), |
425 masm->isolate()->factory()->the_hole_value()); | 357 masm->isolate()->factory()->the_hole_value()); |
426 __ j(not_equal, miss); | 358 __ j(not_equal, miss); |
427 } | 359 } |
428 | 360 |
429 | 361 |
430 void StoreStubCompiler::GenerateNegativeHolderLookup( | 362 void NamedStoreHandlerCompiler::GenerateNegativeHolderLookup( |
431 MacroAssembler* masm, | 363 MacroAssembler* masm, Handle<JSObject> holder, Register holder_reg, |
432 Handle<JSObject> holder, | 364 Handle<Name> name, Label* miss) { |
433 Register holder_reg, | |
434 Handle<Name> name, | |
435 Label* miss) { | |
436 if (holder->IsJSGlobalObject()) { | 365 if (holder->IsJSGlobalObject()) { |
437 GenerateCheckPropertyCell( | 366 GenerateCheckPropertyCell( |
438 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); | 367 masm, Handle<JSGlobalObject>::cast(holder), name, scratch1(), miss); |
439 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { | 368 } else if (!holder->HasFastProperties() && !holder->IsJSGlobalProxy()) { |
440 GenerateDictionaryNegativeLookup( | 369 GenerateDictionaryNegativeLookup( |
441 masm, miss, holder_reg, name, scratch1(), scratch2()); | 370 masm, miss, holder_reg, name, scratch1(), scratch2()); |
442 } | 371 } |
443 } | 372 } |
444 | 373 |
445 | 374 |
446 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if | 375 // Receiver_reg is preserved on jumps to miss_label, but may be destroyed if |
447 // store is successful. | 376 // store is successful. |
448 void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm, | 377 void NamedStoreHandlerCompiler::GenerateStoreTransition( |
449 Handle<JSObject> object, | 378 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
450 LookupResult* lookup, | 379 Handle<Map> transition, Handle<Name> name, Register receiver_reg, |
451 Handle<Map> transition, | 380 Register storage_reg, Register value_reg, Register scratch1, |
452 Handle<Name> name, | 381 Register scratch2, Register unused, Label* miss_label, Label* slow) { |
453 Register receiver_reg, | |
454 Register storage_reg, | |
455 Register value_reg, | |
456 Register scratch1, | |
457 Register scratch2, | |
458 Register unused, | |
459 Label* miss_label, | |
460 Label* slow) { | |
461 int descriptor = transition->LastAdded(); | 382 int descriptor = transition->LastAdded(); |
462 DescriptorArray* descriptors = transition->instance_descriptors(); | 383 DescriptorArray* descriptors = transition->instance_descriptors(); |
463 PropertyDetails details = descriptors->GetDetails(descriptor); | 384 PropertyDetails details = descriptors->GetDetails(descriptor); |
464 Representation representation = details.representation(); | 385 Representation representation = details.representation(); |
465 ASSERT(!representation.IsNone()); | 386 ASSERT(!representation.IsNone()); |
466 | 387 |
467 if (details.type() == CONSTANT) { | 388 if (details.type() == CONSTANT) { |
468 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); | 389 Handle<Object> constant(descriptors->GetValue(descriptor), masm->isolate()); |
469 __ Cmp(value_reg, constant); | 390 __ Cmp(value_reg, constant); |
470 __ j(not_equal, miss_label); | 391 __ j(not_equal, miss_label); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 } | 519 } |
599 | 520 |
600 // Return the value (register rax). | 521 // Return the value (register rax). |
601 ASSERT(value_reg.is(rax)); | 522 ASSERT(value_reg.is(rax)); |
602 __ ret(0); | 523 __ ret(0); |
603 } | 524 } |
604 | 525 |
605 | 526 |
606 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 527 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
607 // but may be destroyed if store is successful. | 528 // but may be destroyed if store is successful. |
608 void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm, | 529 void NamedStoreHandlerCompiler::GenerateStoreField( |
609 Handle<JSObject> object, | 530 MacroAssembler* masm, Handle<JSObject> object, LookupResult* lookup, |
610 LookupResult* lookup, | 531 Register receiver_reg, Register name_reg, Register value_reg, |
611 Register receiver_reg, | 532 Register scratch1, Register scratch2, Label* miss_label) { |
612 Register name_reg, | |
613 Register value_reg, | |
614 Register scratch1, | |
615 Register scratch2, | |
616 Label* miss_label) { | |
617 // Stub never generated for non-global objects that require access | 533 // Stub never generated for non-global objects that require access |
618 // checks. | 534 // checks. |
619 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); | 535 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); |
620 | 536 |
621 FieldIndex index = lookup->GetFieldIndex(); | 537 FieldIndex index = lookup->GetFieldIndex(); |
622 | 538 |
623 Representation representation = lookup->representation(); | 539 Representation representation = lookup->representation(); |
624 ASSERT(!representation.IsNone()); | 540 ASSERT(!representation.IsNone()); |
625 if (representation.IsSmi()) { | 541 if (representation.IsSmi()) { |
626 __ JumpIfNotSmi(value_reg, miss_label); | 542 __ JumpIfNotSmi(value_reg, miss_label); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 EMIT_REMEMBERED_SET, smi_check); | 616 EMIT_REMEMBERED_SET, smi_check); |
701 } | 617 } |
702 } | 618 } |
703 | 619 |
704 // Return the value (register rax). | 620 // Return the value (register rax). |
705 ASSERT(value_reg.is(rax)); | 621 ASSERT(value_reg.is(rax)); |
706 __ ret(0); | 622 __ ret(0); |
707 } | 623 } |
708 | 624 |
709 | 625 |
710 void StubCompiler::GenerateTailCall(MacroAssembler* masm, Handle<Code> code) { | 626 void PropertyAccessCompiler::GenerateTailCall(MacroAssembler* masm, |
| 627 Handle<Code> code) { |
711 __ jmp(code, RelocInfo::CODE_TARGET); | 628 __ jmp(code, RelocInfo::CODE_TARGET); |
712 } | 629 } |
713 | 630 |
714 | 631 |
715 #undef __ | 632 #undef __ |
716 #define __ ACCESS_MASM((masm())) | 633 #define __ ACCESS_MASM((masm())) |
717 | 634 |
718 | 635 |
719 Register StubCompiler::CheckPrototypes(Handle<HeapType> type, | 636 Register PropertyHandlerCompiler::CheckPrototypes( |
720 Register object_reg, | 637 Handle<HeapType> type, Register object_reg, Handle<JSObject> holder, |
721 Handle<JSObject> holder, | 638 Register holder_reg, Register scratch1, Register scratch2, |
722 Register holder_reg, | 639 Handle<Name> name, Label* miss, PrototypeCheckType check) { |
723 Register scratch1, | |
724 Register scratch2, | |
725 Handle<Name> name, | |
726 Label* miss, | |
727 PrototypeCheckType check) { | |
728 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); | 640 Handle<Map> receiver_map(IC::TypeToMap(*type, isolate())); |
729 | 641 |
730 // Make sure there's no overlap between holder and object registers. | 642 // Make sure there's no overlap between holder and object registers. |
731 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); | 643 ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); |
732 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) | 644 ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) |
733 && !scratch2.is(scratch1)); | 645 && !scratch2.is(scratch1)); |
734 | 646 |
735 // Keep track of the current object in register reg. On the first | 647 // Keep track of the current object in register reg. On the first |
736 // iteration, reg is an alias for object_reg, on later iterations, | 648 // iteration, reg is an alias for object_reg, on later iterations, |
737 // it is an alias for holder_reg. | 649 // it is an alias for holder_reg. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 !current_map->is_access_check_needed()); | 737 !current_map->is_access_check_needed()); |
826 if (current_map->IsJSGlobalProxyMap()) { | 738 if (current_map->IsJSGlobalProxyMap()) { |
827 __ CheckAccessGlobalProxy(reg, scratch1, miss); | 739 __ CheckAccessGlobalProxy(reg, scratch1, miss); |
828 } | 740 } |
829 | 741 |
830 // Return the register containing the holder. | 742 // Return the register containing the holder. |
831 return reg; | 743 return reg; |
832 } | 744 } |
833 | 745 |
834 | 746 |
835 void LoadStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 747 void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
836 if (!miss->is_unused()) { | 748 if (!miss->is_unused()) { |
837 Label success; | 749 Label success; |
838 __ jmp(&success); | 750 __ jmp(&success); |
839 __ bind(miss); | 751 __ bind(miss); |
840 TailCallBuiltin(masm(), MissBuiltin(kind())); | 752 TailCallBuiltin(masm(), MissBuiltin(kind())); |
841 __ bind(&success); | 753 __ bind(&success); |
842 } | 754 } |
843 } | 755 } |
844 | 756 |
845 | 757 |
846 void StoreStubCompiler::HandlerFrontendFooter(Handle<Name> name, Label* miss) { | 758 void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { |
847 if (!miss->is_unused()) { | 759 if (!miss->is_unused()) { |
848 Label success; | 760 Label success; |
849 __ jmp(&success); | 761 __ jmp(&success); |
850 GenerateRestoreName(masm(), miss, name); | 762 GenerateRestoreName(masm(), miss, name); |
851 TailCallBuiltin(masm(), MissBuiltin(kind())); | 763 TailCallBuiltin(masm(), MissBuiltin(kind())); |
852 __ bind(&success); | 764 __ bind(&success); |
853 } | 765 } |
854 } | 766 } |
855 | 767 |
856 | 768 |
857 Register LoadStubCompiler::CallbackHandlerFrontend( | 769 Register NamedLoadHandlerCompiler::CallbackFrontend(Handle<HeapType> type, |
858 Handle<HeapType> type, | 770 Register object_reg, |
859 Register object_reg, | 771 Handle<JSObject> holder, |
860 Handle<JSObject> holder, | 772 Handle<Name> name, |
861 Handle<Name> name, | 773 Handle<Object> callback) { |
862 Handle<Object> callback) { | |
863 Label miss; | 774 Label miss; |
864 | 775 |
865 Register reg = HandlerFrontendHeader(type, object_reg, holder, name, &miss); | 776 Register reg = FrontendHeader(type, object_reg, holder, name, &miss); |
866 | 777 |
867 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { | 778 if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { |
868 ASSERT(!reg.is(scratch2())); | 779 ASSERT(!reg.is(scratch2())); |
869 ASSERT(!reg.is(scratch3())); | 780 ASSERT(!reg.is(scratch3())); |
870 ASSERT(!reg.is(scratch4())); | 781 ASSERT(!reg.is(scratch4())); |
871 | 782 |
872 // Load the properties dictionary. | 783 // Load the properties dictionary. |
873 Register dictionary = scratch4(); | 784 Register dictionary = scratch4(); |
874 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); | 785 __ movp(dictionary, FieldOperand(reg, JSObject::kPropertiesOffset)); |
875 | 786 |
(...skipping 16 matching lines...) Expand all Loading... |
892 NameDictionary::kElementsStartIndex * kPointerSize; | 803 NameDictionary::kElementsStartIndex * kPointerSize; |
893 const int kValueOffset = kElementsStartOffset + kPointerSize; | 804 const int kValueOffset = kElementsStartOffset + kPointerSize; |
894 __ movp(scratch2(), | 805 __ movp(scratch2(), |
895 Operand(dictionary, index, times_pointer_size, | 806 Operand(dictionary, index, times_pointer_size, |
896 kValueOffset - kHeapObjectTag)); | 807 kValueOffset - kHeapObjectTag)); |
897 __ Move(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); | 808 __ Move(scratch3(), callback, RelocInfo::EMBEDDED_OBJECT); |
898 __ cmpp(scratch2(), scratch3()); | 809 __ cmpp(scratch2(), scratch3()); |
899 __ j(not_equal, &miss); | 810 __ j(not_equal, &miss); |
900 } | 811 } |
901 | 812 |
902 HandlerFrontendFooter(name, &miss); | 813 FrontendFooter(name, &miss); |
903 return reg; | 814 return reg; |
904 } | 815 } |
905 | 816 |
906 | 817 |
907 void LoadStubCompiler::GenerateLoadField(Register reg, | 818 void NamedLoadHandlerCompiler::GenerateLoadField( |
908 Handle<JSObject> holder, | 819 Register reg, Handle<JSObject> holder, FieldIndex field, |
909 FieldIndex field, | 820 Representation representation) { |
910 Representation representation) { | |
911 if (!reg.is(receiver())) __ movp(receiver(), reg); | 821 if (!reg.is(receiver())) __ movp(receiver(), reg); |
912 LoadFieldStub stub(isolate(), field); | 822 LoadFieldStub stub(isolate(), field); |
913 GenerateTailCall(masm(), stub.GetCode()); | 823 GenerateTailCall(masm(), stub.GetCode()); |
914 } | 824 } |
915 | 825 |
916 | 826 |
917 void LoadStubCompiler::GenerateLoadCallback( | 827 void NamedLoadHandlerCompiler::GenerateLoadCallback( |
918 Register reg, | 828 Register reg, Handle<ExecutableAccessorInfo> callback) { |
919 Handle<ExecutableAccessorInfo> callback) { | |
920 // Insert additional parameters into the stack frame above return address. | 829 // Insert additional parameters into the stack frame above return address. |
921 ASSERT(!scratch4().is(reg)); | 830 ASSERT(!scratch4().is(reg)); |
922 __ PopReturnAddressTo(scratch4()); | 831 __ PopReturnAddressTo(scratch4()); |
923 | 832 |
924 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); | 833 STATIC_ASSERT(PropertyCallbackArguments::kHolderIndex == 0); |
925 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); | 834 STATIC_ASSERT(PropertyCallbackArguments::kIsolateIndex == 1); |
926 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); | 835 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueDefaultValueIndex == 2); |
927 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); | 836 STATIC_ASSERT(PropertyCallbackArguments::kReturnValueOffset == 3); |
928 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); | 837 STATIC_ASSERT(PropertyCallbackArguments::kDataIndex == 4); |
929 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); | 838 STATIC_ASSERT(PropertyCallbackArguments::kThisIndex == 5); |
(...skipping 22 matching lines...) Expand all Loading... |
952 // Abi for CallApiGetter | 861 // Abi for CallApiGetter |
953 Register api_function_address = r8; | 862 Register api_function_address = r8; |
954 Address getter_address = v8::ToCData<Address>(callback->getter()); | 863 Address getter_address = v8::ToCData<Address>(callback->getter()); |
955 __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE); | 864 __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE); |
956 | 865 |
957 CallApiGetterStub stub(isolate()); | 866 CallApiGetterStub stub(isolate()); |
958 __ TailCallStub(&stub); | 867 __ TailCallStub(&stub); |
959 } | 868 } |
960 | 869 |
961 | 870 |
962 void LoadStubCompiler::GenerateLoadConstant(Handle<Object> value) { | 871 void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) { |
963 // Return the constant value. | 872 // Return the constant value. |
964 __ Move(rax, value); | 873 __ Move(rax, value); |
965 __ ret(0); | 874 __ ret(0); |
966 } | 875 } |
967 | 876 |
968 | 877 |
969 void LoadStubCompiler::GenerateLoadInterceptor( | 878 void NamedLoadHandlerCompiler::GenerateLoadInterceptor( |
970 Register holder_reg, | 879 Register holder_reg, Handle<Object> object, |
971 Handle<Object> object, | 880 Handle<JSObject> interceptor_holder, LookupResult* lookup, |
972 Handle<JSObject> interceptor_holder, | |
973 LookupResult* lookup, | |
974 Handle<Name> name) { | 881 Handle<Name> name) { |
975 ASSERT(interceptor_holder->HasNamedInterceptor()); | 882 ASSERT(interceptor_holder->HasNamedInterceptor()); |
976 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); | 883 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); |
977 | 884 |
978 // So far the most popular follow ups for interceptor loads are FIELD | 885 // So far the most popular follow ups for interceptor loads are FIELD |
979 // and CALLBACKS, so inline only them, other cases may be added | 886 // and CALLBACKS, so inline only them, other cases may be added |
980 // later. | 887 // later. |
981 bool compile_followup_inline = false; | 888 bool compile_followup_inline = false; |
982 if (lookup->IsFound() && lookup->IsCacheable()) { | 889 if (lookup->IsFound() && lookup->IsCacheable()) { |
983 if (lookup->IsField()) { | 890 if (lookup->IsField()) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 this->name(), interceptor_holder); | 957 this->name(), interceptor_holder); |
1051 __ PushReturnAddressFrom(scratch2()); | 958 __ PushReturnAddressFrom(scratch2()); |
1052 | 959 |
1053 ExternalReference ref = ExternalReference( | 960 ExternalReference ref = ExternalReference( |
1054 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); | 961 IC_Utility(IC::kLoadPropertyWithInterceptor), isolate()); |
1055 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); | 962 __ TailCallExternalReference(ref, StubCache::kInterceptorArgsLength, 1); |
1056 } | 963 } |
1057 } | 964 } |
1058 | 965 |
1059 | 966 |
1060 Handle<Code> StoreStubCompiler::CompileStoreCallback( | 967 Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( |
1061 Handle<JSObject> object, | 968 Handle<JSObject> object, Handle<JSObject> holder, Handle<Name> name, |
1062 Handle<JSObject> holder, | |
1063 Handle<Name> name, | |
1064 Handle<ExecutableAccessorInfo> callback) { | 969 Handle<ExecutableAccessorInfo> callback) { |
1065 Register holder_reg = HandlerFrontend( | 970 Register holder_reg = |
1066 IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); | 971 Frontend(IC::CurrentTypeOf(object, isolate()), receiver(), holder, name); |
1067 | 972 |
1068 __ PopReturnAddressTo(scratch1()); | 973 __ PopReturnAddressTo(scratch1()); |
1069 __ Push(receiver()); | 974 __ Push(receiver()); |
1070 __ Push(holder_reg); | 975 __ Push(holder_reg); |
1071 __ Push(callback); // callback info | 976 __ Push(callback); // callback info |
1072 __ Push(name); | 977 __ Push(name); |
1073 __ Push(value()); | 978 __ Push(value()); |
1074 __ PushReturnAddressFrom(scratch1()); | 979 __ PushReturnAddressFrom(scratch1()); |
1075 | 980 |
1076 // Do tail-call to the runtime system. | 981 // Do tail-call to the runtime system. |
1077 ExternalReference store_callback_property = | 982 ExternalReference store_callback_property = |
1078 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); | 983 ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); |
1079 __ TailCallExternalReference(store_callback_property, 5, 1); | 984 __ TailCallExternalReference(store_callback_property, 5, 1); |
1080 | 985 |
1081 // Return the generated code. | 986 // Return the generated code. |
1082 return GetCode(kind(), Code::FAST, name); | 987 return GetCode(kind(), Code::FAST, name); |
1083 } | 988 } |
1084 | 989 |
1085 | 990 |
1086 #undef __ | 991 #undef __ |
1087 #define __ ACCESS_MASM(masm) | 992 #define __ ACCESS_MASM(masm) |
1088 | 993 |
1089 | 994 |
1090 void StoreStubCompiler::GenerateStoreViaSetter( | 995 void NamedStoreHandlerCompiler::GenerateStoreViaSetter( |
1091 MacroAssembler* masm, | 996 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
1092 Handle<HeapType> type, | |
1093 Register receiver, | |
1094 Handle<JSFunction> setter) { | 997 Handle<JSFunction> setter) { |
1095 // ----------- S t a t e ------------- | 998 // ----------- S t a t e ------------- |
1096 // -- rsp[0] : return address | 999 // -- rsp[0] : return address |
1097 // ----------------------------------- | 1000 // ----------------------------------- |
1098 { | 1001 { |
1099 FrameScope scope(masm, StackFrame::INTERNAL); | 1002 FrameScope scope(masm, StackFrame::INTERNAL); |
1100 | 1003 |
1101 // Save value register, so we can restore it later. | 1004 // Save value register, so we can restore it later. |
1102 __ Push(value()); | 1005 __ Push(value()); |
1103 | 1006 |
(...skipping 23 matching lines...) Expand all Loading... |
1127 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1030 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1128 } | 1031 } |
1129 __ ret(0); | 1032 __ ret(0); |
1130 } | 1033 } |
1131 | 1034 |
1132 | 1035 |
1133 #undef __ | 1036 #undef __ |
1134 #define __ ACCESS_MASM(masm()) | 1037 #define __ ACCESS_MASM(masm()) |
1135 | 1038 |
1136 | 1039 |
1137 Handle<Code> StoreStubCompiler::CompileStoreInterceptor( | 1040 Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor( |
1138 Handle<JSObject> object, | 1041 Handle<JSObject> object, Handle<Name> name) { |
1139 Handle<Name> name) { | |
1140 __ PopReturnAddressTo(scratch1()); | 1042 __ PopReturnAddressTo(scratch1()); |
1141 __ Push(receiver()); | 1043 __ Push(receiver()); |
1142 __ Push(this->name()); | 1044 __ Push(this->name()); |
1143 __ Push(value()); | 1045 __ Push(value()); |
1144 __ PushReturnAddressFrom(scratch1()); | 1046 __ PushReturnAddressFrom(scratch1()); |
1145 | 1047 |
1146 // Do tail-call to the runtime system. | 1048 // Do tail-call to the runtime system. |
1147 ExternalReference store_ic_property = | 1049 ExternalReference store_ic_property = |
1148 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); | 1050 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); |
1149 __ TailCallExternalReference(store_ic_property, 3, 1); | 1051 __ TailCallExternalReference(store_ic_property, 3, 1); |
1150 | 1052 |
1151 // Return the generated code. | 1053 // Return the generated code. |
1152 return GetCode(kind(), Code::FAST, name); | 1054 return GetCode(kind(), Code::FAST, name); |
1153 } | 1055 } |
1154 | 1056 |
1155 | 1057 |
1156 void StoreStubCompiler::GenerateStoreArrayLength() { | 1058 void NamedStoreHandlerCompiler::GenerateStoreArrayLength() { |
1157 // Prepare tail call to StoreIC_ArrayLength. | 1059 // Prepare tail call to StoreIC_ArrayLength. |
1158 __ PopReturnAddressTo(scratch1()); | 1060 __ PopReturnAddressTo(scratch1()); |
1159 __ Push(receiver()); | 1061 __ Push(receiver()); |
1160 __ Push(value()); | 1062 __ Push(value()); |
1161 __ PushReturnAddressFrom(scratch1()); | 1063 __ PushReturnAddressFrom(scratch1()); |
1162 | 1064 |
1163 ExternalReference ref = | 1065 ExternalReference ref = |
1164 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), | 1066 ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), |
1165 masm()->isolate()); | 1067 masm()->isolate()); |
1166 __ TailCallExternalReference(ref, 2, 1); | 1068 __ TailCallExternalReference(ref, 2, 1); |
1167 } | 1069 } |
1168 | 1070 |
1169 | 1071 |
1170 Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( | 1072 Handle<Code> PropertyICCompiler::CompileIndexedStorePolymorphic( |
1171 MapHandleList* receiver_maps, | 1073 MapHandleList* receiver_maps, CodeHandleList* handler_stubs, |
1172 CodeHandleList* handler_stubs, | |
1173 MapHandleList* transitioned_maps) { | 1074 MapHandleList* transitioned_maps) { |
1174 Label miss; | 1075 Label miss; |
1175 __ JumpIfSmi(receiver(), &miss, Label::kNear); | 1076 __ JumpIfSmi(receiver(), &miss, Label::kNear); |
1176 | 1077 |
1177 __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); | 1078 __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset)); |
1178 int receiver_count = receiver_maps->length(); | 1079 int receiver_count = receiver_maps->length(); |
1179 for (int i = 0; i < receiver_count; ++i) { | 1080 for (int i = 0; i < receiver_count; ++i) { |
1180 // Check map and tail call if there's a match | 1081 // Check map and tail call if there's a match |
1181 __ Cmp(scratch1(), receiver_maps->at(i)); | 1082 __ Cmp(scratch1(), receiver_maps->at(i)); |
1182 if (transitioned_maps->at(i).is_null()) { | 1083 if (transitioned_maps->at(i).is_null()) { |
1183 __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); | 1084 __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); |
1184 } else { | 1085 } else { |
1185 Label next_map; | 1086 Label next_map; |
1186 __ j(not_equal, &next_map, Label::kNear); | 1087 __ j(not_equal, &next_map, Label::kNear); |
1187 __ Move(transition_map(), | 1088 __ Move(transition_map(), |
1188 transitioned_maps->at(i), | 1089 transitioned_maps->at(i), |
1189 RelocInfo::EMBEDDED_OBJECT); | 1090 RelocInfo::EMBEDDED_OBJECT); |
1190 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); | 1091 __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); |
1191 __ bind(&next_map); | 1092 __ bind(&next_map); |
1192 } | 1093 } |
1193 } | 1094 } |
1194 | 1095 |
1195 __ bind(&miss); | 1096 __ bind(&miss); |
1196 | 1097 |
1197 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1098 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1198 | 1099 |
1199 // Return the generated code. | 1100 // Return the generated code. |
1200 return GetICCode( | 1101 return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); |
1201 kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC); | |
1202 } | 1102 } |
1203 | 1103 |
1204 | 1104 |
1205 Handle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<HeapType> type, | 1105 Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( |
1206 Handle<JSObject> last, | 1106 Handle<HeapType> type, Handle<JSObject> last, Handle<Name> name) { |
1207 Handle<Name> name) { | 1107 NonexistentFrontend(type, last, name); |
1208 NonexistentHandlerFrontend(type, last, name); | |
1209 | 1108 |
1210 // Return undefined if maps of the full prototype chain are still the | 1109 // Return undefined if maps of the full prototype chain are still the |
1211 // same and no global property with this name contains a value. | 1110 // same and no global property with this name contains a value. |
1212 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); | 1111 __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); |
1213 __ ret(0); | 1112 __ ret(0); |
1214 | 1113 |
1215 // Return the generated code. | 1114 // Return the generated code. |
1216 return GetCode(kind(), Code::FAST, name); | 1115 return GetCode(kind(), Code::FAST, name); |
1217 } | 1116 } |
1218 | 1117 |
1219 | 1118 |
1220 Register* LoadStubCompiler::registers() { | 1119 Register* PropertyAccessCompiler::load_calling_convention() { |
1221 // receiver, name, scratch1, scratch2, scratch3, scratch4. | 1120 // receiver, name, scratch1, scratch2, scratch3, scratch4. |
1222 Register receiver = LoadIC::ReceiverRegister(); | 1121 Register receiver = LoadIC::ReceiverRegister(); |
1223 Register name = LoadIC::NameRegister(); | 1122 Register name = LoadIC::NameRegister(); |
1224 static Register registers[] = { receiver, name, rax, rbx, rdi, r8 }; | 1123 static Register registers[] = { receiver, name, rax, rbx, rdi, r8 }; |
1225 return registers; | 1124 return registers; |
1226 } | 1125 } |
1227 | 1126 |
1228 | 1127 |
1229 Register* KeyedLoadStubCompiler::registers() { | 1128 Register* PropertyAccessCompiler::store_calling_convention() { |
1230 // receiver, name, scratch1, scratch2, scratch3, scratch4. | |
1231 Register receiver = LoadIC::ReceiverRegister(); | |
1232 Register name = LoadIC::NameRegister(); | |
1233 static Register registers[] = { receiver, name, rax, rbx, rdi, r8 }; | |
1234 return registers; | |
1235 } | |
1236 | |
1237 | |
1238 Register StoreStubCompiler::value() { | |
1239 return StoreIC::ValueRegister(); | |
1240 } | |
1241 | |
1242 | |
1243 Register* StoreStubCompiler::registers() { | |
1244 // receiver, name, scratch1, scratch2, scratch3. | 1129 // receiver, name, scratch1, scratch2, scratch3. |
1245 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1130 Register receiver = KeyedStoreIC::ReceiverRegister(); |
1246 Register name = KeyedStoreIC::NameRegister(); | 1131 Register name = KeyedStoreIC::NameRegister(); |
1247 static Register registers[] = { receiver, name, rbx, rdi, r8 }; | 1132 static Register registers[] = { receiver, name, rbx, rdi, r8 }; |
1248 return registers; | 1133 return registers; |
1249 } | 1134 } |
1250 | 1135 |
1251 | 1136 |
1252 Register* KeyedStoreStubCompiler::registers() { | 1137 Register* PropertyAccessCompiler::keyed_store_calling_convention() { |
1253 // receiver, name, scratch1/map, scratch2, scratch3. | 1138 // receiver, name, scratch1/map, scratch2, scratch3. |
1254 Register receiver = KeyedStoreIC::ReceiverRegister(); | 1139 Register receiver = KeyedStoreIC::ReceiverRegister(); |
1255 Register name = KeyedStoreIC::NameRegister(); | 1140 Register name = KeyedStoreIC::NameRegister(); |
1256 Register map = KeyedStoreIC::MapRegister(); | 1141 Register map = KeyedStoreIC::MapRegister(); |
1257 static Register registers[] = { receiver, name, map, rdi, r8 }; | 1142 static Register registers[] = { receiver, name, map, rdi, r8 }; |
1258 return registers; | 1143 return registers; |
1259 } | 1144 } |
1260 | 1145 |
1261 | 1146 |
| 1147 Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); } |
| 1148 |
| 1149 |
1262 #undef __ | 1150 #undef __ |
1263 #define __ ACCESS_MASM(masm) | 1151 #define __ ACCESS_MASM(masm) |
1264 | 1152 |
1265 | 1153 |
1266 void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm, | 1154 void NamedLoadHandlerCompiler::GenerateLoadViaGetter( |
1267 Handle<HeapType> type, | 1155 MacroAssembler* masm, Handle<HeapType> type, Register receiver, |
1268 Register receiver, | 1156 Handle<JSFunction> getter) { |
1269 Handle<JSFunction> getter) { | |
1270 // ----------- S t a t e ------------- | 1157 // ----------- S t a t e ------------- |
1271 // -- rax : receiver | 1158 // -- rax : receiver |
1272 // -- rcx : name | 1159 // -- rcx : name |
1273 // -- rsp[0] : return address | 1160 // -- rsp[0] : return address |
1274 // ----------------------------------- | 1161 // ----------------------------------- |
1275 { | 1162 { |
1276 FrameScope scope(masm, StackFrame::INTERNAL); | 1163 FrameScope scope(masm, StackFrame::INTERNAL); |
1277 | 1164 |
1278 if (!getter.is_null()) { | 1165 if (!getter.is_null()) { |
1279 // Call the JavaScript getter with the receiver on the stack. | 1166 // Call the JavaScript getter with the receiver on the stack. |
(...skipping 17 matching lines...) Expand all Loading... |
1297 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1184 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1298 } | 1185 } |
1299 __ ret(0); | 1186 __ ret(0); |
1300 } | 1187 } |
1301 | 1188 |
1302 | 1189 |
1303 #undef __ | 1190 #undef __ |
1304 #define __ ACCESS_MASM(masm()) | 1191 #define __ ACCESS_MASM(masm()) |
1305 | 1192 |
1306 | 1193 |
1307 Handle<Code> LoadStubCompiler::CompileLoadGlobal( | 1194 Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( |
1308 Handle<HeapType> type, | 1195 Handle<HeapType> type, Handle<GlobalObject> global, |
1309 Handle<GlobalObject> global, | 1196 Handle<PropertyCell> cell, Handle<Name> name, bool is_dont_delete) { |
1310 Handle<PropertyCell> cell, | |
1311 Handle<Name> name, | |
1312 bool is_dont_delete) { | |
1313 Label miss; | 1197 Label miss; |
1314 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since | 1198 // TODO(verwaest): Directly store to rax. Currently we cannot do this, since |
1315 // rax is used as receiver(), which we would otherwise clobber before a | 1199 // rax is used as receiver(), which we would otherwise clobber before a |
1316 // potential miss. | 1200 // potential miss. |
1317 HandlerFrontendHeader(type, receiver(), global, name, &miss); | 1201 FrontendHeader(type, receiver(), global, name, &miss); |
1318 | 1202 |
1319 // Get the value from the cell. | 1203 // Get the value from the cell. |
1320 __ Move(rbx, cell); | 1204 __ Move(rbx, cell); |
1321 __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); | 1205 __ movp(rbx, FieldOperand(rbx, PropertyCell::kValueOffset)); |
1322 | 1206 |
1323 // Check for deleted property if property can actually be deleted. | 1207 // Check for deleted property if property can actually be deleted. |
1324 if (!is_dont_delete) { | 1208 if (!is_dont_delete) { |
1325 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 1209 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
1326 __ j(equal, &miss); | 1210 __ j(equal, &miss); |
1327 } else if (FLAG_debug_code) { | 1211 } else if (FLAG_debug_code) { |
1328 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 1212 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
1329 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); | 1213 __ Check(not_equal, kDontDeleteCellsCannotContainTheHole); |
1330 } | 1214 } |
1331 | 1215 |
1332 Counters* counters = isolate()->counters(); | 1216 Counters* counters = isolate()->counters(); |
1333 __ IncrementCounter(counters->named_load_global_stub(), 1); | 1217 __ IncrementCounter(counters->named_load_global_stub(), 1); |
1334 __ movp(rax, rbx); | 1218 __ movp(rax, rbx); |
1335 __ ret(0); | 1219 __ ret(0); |
1336 | 1220 |
1337 HandlerFrontendFooter(name, &miss); | 1221 FrontendFooter(name, &miss); |
1338 | 1222 |
1339 // Return the generated code. | 1223 // Return the generated code. |
1340 return GetCode(kind(), Code::NORMAL, name); | 1224 return GetCode(kind(), Code::NORMAL, name); |
1341 } | 1225 } |
1342 | 1226 |
1343 | 1227 |
1344 Handle<Code> BaseLoadStoreStubCompiler::CompilePolymorphicIC( | 1228 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types, |
1345 TypeHandleList* types, | 1229 CodeHandleList* handlers, |
1346 CodeHandleList* handlers, | 1230 Handle<Name> name, |
1347 Handle<Name> name, | 1231 Code::StubType type, |
1348 Code::StubType type, | 1232 IcCheckType check) { |
1349 IcCheckType check) { | |
1350 Label miss; | 1233 Label miss; |
1351 | 1234 |
1352 if (check == PROPERTY && | 1235 if (check == PROPERTY && |
1353 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { | 1236 (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) { |
1354 __ Cmp(this->name(), name); | 1237 __ Cmp(this->name(), name); |
1355 __ j(not_equal, &miss); | 1238 __ j(not_equal, &miss); |
1356 } | 1239 } |
1357 | 1240 |
1358 Label number_case; | 1241 Label number_case; |
1359 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; | 1242 Label* smi_target = IncludesNumberType(types) ? &number_case : &miss; |
(...skipping 21 matching lines...) Expand all Loading... |
1381 } | 1264 } |
1382 } | 1265 } |
1383 ASSERT(number_of_handled_maps > 0); | 1266 ASSERT(number_of_handled_maps > 0); |
1384 | 1267 |
1385 __ bind(&miss); | 1268 __ bind(&miss); |
1386 TailCallBuiltin(masm(), MissBuiltin(kind())); | 1269 TailCallBuiltin(masm(), MissBuiltin(kind())); |
1387 | 1270 |
1388 // Return the generated code. | 1271 // Return the generated code. |
1389 InlineCacheState state = | 1272 InlineCacheState state = |
1390 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; | 1273 number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC; |
1391 return GetICCode(kind(), type, name, state); | 1274 return GetCode(kind(), type, name, state); |
1392 } | 1275 } |
1393 | 1276 |
1394 | 1277 |
1395 #undef __ | 1278 #undef __ |
1396 #define __ ACCESS_MASM(masm) | 1279 #define __ ACCESS_MASM(masm) |
1397 | 1280 |
1398 | 1281 |
1399 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement( | 1282 void IndexedHandlerCompiler::GenerateLoadDictionaryElement( |
1400 MacroAssembler* masm) { | 1283 MacroAssembler* masm) { |
1401 // ----------- S t a t e ------------- | 1284 // ----------- S t a t e ------------- |
1402 // -- rcx : key | 1285 // -- rcx : key |
1403 // -- rdx : receiver | 1286 // -- rdx : receiver |
1404 // -- rsp[0] : return address | 1287 // -- rsp[0] : return address |
1405 // ----------------------------------- | 1288 // ----------------------------------- |
1406 ASSERT(rdx.is(LoadIC::ReceiverRegister())); | 1289 ASSERT(rdx.is(LoadIC::ReceiverRegister())); |
1407 ASSERT(rcx.is(LoadIC::NameRegister())); | 1290 ASSERT(rcx.is(LoadIC::NameRegister())); |
1408 Label slow, miss; | 1291 Label slow, miss; |
1409 | 1292 |
(...skipping 28 matching lines...) Expand all Loading... |
1438 // ----------------------------------- | 1321 // ----------------------------------- |
1439 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); | 1322 TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss); |
1440 } | 1323 } |
1441 | 1324 |
1442 | 1325 |
1443 #undef __ | 1326 #undef __ |
1444 | 1327 |
1445 } } // namespace v8::internal | 1328 } } // namespace v8::internal |
1446 | 1329 |
1447 #endif // V8_TARGET_ARCH_X64 | 1330 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |