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

Side by Side Diff: src/ic/x64/ic-x64.cc

Issue 1199983002: [strong] Implement strong property access semantics (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: add TODOs Created 5 years, 5 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/ic/ppc/ic-ppc.cc ('k') | src/ic/x87/handler-compiler-x87.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // 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/codegen.h" 9 #include "src/codegen.h"
10 #include "src/ic/ic.h" 10 #include "src/ic/ic.h"
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 FieldOperand(map, Map::kBitFieldOffset), 164 FieldOperand(map, Map::kBitFieldOffset),
165 Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); 165 Immediate((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit)));
166 __ j(not_zero, slow); 166 __ j(not_zero, slow);
167 } 167 }
168 168
169 169
170 // Loads an indexed element from a fast case array. 170 // Loads an indexed element from a fast case array.
171 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, 171 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
172 Register key, Register elements, 172 Register key, Register elements,
173 Register scratch, Register result, 173 Register scratch, Register result,
174 Label* slow) { 174 Label* slow, LanguageMode language_mode) {
175 // Register use: 175 // Register use:
176 // 176 //
177 // receiver - holds the receiver on entry. 177 // receiver - holds the receiver on entry.
178 // Unchanged unless 'result' is the same register. 178 // Unchanged unless 'result' is the same register.
179 // 179 //
180 // key - holds the smi key on entry. 180 // key - holds the smi key on entry.
181 // Unchanged unless 'result' is the same register. 181 // Unchanged unless 'result' is the same register.
182 // 182 //
183 // result - holds the result on exit if the load succeeded. 183 // result - holds the result on exit if the load succeeded.
184 // Allowed to be the the same as 'receiver' or 'key'. 184 // Allowed to be the the same as 'receiver' or 'key'.
185 // Unchanged on bailout so 'receiver' and 'key' can be safely 185 // Unchanged on bailout so 'receiver' and 'key' can be safely
186 // used by further computation. 186 // used by further computation.
187 // 187 //
188 // Scratch registers: 188 // Scratch registers:
189 // 189 //
190 // elements - holds the elements of the receiver and its prototypes. 190 // elements - holds the elements of the receiver and its prototypes.
191 // 191 //
192 // scratch - used to hold maps, prototypes, and the loaded value. 192 // scratch - used to hold maps, prototypes, and the loaded value.
193 Label check_prototypes, check_next_prototype; 193 Label check_prototypes, check_next_prototype;
194 Label done, in_bounds, return_undefined; 194 Label done, in_bounds, absent;
195 195
196 __ movp(elements, FieldOperand(receiver, JSObject::kElementsOffset)); 196 __ movp(elements, FieldOperand(receiver, JSObject::kElementsOffset));
197 __ AssertFastElements(elements); 197 __ AssertFastElements(elements);
198 // Check that the key (index) is within bounds. 198 // Check that the key (index) is within bounds.
199 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset)); 199 __ SmiCompare(key, FieldOperand(elements, FixedArray::kLengthOffset));
200 // Unsigned comparison rejects negative indices. 200 // Unsigned comparison rejects negative indices.
201 __ j(below, &in_bounds); 201 __ j(below, &in_bounds);
202 202
203 // Out-of-bounds. Check the prototype chain to see if we can just return 203 // Out-of-bounds. Check the prototype chain to see if we can just return
204 // 'undefined'. 204 // 'undefined'.
205 __ SmiCompare(key, Smi::FromInt(0)); 205 __ SmiCompare(key, Smi::FromInt(0));
206 __ j(less, slow); // Negative keys can't take the fast OOB path. 206 __ j(less, slow); // Negative keys can't take the fast OOB path.
207 __ bind(&check_prototypes); 207 __ bind(&check_prototypes);
208 __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 208 __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
209 __ bind(&check_next_prototype); 209 __ bind(&check_next_prototype);
210 __ movp(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); 210 __ movp(scratch, FieldOperand(scratch, Map::kPrototypeOffset));
211 // scratch: current prototype 211 // scratch: current prototype
212 __ CompareRoot(scratch, Heap::kNullValueRootIndex); 212 __ CompareRoot(scratch, Heap::kNullValueRootIndex);
213 __ j(equal, &return_undefined); 213 __ j(equal, &absent);
214 __ movp(elements, FieldOperand(scratch, JSObject::kElementsOffset)); 214 __ movp(elements, FieldOperand(scratch, JSObject::kElementsOffset));
215 __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); 215 __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset));
216 // elements: elements of current prototype 216 // elements: elements of current prototype
217 // scratch: map of current prototype 217 // scratch: map of current prototype
218 __ CmpInstanceType(scratch, JS_OBJECT_TYPE); 218 __ CmpInstanceType(scratch, JS_OBJECT_TYPE);
219 __ j(below, slow); 219 __ j(below, slow);
220 __ testb(FieldOperand(scratch, Map::kBitFieldOffset), 220 __ testb(FieldOperand(scratch, Map::kBitFieldOffset),
221 Immediate((1 << Map::kIsAccessCheckNeeded) | 221 Immediate((1 << Map::kIsAccessCheckNeeded) |
222 (1 << Map::kHasIndexedInterceptor))); 222 (1 << Map::kHasIndexedInterceptor)));
223 __ j(not_zero, slow); 223 __ j(not_zero, slow);
224 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); 224 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex);
225 __ j(not_equal, slow); 225 __ j(not_equal, slow);
226 __ jmp(&check_next_prototype); 226 __ jmp(&check_next_prototype);
227 227
228 __ bind(&return_undefined); 228 __ bind(&absent);
229 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 229 if (is_strong(language_mode)) {
230 __ jmp(&done); 230 // Strong mode accesses must throw in this case, so call the runtime.
231 __ jmp(slow);
232 } else {
233 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
234 __ jmp(&done);
235 }
231 236
232 __ bind(&in_bounds); 237 __ bind(&in_bounds);
233 // Fast case: Do the load. 238 // Fast case: Do the load.
234 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2); 239 SmiIndex index = masm->SmiToIndex(scratch, key, kPointerSizeLog2);
235 __ movp(scratch, FieldOperand(elements, index.reg, index.scale, 240 __ movp(scratch, FieldOperand(elements, index.reg, index.scale,
236 FixedArray::kHeaderSize)); 241 FixedArray::kHeaderSize));
237 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex); 242 __ CompareRoot(scratch, Heap::kTheHoleValueRootIndex);
238 // In case the loaded value is the_hole we have to check the prototype chain. 243 // In case the loaded value is the_hole we have to check the prototype chain.
239 __ j(equal, &check_prototypes); 244 __ j(equal, &check_prototypes);
240 __ Move(result, scratch); 245 __ Move(result, scratch);
(...skipping 26 matching lines...) Expand all
267 // bit test is enough. 272 // bit test is enough.
268 STATIC_ASSERT(kNotInternalizedTag != 0); 273 STATIC_ASSERT(kNotInternalizedTag != 0);
269 __ testb(FieldOperand(map, Map::kInstanceTypeOffset), 274 __ testb(FieldOperand(map, Map::kInstanceTypeOffset),
270 Immediate(kIsNotInternalizedMask)); 275 Immediate(kIsNotInternalizedMask));
271 __ j(not_zero, not_unique); 276 __ j(not_zero, not_unique);
272 277
273 __ bind(&unique); 278 __ bind(&unique);
274 } 279 }
275 280
276 281
277 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { 282 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
283 LanguageMode language_mode) {
278 // The return address is on the stack. 284 // The return address is on the stack.
279 Label slow, check_name, index_smi, index_name, property_array_property; 285 Label slow, check_name, index_smi, index_name, property_array_property;
280 Label probe_dictionary, check_number_dictionary; 286 Label probe_dictionary, check_number_dictionary;
281 287
282 Register receiver = LoadDescriptor::ReceiverRegister(); 288 Register receiver = LoadDescriptor::ReceiverRegister();
283 Register key = LoadDescriptor::NameRegister(); 289 Register key = LoadDescriptor::NameRegister();
284 DCHECK(receiver.is(rdx)); 290 DCHECK(receiver.is(rdx));
285 DCHECK(key.is(rcx)); 291 DCHECK(key.is(rcx));
286 292
287 // Check that the key is a smi. 293 // Check that the key is a smi.
288 __ JumpIfNotSmi(key, &check_name); 294 __ JumpIfNotSmi(key, &check_name);
289 __ bind(&index_smi); 295 __ bind(&index_smi);
290 // Now the key is known to be a smi. This place is also jumped to from below 296 // Now the key is known to be a smi. This place is also jumped to from below
291 // where a numeric string is converted to a smi. 297 // where a numeric string is converted to a smi.
292 298
293 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, 299 GenerateKeyedLoadReceiverCheck(masm, receiver, rax,
294 Map::kHasIndexedInterceptor, &slow); 300 Map::kHasIndexedInterceptor, &slow);
295 301
296 // Check the receiver's map to see if it has fast elements. 302 // Check the receiver's map to see if it has fast elements.
297 __ CheckFastElements(rax, &check_number_dictionary); 303 __ CheckFastElements(rax, &check_number_dictionary);
298 304
299 GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, &slow); 305 GenerateFastArrayLoad(masm, receiver, key, rax, rbx, rax, &slow,
306 language_mode);
300 Counters* counters = masm->isolate()->counters(); 307 Counters* counters = masm->isolate()->counters();
301 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); 308 __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
302 __ ret(0); 309 __ ret(0);
303 310
304 __ bind(&check_number_dictionary); 311 __ bind(&check_number_dictionary);
305 __ SmiToInteger32(rbx, key); 312 __ SmiToInteger32(rbx, key);
306 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset)); 313 __ movp(rax, FieldOperand(receiver, JSObject::kElementsOffset));
307 314
308 // Check whether the elements is a number dictionary. 315 // Check whether the elements is a number dictionary.
309 // rbx: key as untagged int32 316 // rbx: key as untagged int32
310 // rax: elements 317 // rax: elements
311 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 318 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
312 Heap::kHashTableMapRootIndex); 319 Heap::kHashTableMapRootIndex);
313 __ j(not_equal, &slow); 320 __ j(not_equal, &slow);
314 __ LoadFromNumberDictionary(&slow, rax, key, rbx, r9, rdi, rax); 321 __ LoadFromNumberDictionary(&slow, rax, key, rbx, r9, rdi, rax);
315 __ ret(0); 322 __ ret(0);
316 323
317 __ bind(&slow); 324 __ bind(&slow);
318 // Slow case: Jump to runtime. 325 // Slow case: Jump to runtime.
319 __ IncrementCounter(counters->keyed_load_generic_slow(), 1); 326 __ IncrementCounter(counters->keyed_load_generic_slow(), 1);
320 GenerateRuntimeGetProperty(masm); 327 KeyedLoadIC::GenerateRuntimeGetProperty(masm, language_mode);
321 328
322 __ bind(&check_name); 329 __ bind(&check_name);
323 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow); 330 GenerateKeyNameCheck(masm, key, rax, rbx, &index_name, &slow);
324 331
325 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor, 332 GenerateKeyedLoadReceiverCheck(masm, receiver, rax, Map::kHasNamedInterceptor,
326 &slow); 333 &slow);
327 334
328 // If the receiver is a fast-case object, check the stub cache. Otherwise 335 // If the receiver is a fast-case object, check the stub cache. Otherwise
329 // probe the dictionary. 336 // probe the dictionary.
330 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset)); 337 __ movp(rbx, FieldOperand(receiver, JSObject::kPropertiesOffset));
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 kCheckMap, kDontIncrementLength); 621 kCheckMap, kDontIncrementLength);
615 KeyedStoreGenerateMegamorphicHelper(masm, &fast_object_grow, 622 KeyedStoreGenerateMegamorphicHelper(masm, &fast_object_grow,
616 &fast_double_grow, &slow, kDontCheckMap, 623 &fast_double_grow, &slow, kDontCheckMap,
617 kIncrementLength); 624 kIncrementLength);
618 625
619 __ bind(&miss); 626 __ bind(&miss);
620 GenerateMiss(masm); 627 GenerateMiss(masm);
621 } 628 }
622 629
623 630
624 void LoadIC::GenerateNormal(MacroAssembler* masm) { 631 void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) {
625 Register dictionary = rax; 632 Register dictionary = rax;
626 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); 633 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
627 DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); 634 DCHECK(!dictionary.is(LoadDescriptor::NameRegister()));
628 635
629 Label slow; 636 Label slow;
630 637
631 __ movp(dictionary, FieldOperand(LoadDescriptor::ReceiverRegister(), 638 __ movp(dictionary, FieldOperand(LoadDescriptor::ReceiverRegister(),
632 JSObject::kPropertiesOffset)); 639 JSObject::kPropertiesOffset));
633 GenerateDictionaryLoad(masm, &slow, dictionary, 640 GenerateDictionaryLoad(masm, &slow, dictionary,
634 LoadDescriptor::NameRegister(), rbx, rdi, rax); 641 LoadDescriptor::NameRegister(), rbx, rdi, rax);
635 __ ret(0); 642 __ ret(0);
636 643
637 // Dictionary load failed, go slow (but don't miss). 644 // Dictionary load failed, go slow (but don't miss).
638 __ bind(&slow); 645 __ bind(&slow);
639 GenerateRuntimeGetProperty(masm); 646 LoadIC::GenerateRuntimeGetProperty(masm, language_mode);
640 } 647 }
641 648
642 649
643 static void LoadIC_PushArgs(MacroAssembler* masm) { 650 static void LoadIC_PushArgs(MacroAssembler* masm) {
644 Register receiver = LoadDescriptor::ReceiverRegister(); 651 Register receiver = LoadDescriptor::ReceiverRegister();
645 Register name = LoadDescriptor::NameRegister(); 652 Register name = LoadDescriptor::NameRegister();
646 Register slot = LoadDescriptor::SlotRegister(); 653 Register slot = LoadDescriptor::SlotRegister();
647 Register vector = LoadWithVectorDescriptor::VectorRegister(); 654 Register vector = LoadWithVectorDescriptor::VectorRegister();
648 DCHECK(!rdi.is(receiver) && !rdi.is(name) && !rdi.is(slot) && 655 DCHECK(!rdi.is(receiver) && !rdi.is(name) && !rdi.is(slot) &&
649 !rdi.is(vector)); 656 !rdi.is(vector));
(...skipping 16 matching lines...) Expand all
666 LoadIC_PushArgs(masm); 673 LoadIC_PushArgs(masm);
667 674
668 // Perform tail call to the entry. 675 // Perform tail call to the entry.
669 ExternalReference ref = 676 ExternalReference ref =
670 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); 677 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
671 int arg_count = 4; 678 int arg_count = 4;
672 __ TailCallExternalReference(ref, arg_count, 1); 679 __ TailCallExternalReference(ref, arg_count, 1);
673 } 680 }
674 681
675 682
676 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 683 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm,
684 LanguageMode language_mode) {
677 // The return address is on the stack. 685 // The return address is on the stack.
678 Register receiver = LoadDescriptor::ReceiverRegister(); 686 Register receiver = LoadDescriptor::ReceiverRegister();
679 Register name = LoadDescriptor::NameRegister(); 687 Register name = LoadDescriptor::NameRegister();
688
680 DCHECK(!rbx.is(receiver) && !rbx.is(name)); 689 DCHECK(!rbx.is(receiver) && !rbx.is(name));
681 690
682 __ PopReturnAddressTo(rbx); 691 __ PopReturnAddressTo(rbx);
683 __ Push(receiver); 692 __ Push(receiver);
684 __ Push(name); 693 __ Push(name);
685 __ PushReturnAddressFrom(rbx); 694 __ PushReturnAddressFrom(rbx);
686 695
687 // Perform tail call to the entry. 696 // Do tail-call to runtime routine.
688 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); 697 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong
698 : Runtime::kGetProperty,
699 2, 1);
689 } 700 }
690 701
691 702
692 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 703 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
693 // The return address is on the stack. 704 // The return address is on the stack.
694 Counters* counters = masm->isolate()->counters(); 705 Counters* counters = masm->isolate()->counters();
695 __ IncrementCounter(counters->keyed_load_miss(), 1); 706 __ IncrementCounter(counters->keyed_load_miss(), 1);
696 707
697 LoadIC_PushArgs(masm); 708 LoadIC_PushArgs(masm);
698 709
699 // Perform tail call to the entry. 710 // Perform tail call to the entry.
700 ExternalReference ref = 711 ExternalReference ref =
701 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); 712 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
702 int arg_count = 4; 713 int arg_count = 4;
703 __ TailCallExternalReference(ref, arg_count, 1); 714 __ TailCallExternalReference(ref, arg_count, 1);
704 } 715 }
705 716
706 717
707 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 718 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm,
719 LanguageMode language_mode) {
708 // The return address is on the stack. 720 // The return address is on the stack.
709 Register receiver = LoadDescriptor::ReceiverRegister(); 721 Register receiver = LoadDescriptor::ReceiverRegister();
710 Register name = LoadDescriptor::NameRegister(); 722 Register name = LoadDescriptor::NameRegister();
723
711 DCHECK(!rbx.is(receiver) && !rbx.is(name)); 724 DCHECK(!rbx.is(receiver) && !rbx.is(name));
712 725
713 __ PopReturnAddressTo(rbx); 726 __ PopReturnAddressTo(rbx);
714 __ Push(receiver); 727 __ Push(receiver);
715 __ Push(name); 728 __ Push(name);
716 __ PushReturnAddressFrom(rbx); 729 __ PushReturnAddressFrom(rbx);
717 730
718 // Perform tail call to the entry. 731 // Do tail-call to runtime routine.
719 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 732 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong
733 : Runtime::kKeyedGetProperty,
734 2, 1);
720 } 735 }
721 736
722 737
723 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 738 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
724 // The return address is on the stack. 739 // The return address is on the stack.
725 740
726 // Get the receiver from the stack and probe the stub cache. 741 // Get the receiver from the stack and probe the stub cache.
727 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 742 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
728 Code::ComputeHandlerFlags(Code::STORE_IC)); 743 Code::ComputeHandlerFlags(Code::STORE_IC));
729 masm->isolate()->stub_cache()->GenerateProbe( 744 masm->isolate()->stub_cache()->GenerateProbe(
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 Condition cc = 874 Condition cc =
860 (check == ENABLE_INLINED_SMI_CHECK) 875 (check == ENABLE_INLINED_SMI_CHECK)
861 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) 876 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
862 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); 877 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
863 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 878 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
864 } 879 }
865 } // namespace internal 880 } // namespace internal
866 } // namespace v8 881 } // namespace v8
867 882
868 #endif // V8_TARGET_ARCH_X64 883 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/ic/ppc/ic-ppc.cc ('k') | src/ic/x87/handler-compiler-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698