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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 160272: X64: Added inline keyed load/store and a bunch of other missing functions. (Closed)
Patch Set: Addressed review comments, and fixed bugs introduced by updating. Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 18 matching lines...) Expand all
29 #include "v8.h" 29 #include "v8.h"
30 30
31 #include "ic-inl.h" 31 #include "ic-inl.h"
32 #include "codegen-inl.h" 32 #include "codegen-inl.h"
33 #include "stub-cache.h" 33 #include "stub-cache.h"
34 #include "macro-assembler-x64.h" 34 #include "macro-assembler-x64.h"
35 35
36 namespace v8 { 36 namespace v8 {
37 namespace internal { 37 namespace internal {
38 38
39 //-----------------------------------------------------------------------------
40 // StubCompiler static helper functions
41
42 #define __ ACCESS_MASM(masm)
43
44
45 static void ProbeTable(MacroAssembler* masm,
46 Code::Flags flags,
47 StubCache::Table table,
48 Register name,
49 Register offset) {
50 ExternalReference key_offset(SCTableReference::keyReference(table));
51 Label miss;
52
53 __ movq(kScratchRegister, key_offset);
54 // Check that the key in the entry matches the name.
55 __ cmpl(name, Operand(kScratchRegister, offset, times_4, 0));
56 __ j(not_equal, &miss);
57 // Get the code entry from the cache.
58 // Use key_offset + kPointerSize, rather than loading value_offset.
59 __ movq(kScratchRegister,
60 Operand(kScratchRegister, offset, times_4, kPointerSize));
61 // Check that the flags match what we're looking for.
62 __ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset));
63 __ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup));
64 __ cmpl(offset, Immediate(flags));
65 __ j(not_equal, &miss);
66
67 // Jump to the first instruction in the code stub.
68 __ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag));
69 __ jmp(kScratchRegister);
70
71 __ bind(&miss);
72 }
73
74
75 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
76 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
77 Code* code = NULL;
78 if (kind == Code::LOAD_IC) {
79 code = Builtins::builtin(Builtins::LoadIC_Miss);
80 } else {
81 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
82 }
83
84 Handle<Code> ic(code);
85 __ Jump(ic, RelocInfo::CODE_TARGET);
86 }
87
88
89 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
90 int index,
91 Register prototype) {
92 // Load the global or builtins object from the current context.
93 __ movq(prototype,
94 Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
95 // Load the global context from the global or builtins object.
96 __ movq(prototype,
97 FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
98 // Load the function from the global context.
99 __ movq(prototype, Operand(prototype, Context::SlotOffset(index)));
100 // Load the initial map. The global functions all have initial maps.
101 __ movq(prototype,
102 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
103 // Load the prototype from the initial map.
104 __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
105 }
106
107
108 // Load a fast property out of a holder object (src). In-object properties
109 // are loaded directly otherwise the property is loaded from the properties
110 // fixed array.
111 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
112 Register dst, Register src,
113 JSObject* holder, int index) {
114 // Adjust for the number of properties stored in the holder.
115 index -= holder->map()->inobject_properties();
116 if (index < 0) {
117 // Get the property straight out of the holder.
118 int offset = holder->map()->instance_size() + (index * kPointerSize);
119 __ movq(dst, FieldOperand(src, offset));
120 } else {
121 // Calculate the offset into the properties array.
122 int offset = index * kPointerSize + FixedArray::kHeaderSize;
123 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
124 __ movq(dst, FieldOperand(dst, offset));
125 }
126 }
127
128
129 template <typename Pushable>
130 static void PushInterceptorArguments(MacroAssembler* masm,
131 Register receiver,
132 Register holder,
133 Pushable name,
134 JSObject* holder_obj,
135 Smi* lookup_hint) {
136 __ push(receiver);
137 __ push(holder);
138 __ push(name);
139 // TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or
140 // LOOKUP_IN_PROTOTYPE, but use a special version of lookup method?
141 __ push(Immediate(lookup_hint));
142
143 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
144 __ movq(kScratchRegister, Handle<Object>(interceptor),
145 RelocInfo::EMBEDDED_OBJECT);
146 __ push(kScratchRegister);
147 __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset));
148 }
149
150
151 void StubCache::GenerateProbe(MacroAssembler* masm,
152 Code::Flags flags,
153 Register receiver,
154 Register name,
155 Register scratch,
156 Register extra) {
157 Label miss;
158 USE(extra); // The register extra is not used on the X64 platform.
159 // Make sure that code is valid. The shifting code relies on the
160 // entry size being 16.
161 ASSERT(sizeof(Entry) == 16);
162
163 // Make sure the flags do not name a specific type.
164 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
165
166 // Make sure that there are no register conflicts.
167 ASSERT(!scratch.is(receiver));
168 ASSERT(!scratch.is(name));
169
170 // Check that the receiver isn't a smi.
171 __ testl(receiver, Immediate(kSmiTagMask));
172 __ j(zero, &miss);
173
174 // Get the map of the receiver and compute the hash.
175 __ movl(scratch, FieldOperand(name, String::kLengthOffset));
176 // Use only the low 32 bits of the map pointer.
177 __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
178 __ xor_(scratch, Immediate(flags));
179 __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
180
181 // Probe the primary table.
182 ProbeTable(masm, flags, kPrimary, name, scratch);
183
184 // Primary miss: Compute hash for secondary probe.
185 __ movl(scratch, FieldOperand(name, String::kLengthOffset));
186 __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
187 __ xor_(scratch, Immediate(flags));
188 __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
189 __ subl(scratch, name);
190 __ addl(scratch, Immediate(flags));
191 __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize));
192
193 // Probe the secondary table.
194 ProbeTable(masm, flags, kSecondary, name, scratch);
195
196 // Cache miss: Fall-through and let caller handle the miss by
197 // entering the runtime system.
198 __ bind(&miss);
199 }
200
201
202 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
203 Builtins::Name storage_extend,
204 JSObject* object,
205 int index,
206 Map* transition,
207 Register receiver_reg,
208 Register name_reg,
209 Register scratch,
210 Label* miss_label) {
211 // Check that the object isn't a smi.
212 __ testl(receiver_reg, Immediate(kSmiTagMask));
213 __ j(zero, miss_label);
214
215 // Check that the map of the object hasn't changed.
216 __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
217 Handle<Map>(object->map()));
218 __ j(not_equal, miss_label);
219
220 // Perform global security token check if needed.
221 if (object->IsJSGlobalProxy()) {
222 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
223 }
224
225 // Stub never generated for non-global objects that require access
226 // checks.
227 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
228
229 // Perform map transition for the receiver if necessary.
230 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
231 // The properties must be extended before we can store the value.
232 // We jump to a runtime call that extends the properties array.
233 __ Move(rcx, Handle<Map>(transition));
234 Handle<Code> ic(Builtins::builtin(storage_extend));
235 __ Jump(ic, RelocInfo::CODE_TARGET);
236 return;
237 }
238
239 if (transition != NULL) {
240 // Update the map of the object; no write barrier updating is
241 // needed because the map is never in new space.
242 __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset),
243 Handle<Map>(transition));
244 }
245
246 // Adjust for the number of properties stored in the object. Even in the
247 // face of a transition we can use the old map here because the size of the
248 // object and the number of in-object properties is not going to change.
249 index -= object->map()->inobject_properties();
250
251 if (index < 0) {
252 // Set the property straight into the object.
253 int offset = object->map()->instance_size() + (index * kPointerSize);
254 __ movq(FieldOperand(receiver_reg, offset), rax);
255
256 // Update the write barrier for the array address.
257 // Pass the value being stored in the now unused name_reg.
258 __ movq(name_reg, rax);
259 __ RecordWrite(receiver_reg, offset, name_reg, scratch);
260 } else {
261 // Write to the properties array.
262 int offset = index * kPointerSize + FixedArray::kHeaderSize;
263 // Get the properties array (optimistically).
264 __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
265 __ movq(FieldOperand(scratch, offset), rax);
266
267 // Update the write barrier for the array address.
268 // Pass the value being stored in the now unused name_reg.
269 __ movq(name_reg, rax);
270 __ RecordWrite(scratch, offset, name_reg, receiver_reg);
271 }
272
273 // Return the value (register rax).
274 __ ret(0);
275 }
276
277
278 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
279 Register receiver,
280 Register scratch,
281 Label* miss_label) {
282 // Check that the receiver isn't a smi.
283 __ testl(receiver, Immediate(kSmiTagMask));
284 __ j(zero, miss_label);
285
286 // Check that the object is a JS array.
287 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
288 __ j(not_equal, miss_label);
289
290 // Load length directly from the JS array.
291 __ movq(rax, FieldOperand(receiver, JSArray::kLengthOffset));
292 __ ret(0);
293 }
294
295
296 // Generate code to check if an object is a string. If the object is
297 // a string, the map's instance type is left in the scratch register.
298 static void GenerateStringCheck(MacroAssembler* masm,
299 Register receiver,
300 Register scratch,
301 Label* smi,
302 Label* non_string_object) {
303 // Check that the object isn't a smi.
304 __ testl(receiver, Immediate(kSmiTagMask));
305 __ j(zero, smi);
306
307 // Check that the object is a string.
308 __ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
309 __ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
310 ASSERT(kNotStringTag != 0);
311 __ testl(scratch, Immediate(kNotStringTag));
312 __ j(not_zero, non_string_object);
313 }
314
315
316 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
317 Register receiver,
318 Register scratch,
319 Label* miss) {
320 Label load_length, check_wrapper;
321
322 // Check if the object is a string leaving the instance type in the
323 // scratch register.
324 GenerateStringCheck(masm, receiver, scratch, miss, &check_wrapper);
325
326 // Load length directly from the string.
327 __ bind(&load_length);
328 __ and_(scratch, Immediate(kStringSizeMask));
329 __ movl(rax, FieldOperand(receiver, String::kLengthOffset));
330 // rcx is also the receiver.
331 __ lea(rcx, Operand(scratch, String::kLongLengthShift));
332 __ shr(rax); // rcx is implicit shift register.
333 __ shl(rax, Immediate(kSmiTagSize));
334 __ ret(0);
335
336 // Check if the object is a JSValue wrapper.
337 __ bind(&check_wrapper);
338 __ cmpl(scratch, Immediate(JS_VALUE_TYPE));
339 __ j(not_equal, miss);
340
341 // Check if the wrapped value is a string and load the length
342 // directly if it is.
343 __ movq(receiver, FieldOperand(receiver, JSValue::kValueOffset));
344 GenerateStringCheck(masm, receiver, scratch, miss, miss);
345 __ jmp(&load_length);
346 }
347
348
349 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
350 Register receiver,
351 Register result,
352 Register scratch,
353 Label* miss_label) {
354 __ TryGetFunctionPrototype(receiver, result, miss_label);
355 if (!result.is(rax)) __ movq(rax, result);
356 __ ret(0);
357 }
358
359 #undef __
360
39 #define __ ACCESS_MASM((masm())) 361 #define __ ACCESS_MASM((masm()))
40 362
41 363
42 Object* CallStubCompiler::CompileCallConstant(Object* object, 364 Object* CallStubCompiler::CompileCallConstant(Object* object,
43 JSObject* holder, 365 JSObject* holder,
44 JSFunction* function, 366 JSFunction* function,
45 String* name, 367 String* name,
46 StubCompiler::CheckType check) { 368 StubCompiler::CheckType check) {
47 // ----------- S t a t e ------------- 369 // ----------- S t a t e -------------
48 // ----------------------------------- 370 // -----------------------------------
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 // Handle call cache miss. 542 // Handle call cache miss.
221 __ bind(&miss); 543 __ bind(&miss);
222 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 544 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
223 __ Jump(ic, RelocInfo::CODE_TARGET); 545 __ Jump(ic, RelocInfo::CODE_TARGET);
224 546
225 // Return the generated code. 547 // Return the generated code.
226 return GetCode(FIELD, name); 548 return GetCode(FIELD, name);
227 } 549 }
228 550
229 551
230 Object* CallStubCompiler::CompileCallInterceptor(Object* a, 552 Object* CallStubCompiler::CompileCallInterceptor(Object* object,
231 JSObject* b, 553 JSObject* holder,
232 String* c) { 554 String* name) {
233 // TODO(X64): Implement a real stub. 555 // ----------- S t a t e -------------
234 return Failure::InternalError(); 556 // -----------------------------------
557 Label miss;
558
559 // Get the number of arguments.
560 const int argc = arguments().immediate();
561
562 // Get the receiver from the stack.
563 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
564
565 // Check that the receiver isn't a smi.
566 __ testl(rdx, Immediate(kSmiTagMask));
567 __ j(zero, &miss);
568
569 // Check that maps have not changed and compute the holder register.
570 Register reg =
571 CheckPrototypes(JSObject::cast(object), rdx, holder,
572 rbx, rcx, name, &miss);
573
574 // Enter an internal frame.
575 __ EnterInternalFrame();
576
577 // Push arguments on the expression stack.
578 PushInterceptorArguments(masm(),
579 rdx,
580 reg,
581 Operand(rbp, (argc + 3) * kPointerSize),
582 holder,
583 holder->InterceptorPropertyLookupHint(name));
584
585 // Perform call.
586 ExternalReference load_interceptor =
587 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
588 __ movq(rax, Immediate(6));
589 __ movq(rbx, load_interceptor);
590
591 CEntryStub stub;
592 __ CallStub(&stub);
593
594 // Move result to rdi and restore receiver.
595 __ movq(rdi, rax);
596 __ movq(rdx, Operand(rbp, (argc + 2) * kPointerSize)); // receiver
597
598 // Exit frame.
599 __ LeaveInternalFrame();
600
601 // Check that the function really is a function.
602 __ testl(rdi, Immediate(kSmiTagMask));
603 __ j(zero, &miss);
604 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx);
605 __ j(not_equal, &miss);
606
607 // Patch the receiver on the stack with the global proxy if
608 // necessary.
609 if (object->IsGlobalObject()) {
610 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
611 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
612 }
613
614 // Invoke the function.
615 __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION);
616
617 // Handle load cache miss.
618 __ bind(&miss);
619 Handle<Code> ic = ComputeCallMiss(argc);
620 __ Jump(ic, RelocInfo::CODE_TARGET);
621
622 // Return the generated code.
623 return GetCode(INTERCEPTOR, name);
235 } 624 }
236 625
237 626
238 627
239 Object* CallStubCompiler::CompileCallGlobal(JSObject* object, 628 Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
240 GlobalObject* holder, 629 GlobalObject* holder,
241 JSGlobalPropertyCell* cell, 630 JSGlobalPropertyCell* cell,
242 JSFunction* function, 631 JSFunction* function,
243 String* name) { 632 String* name) {
244 // ----------- S t a t e ------------- 633 // ----------- S t a t e -------------
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 __ bind(&miss); 687 __ bind(&miss);
299 __ IncrementCounter(&Counters::call_global_inline_miss, 1); 688 __ IncrementCounter(&Counters::call_global_inline_miss, 1);
300 Handle<Code> ic = ComputeCallMiss(arguments().immediate()); 689 Handle<Code> ic = ComputeCallMiss(arguments().immediate());
301 __ Jump(ic, RelocInfo::CODE_TARGET); 690 __ Jump(ic, RelocInfo::CODE_TARGET);
302 691
303 // Return the generated code. 692 // Return the generated code.
304 return GetCode(NORMAL, name); 693 return GetCode(NORMAL, name);
305 } 694 }
306 695
307 696
308 Object* LoadStubCompiler::CompileLoadCallback(JSObject* a, 697 Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
309 JSObject* b, 698 JSObject* holder,
310 AccessorInfo* c, 699 AccessorInfo* callback,
311 String* d) { 700 String* name) {
312 // TODO(X64): Implement a real stub. 701 // ----------- S t a t e -------------
313 return Failure::InternalError(); 702 // -- rcx : name
703 // -- rsp[0] : return address
704 // -- rsp[8] : receiver
705 // -----------------------------------
706 Label miss;
707
708 __ movq(rax, Operand(rsp, kPointerSize));
709 GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx,
710 callback, name, &miss);
711 __ bind(&miss);
712 GenerateLoadMiss(masm(), Code::LOAD_IC);
713
714 // Return the generated code.
715 return GetCode(CALLBACKS, name);
314 } 716 }
315 717
316 718
317 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, 719 Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
318 JSObject* holder, 720 JSObject* holder,
319 Object* value, 721 Object* value,
320 String* name) { 722 String* name) {
321 // ----------- S t a t e ------------- 723 // ----------- S t a t e -------------
322 // -- rcx : name 724 // -- rcx : name
323 // -- rsp[0] : return address 725 // -- rsp[0] : return address
(...skipping 25 matching lines...) Expand all
349 __ movq(rax, Operand(rsp, kPointerSize)); 751 __ movq(rax, Operand(rsp, kPointerSize));
350 GenerateLoadField(object, holder, rax, rbx, rdx, index, name, &miss); 752 GenerateLoadField(object, holder, rax, rbx, rdx, index, name, &miss);
351 __ bind(&miss); 753 __ bind(&miss);
352 GenerateLoadMiss(masm(), Code::LOAD_IC); 754 GenerateLoadMiss(masm(), Code::LOAD_IC);
353 755
354 // Return the generated code. 756 // Return the generated code.
355 return GetCode(FIELD, name); 757 return GetCode(FIELD, name);
356 } 758 }
357 759
358 760
359 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* a, 761 Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
360 JSObject* b, 762 JSObject* holder,
361 String* c) { 763 String* name) {
362 // TODO(X64): Implement a real stub. 764 // ----------- S t a t e -------------
363 return Failure::InternalError(); 765 // -- rcx : name
766 // -- rsp[0] : return address
767 // -- rsp[8] : receiver
768 // -----------------------------------
769 Label miss;
770
771 __ movq(rax, Operand(rsp, kPointerSize));
772 // TODO(368): Compile in the whole chain: all the interceptors in
773 // prototypes and ultimate answer.
774 GenerateLoadInterceptor(receiver,
775 holder,
776 holder->InterceptorPropertyLookupHint(name),
777 rax,
778 rcx,
779 rdx,
780 rbx,
781 name,
782 &miss);
783
784 __ bind(&miss);
785 GenerateLoadMiss(masm(), Code::LOAD_IC);
786
787 // Return the generated code.
788 return GetCode(INTERCEPTOR, name);
364 } 789 }
365 790
366 791
367 Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, 792 Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
368 GlobalObject* holder, 793 GlobalObject* holder,
369 JSGlobalPropertyCell* cell, 794 JSGlobalPropertyCell* cell,
370 String* name, 795 String* name,
371 bool is_dont_delete) { 796 bool is_dont_delete) {
372 // ----------- S t a t e ------------- 797 // ----------- S t a t e -------------
373 // -- rcx : name 798 // -- rcx : name
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 833
409 __ bind(&miss); 834 __ bind(&miss);
410 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1); 835 __ IncrementCounter(&Counters::named_load_global_inline_miss, 1);
411 GenerateLoadMiss(masm(), Code::LOAD_IC); 836 GenerateLoadMiss(masm(), Code::LOAD_IC);
412 837
413 // Return the generated code. 838 // Return the generated code.
414 return GetCode(NORMAL, name); 839 return GetCode(NORMAL, name);
415 } 840 }
416 841
417 842
418 Object* StoreStubCompiler::CompileStoreCallback(JSObject* a, 843 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
419 AccessorInfo* b, 844 // ----------- S t a t e -------------
420 String* c) { 845 // -- rsp[0] : return address
421 // TODO(X64): Implement a real stub. 846 // -- rsp[8] : name
422 return Failure::InternalError(); 847 // -- rsp[16] : receiver
848 // -----------------------------------
849 Label miss;
850
851 __ movq(rax, Operand(rsp, kPointerSize));
852 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
853 __ IncrementCounter(&Counters::keyed_load_array_length, 1);
854
855 // Check that the name has not changed.
856 __ Cmp(rax, Handle<String>(name));
857 __ j(not_equal, &miss);
858
859 GenerateLoadArrayLength(masm(), rcx, rdx, &miss);
860 __ bind(&miss);
861 __ DecrementCounter(&Counters::keyed_load_array_length, 1);
862 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
863
864 // Return the generated code.
865 return GetCode(CALLBACKS, name);
423 } 866 }
424 867
425 868
869 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
870 JSObject* object,
871 JSObject* holder,
872 AccessorInfo* callback) {
873 UNIMPLEMENTED();
874 return NULL;
875 }
876
877
878 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
879 JSObject* receiver,
880 JSObject* holder,
881 Object* value) {
882 // ----------- S t a t e -------------
883 // -- rsp[0] : return address
884 // -- rsp[8] : name
885 // -- rsp[16] : receiver
886 // -----------------------------------
887 Label miss;
888
889 __ movq(rax, Operand(rsp, kPointerSize));
890 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
891 __ IncrementCounter(&Counters::keyed_load_constant_function, 1);
892
893 // Check that the name has not changed.
894 __ Cmp(rax, Handle<String>(name));
895 __ j(not_equal, &miss);
896
897 GenerateLoadConstant(receiver, holder, rcx, rbx, rdx,
898 value, name, &miss);
899 __ bind(&miss);
900 __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
901 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
902
903 // Return the generated code.
904 return GetCode(CONSTANT_FUNCTION, name);
905 }
906
907
908 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
909 // ----------- S t a t e -------------
910 // -- rsp[0] : return address
911 // -- rsp[8] : name
912 // -- rsp[16] : receiver
913 // -----------------------------------
914 Label miss;
915
916 __ movq(rax, Operand(rsp, kPointerSize));
917 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
918 __ IncrementCounter(&Counters::keyed_load_function_prototype, 1);
919
920 // Check that the name has not changed.
921 __ Cmp(rax, Handle<String>(name));
922 __ j(not_equal, &miss);
923
924 GenerateLoadFunctionPrototype(masm(), rcx, rdx, rbx, &miss);
925 __ bind(&miss);
926 __ DecrementCounter(&Counters::keyed_load_function_prototype, 1);
927 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
928
929 // Return the generated code.
930 return GetCode(CALLBACKS, name);
931 }
932
933
934 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* object,
935 JSObject* holder,
936 String* name) {
937 UNIMPLEMENTED();
938 return NULL;
939 }
940
941
942 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
943 // ----------- S t a t e -------------
944 // -- rsp[0] : return address
945 // -- rsp[8] : name
946 // -- rsp[16] : receiver
947 // -----------------------------------
948 Label miss;
949
950 __ movq(rax, Operand(rsp, kPointerSize));
951 __ movq(rcx, Operand(rsp, 2 * kPointerSize));
952 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
953
954 // Check that the name has not changed.
955 __ Cmp(rax, Handle<String>(name));
956 __ j(not_equal, &miss);
957
958 GenerateLoadStringLength(masm(), rcx, rdx, &miss);
959 __ bind(&miss);
960 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
961 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
962
963 // Return the generated code.
964 return GetCode(CALLBACKS, name);
965 }
966
967
968 Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
969 AccessorInfo* callback,
970 String* name) {
971 // ----------- S t a t e -------------
972 // -- rax : value
973 // -- rcx : name
974 // -- rsp[0] : return address
975 // -- rsp[8] : receiver
976 // -----------------------------------
977 Label miss;
978
979 // Get the object from the stack.
980 __ movq(rbx, Operand(rsp, 1 * kPointerSize));
981
982 // Check that the object isn't a smi.
983 __ testl(rbx, Immediate(kSmiTagMask));
984 __ j(zero, &miss);
985
986 // Check that the map of the object hasn't changed.
987 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
988 Handle<Map>(object->map()));
989 __ j(not_equal, &miss);
990
991 // Perform global security token check if needed.
992 if (object->IsJSGlobalProxy()) {
993 __ CheckAccessGlobalProxy(rbx, rdx, &miss);
994 }
995
996 // Stub never generated for non-global objects that require access
997 // checks.
998 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
999
1000 __ pop(rbx); // remove the return address
1001 __ push(Operand(rsp, 0)); // receiver
1002 __ Push(Handle<AccessorInfo>(callback)); // callback info
1003 __ push(rcx); // name
1004 __ push(rax); // value
1005 __ push(rbx); // restore return address
1006
1007 // Do tail-call to the runtime system.
1008 ExternalReference store_callback_property =
1009 ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
1010 __ TailCallRuntime(store_callback_property, 4);
1011
1012 // Handle store cache miss.
1013 __ bind(&miss);
1014 __ Move(rcx, Handle<String>(name)); // restore name
1015 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1016 __ Jump(ic, RelocInfo::CODE_TARGET);
1017
1018 // Return the generated code.
1019 return GetCode(CALLBACKS, name);
1020 }
1021
1022
426 Object* StoreStubCompiler::CompileStoreField(JSObject* object, 1023 Object* StoreStubCompiler::CompileStoreField(JSObject* object,
427 int index, 1024 int index,
428 Map* transition, 1025 Map* transition,
429 String* name) { 1026 String* name) {
430 // ----------- S t a t e ------------- 1027 // ----------- S t a t e -------------
431 // -- rax : value 1028 // -- rax : value
432 // -- rcx : name 1029 // -- rcx : name
433 // -- rsp[0] : return address 1030 // -- rsp[0] : return address
434 // -- rsp[8] : receiver 1031 // -- rsp[8] : receiver
435 // ----------------------------------- 1032 // -----------------------------------
(...skipping 15 matching lines...) Expand all
451 __ bind(&miss); 1048 __ bind(&miss);
452 __ Move(rcx, Handle<String>(name)); // restore name 1049 __ Move(rcx, Handle<String>(name)); // restore name
453 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 1050 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
454 __ Jump(ic, RelocInfo::CODE_TARGET); 1051 __ Jump(ic, RelocInfo::CODE_TARGET);
455 1052
456 // Return the generated code. 1053 // Return the generated code.
457 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 1054 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
458 } 1055 }
459 1056
460 1057
461 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* a, String* b) { 1058 Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
462 // TODO(X64): Implement a real stub. 1059 String* name) {
463 return Failure::InternalError(); 1060 // ----------- S t a t e -------------
1061 // -- rax : value
1062 // -- rcx : name
1063 // -- rsp[0] : return address
1064 // -- rsp[8] : receiver
1065 // -----------------------------------
1066 Label miss;
1067
1068 // Get the object from the stack.
1069 __ movq(rbx, Operand(rsp, 1 * kPointerSize));
1070
1071 // Check that the object isn't a smi.
1072 __ testl(rbx, Immediate(kSmiTagMask));
1073 __ j(zero, &miss);
1074
1075 // Check that the map of the object hasn't changed.
1076 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
1077 Handle<Map>(receiver->map()));
1078 __ j(not_equal, &miss);
1079
1080 // Perform global security token check if needed.
1081 if (receiver->IsJSGlobalProxy()) {
1082 __ CheckAccessGlobalProxy(rbx, rdx, &miss);
1083 }
1084
1085 // Stub never generated for non-global objects that require access
1086 // checks.
1087 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
1088
1089 __ pop(rbx); // remove the return address
1090 __ push(Operand(rsp, 0)); // receiver
1091 __ push(rcx); // name
1092 __ push(rax); // value
1093 __ push(rbx); // restore return address
1094
1095 // Do tail-call to the runtime system.
1096 ExternalReference store_ic_property =
1097 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
1098 __ TailCallRuntime(store_ic_property, 3);
1099
1100 // Handle store cache miss.
1101 __ bind(&miss);
1102 __ Move(rcx, Handle<String>(name)); // restore name
1103 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
1104 __ Jump(ic, RelocInfo::CODE_TARGET);
1105
1106 // Return the generated code.
1107 return GetCode(INTERCEPTOR, name);
464 } 1108 }
465 1109
466 1110
467 Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, 1111 Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
468 JSGlobalPropertyCell* cell, 1112 JSGlobalPropertyCell* cell,
469 String* name) { 1113 String* name) {
470 // ----------- S t a t e ------------- 1114 // ----------- S t a t e -------------
471 // -- rax : value 1115 // -- rax : value
472 // -- rcx : name 1116 // -- rcx : name
473 // -- rsp[0] : return address 1117 // -- rsp[0] : return address
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 1167
524 __ bind(&miss); 1168 __ bind(&miss);
525 __ DecrementCounter(&Counters::keyed_load_field, 1); 1169 __ DecrementCounter(&Counters::keyed_load_field, 1);
526 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1170 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
527 1171
528 // Return the generated code. 1172 // Return the generated code.
529 return GetCode(FIELD, name); 1173 return GetCode(FIELD, name);
530 } 1174 }
531 1175
532 1176
533 Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
534 // TODO(X64): Implement a real stub.
535 return Failure::InternalError();
536 }
537
538 Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
539 JSObject* object,
540 JSObject* holder,
541 AccessorInfo* callback) {
542 // TODO(X64): Implement a real stub.
543 return Failure::InternalError();
544 }
545
546 Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
547 JSObject* object,
548 JSObject* holder,
549 Object* callback) {
550 // TODO(X64): Implement a real stub.
551 return Failure::InternalError();
552 }
553
554
555 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
556 // TODO(X64): Implement a real stub.
557 return Failure::InternalError();
558 }
559
560 Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* object,
561 JSObject* holder,
562 String* name) {
563 // TODO(X64): Implement a real stub.
564 return Failure::InternalError();
565 }
566
567 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
568 // TODO(X64): Implement a real stub.
569 return Failure::InternalError();
570 }
571
572
573 Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, 1177 Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
574 int index, 1178 int index,
575 Map* transition, 1179 Map* transition,
576 String* name) { 1180 String* name) {
577 // ----------- S t a t e ------------- 1181 // ----------- S t a t e -------------
578 // -- rax : value 1182 // -- rax : value
579 // -- rsp[0] : return address 1183 // -- rsp[0] : return address
580 // -- rsp[8] : key 1184 // -- rsp[8] : key
581 // -- rsp[16] : receiver 1185 // -- rsp[16] : receiver
582 // ----------------------------------- 1186 // -----------------------------------
583 Label miss; 1187 Label miss;
584 1188
585 __ IncrementCounter(&Counters::keyed_store_field, 1); 1189 __ IncrementCounter(&Counters::keyed_store_field, 1);
586 1190
587 // Get the name from the stack. 1191 // Get the name from the stack.
588 __ movq(rcx, Operand(rsp, 1 * kPointerSize)); 1192 __ movq(rcx, Operand(rsp, 1 * kPointerSize));
589 // Check that the name has not changed. 1193 // Check that the name has not changed.
590 __ Cmp(rcx, Handle<String>(name)); 1194 __ Cmp(rcx, Handle<String>(name));
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 __ LeaveInternalFrame(); 1234 __ LeaveInternalFrame();
631 1235
632 // Do a tail-call of the compiled function. 1236 // Do a tail-call of the compiled function.
633 __ lea(rcx, FieldOperand(rax, Code::kHeaderSize)); 1237 __ lea(rcx, FieldOperand(rax, Code::kHeaderSize));
634 __ jmp(rcx); 1238 __ jmp(rcx);
635 1239
636 return GetCodeWithFlags(flags, "LazyCompileStub"); 1240 return GetCodeWithFlags(flags, "LazyCompileStub");
637 } 1241 }
638 1242
639 1243
1244
1245 void StubCompiler::GenerateLoadInterceptor(JSObject* object,
1246 JSObject* holder,
1247 Smi* lookup_hint,
1248 Register receiver,
1249 Register name_reg,
1250 Register scratch1,
1251 Register scratch2,
1252 String* name,
1253 Label* miss) {
1254 // Check that the receiver isn't a smi.
1255 __ testl(receiver, Immediate(kSmiTagMask));
1256 __ j(zero, miss);
1257
1258 // Check that the maps haven't changed.
1259 Register reg =
1260 CheckPrototypes(object, receiver, holder,
1261 scratch1, scratch2, name, miss);
1262
1263 // Push the arguments on the JS stack of the caller.
1264 __ pop(scratch2); // remove return address
1265 PushInterceptorArguments(masm(),
1266 receiver,
1267 reg,
1268 name_reg,
1269 holder,
1270 lookup_hint);
1271 __ push(scratch2); // restore return address
1272
1273 // Do tail-call to the runtime system.
1274 ExternalReference load_ic_property =
1275 ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
1276 __ TailCallRuntime(load_ic_property, 6);
1277 }
1278
1279
1280 void StubCompiler::GenerateLoadCallback(JSObject* object,
1281 JSObject* holder,
1282 Register receiver,
1283 Register name_reg,
1284 Register scratch1,
1285 Register scratch2,
1286 AccessorInfo* callback,
1287 String* name,
1288 Label* miss) {
1289 // Check that the receiver isn't a smi.
1290 __ testl(receiver, Immediate(kSmiTagMask));
1291 __ j(zero, miss);
1292
1293 // Check that the maps haven't changed.
1294 Register reg =
1295 CheckPrototypes(object, receiver, holder,
1296 scratch1, scratch2, name, miss);
1297
1298 // Push the arguments on the JS stack of the caller.
1299 __ pop(scratch2); // remove return address
1300 __ push(receiver); // receiver
1301 __ push(reg); // holder
1302 __ Move(reg, Handle<AccessorInfo>(callback)); // callback data
1303 __ push(reg);
1304 __ push(FieldOperand(reg, AccessorInfo::kDataOffset));
1305 __ push(name_reg); // name
1306 __ push(scratch2); // restore return address
1307
1308 // Do tail-call to the runtime system.
1309 ExternalReference load_callback_property =
1310 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
1311 __ TailCallRuntime(load_callback_property, 5);
1312 }
1313
1314
640 Register StubCompiler::CheckPrototypes(JSObject* object, 1315 Register StubCompiler::CheckPrototypes(JSObject* object,
641 Register object_reg, 1316 Register object_reg,
642 JSObject* holder, 1317 JSObject* holder,
643 Register holder_reg, 1318 Register holder_reg,
644 Register scratch, 1319 Register scratch,
645 String* name, 1320 String* name,
646 Label* miss) { 1321 Label* miss) {
647 // Check that the maps haven't changed. 1322 // Check that the maps haven't changed.
648 Register result = 1323 Register result =
649 __ CheckMaps(object, object_reg, holder, holder_reg, scratch, miss); 1324 __ CheckMaps(object, object_reg, holder, holder_reg, scratch, miss);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
714 scratch1, scratch2, name, miss); 1389 scratch1, scratch2, name, miss);
715 1390
716 // Return the constant value. 1391 // Return the constant value.
717 __ Move(rax, Handle<Object>(value)); 1392 __ Move(rax, Handle<Object>(value));
718 __ ret(0); 1393 __ ret(0);
719 } 1394 }
720 1395
721 1396
722 #undef __ 1397 #undef __
723 1398
724 //-----------------------------------------------------------------------------
725 // StubCompiler static helper functions
726
727 #define __ ACCESS_MASM(masm)
728
729
730 static void ProbeTable(MacroAssembler* masm,
731 Code::Flags flags,
732 StubCache::Table table,
733 Register name,
734 Register offset) {
735 ExternalReference key_offset(SCTableReference::keyReference(table));
736 Label miss;
737
738 __ movq(kScratchRegister, key_offset);
739 // Check that the key in the entry matches the name.
740 __ cmpl(name, Operand(kScratchRegister, offset, times_4, 0));
741 __ j(not_equal, &miss);
742 // Get the code entry from the cache.
743 // Use key_offset + kPointerSize, rather than loading value_offset.
744 __ movq(kScratchRegister,
745 Operand(kScratchRegister, offset, times_4, kPointerSize));
746 // Check that the flags match what we're looking for.
747 __ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset));
748 __ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup));
749 __ cmpl(offset, Immediate(flags));
750 __ j(not_equal, &miss);
751
752 // Jump to the first instruction in the code stub.
753 __ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag));
754 __ jmp(kScratchRegister);
755
756 __ bind(&miss);
757 }
758
759
760 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
761 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
762 Code* code = NULL;
763 if (kind == Code::LOAD_IC) {
764 code = Builtins::builtin(Builtins::LoadIC_Miss);
765 } else {
766 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
767 }
768
769 Handle<Code> ic(code);
770 __ Jump(ic, RelocInfo::CODE_TARGET);
771 }
772
773
774 void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
775 int index,
776 Register prototype) {
777 // Load the global or builtins object from the current context.
778 __ movq(prototype,
779 Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
780 // Load the global context from the global or builtins object.
781 __ movq(prototype,
782 FieldOperand(prototype, GlobalObject::kGlobalContextOffset));
783 // Load the function from the global context.
784 __ movq(prototype, Operand(prototype, Context::SlotOffset(index)));
785 // Load the initial map. The global functions all have initial maps.
786 __ movq(prototype,
787 FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset));
788 // Load the prototype from the initial map.
789 __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
790 }
791
792
793 // Load a fast property out of a holder object (src). In-object properties
794 // are loaded directly otherwise the property is loaded from the properties
795 // fixed array.
796 void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
797 Register dst, Register src,
798 JSObject* holder, int index) {
799 // Adjust for the number of properties stored in the holder.
800 index -= holder->map()->inobject_properties();
801 if (index < 0) {
802 // Get the property straight out of the holder.
803 int offset = holder->map()->instance_size() + (index * kPointerSize);
804 __ movq(dst, FieldOperand(src, offset));
805 } else {
806 // Calculate the offset into the properties array.
807 int offset = index * kPointerSize + FixedArray::kHeaderSize;
808 __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset));
809 __ movq(dst, FieldOperand(dst, offset));
810 }
811 }
812
813
814 void StubCache::GenerateProbe(MacroAssembler* masm,
815 Code::Flags flags,
816 Register receiver,
817 Register name,
818 Register scratch,
819 Register extra) {
820 Label miss;
821 USE(extra); // The register extra is not used on the X64 platform.
822 // Make sure that code is valid. The shifting code relies on the
823 // entry size being 16.
824 ASSERT(sizeof(Entry) == 16);
825
826 // Make sure the flags do not name a specific type.
827 ASSERT(Code::ExtractTypeFromFlags(flags) == 0);
828
829 // Make sure that there are no register conflicts.
830 ASSERT(!scratch.is(receiver));
831 ASSERT(!scratch.is(name));
832
833 // Check that the receiver isn't a smi.
834 __ testl(receiver, Immediate(kSmiTagMask));
835 __ j(zero, &miss);
836
837 // Get the map of the receiver and compute the hash.
838 __ movl(scratch, FieldOperand(name, String::kLengthOffset));
839 // Use only the low 32 bits of the map pointer.
840 __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
841 __ xor_(scratch, Immediate(flags));
842 __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
843
844 // Probe the primary table.
845 ProbeTable(masm, flags, kPrimary, name, scratch);
846
847 // Primary miss: Compute hash for secondary probe.
848 __ movl(scratch, FieldOperand(name, String::kLengthOffset));
849 __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
850 __ xor_(scratch, Immediate(flags));
851 __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize));
852 __ subl(scratch, name);
853 __ addl(scratch, Immediate(flags));
854 __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize));
855
856 // Probe the secondary table.
857 ProbeTable(masm, flags, kSecondary, name, scratch);
858
859 // Cache miss: Fall-through and let caller handle the miss by
860 // entering the runtime system.
861 __ bind(&miss);
862 }
863
864
865 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
866 Builtins::Name storage_extend,
867 JSObject* object,
868 int index,
869 Map* transition,
870 Register receiver_reg,
871 Register name_reg,
872 Register scratch,
873 Label* miss_label) {
874 // Check that the object isn't a smi.
875 __ testl(receiver_reg, Immediate(kSmiTagMask));
876 __ j(zero, miss_label);
877
878 // Check that the map of the object hasn't changed.
879 __ Cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
880 Handle<Map>(object->map()));
881 __ j(not_equal, miss_label);
882
883 // Perform global security token check if needed.
884 if (object->IsJSGlobalProxy()) {
885 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
886 }
887
888 // Stub never generated for non-global objects that require access
889 // checks.
890 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
891
892 // Perform map transition for the receiver if necessary.
893 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
894 // The properties must be extended before we can store the value.
895 // We jump to a runtime call that extends the properties array.
896 __ Move(rcx, Handle<Map>(transition));
897 Handle<Code> ic(Builtins::builtin(storage_extend));
898 __ Jump(ic, RelocInfo::CODE_TARGET);
899 return;
900 }
901
902 if (transition != NULL) {
903 // Update the map of the object; no write barrier updating is
904 // needed because the map is never in new space.
905 __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset),
906 Handle<Map>(transition));
907 }
908
909 // Adjust for the number of properties stored in the object. Even in the
910 // face of a transition we can use the old map here because the size of the
911 // object and the number of in-object properties is not going to change.
912 index -= object->map()->inobject_properties();
913
914 if (index < 0) {
915 // Set the property straight into the object.
916 int offset = object->map()->instance_size() + (index * kPointerSize);
917 __ movq(FieldOperand(receiver_reg, offset), rax);
918
919 // Update the write barrier for the array address.
920 // Pass the value being stored in the now unused name_reg.
921 __ movq(name_reg, rax);
922 __ RecordWrite(receiver_reg, offset, name_reg, scratch);
923 } else {
924 // Write to the properties array.
925 int offset = index * kPointerSize + FixedArray::kHeaderSize;
926 // Get the properties array (optimistically).
927 __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
928 __ movq(FieldOperand(scratch, offset), rax);
929
930 // Update the write barrier for the array address.
931 // Pass the value being stored in the now unused name_reg.
932 __ movq(name_reg, rax);
933 __ RecordWrite(scratch, offset, name_reg, receiver_reg);
934 }
935
936 // Return the value (register rax).
937 __ ret(0);
938 }
939
940
941 #undef __
942
943
944 } } // namespace v8::internal 1399 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698