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

Side by Side Diff: src/ic/ia32/ic-ia32.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/handler-compiler.cc ('k') | src/ic/ic.h » ('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_IA32 7 #if V8_TARGET_ARCH_IA32
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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 165
166 __ CmpInstanceType(map, JS_OBJECT_TYPE); 166 __ CmpInstanceType(map, JS_OBJECT_TYPE);
167 __ j(below, slow); 167 __ j(below, slow);
168 } 168 }
169 169
170 170
171 // Loads an indexed element from a fast case array. 171 // Loads an indexed element from a fast case array.
172 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, 172 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
173 Register key, Register scratch, 173 Register key, Register scratch,
174 Register scratch2, Register result, 174 Register scratch2, Register result,
175 Label* slow) { 175 Label* slow, LanguageMode language_mode) {
176 // Register use: 176 // Register use:
177 // receiver - holds the receiver and is unchanged. 177 // receiver - holds the receiver and is unchanged.
178 // key - holds the key and is unchanged (must be a smi). 178 // key - holds the key and is unchanged (must be a smi).
179 // Scratch registers: 179 // Scratch registers:
180 // scratch - used to hold elements of the receiver and the loaded value. 180 // scratch - used to hold elements of the receiver and the loaded value.
181 // scratch2 - holds maps and prototypes during prototype chain check. 181 // scratch2 - holds maps and prototypes during prototype chain check.
182 // result - holds the result on exit if the load succeeds and 182 // result - holds the result on exit if the load succeeds and
183 // we fall through. 183 // we fall through.
184 Label check_prototypes, check_next_prototype; 184 Label check_prototypes, check_next_prototype;
185 Label done, in_bounds, return_undefined; 185 Label done, in_bounds, absent;
186 186
187 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset)); 187 __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
188 __ AssertFastElements(scratch); 188 __ AssertFastElements(scratch);
189 189
190 // Check that the key (index) is within bounds. 190 // Check that the key (index) is within bounds.
191 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset)); 191 __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
192 __ j(below, &in_bounds); 192 __ j(below, &in_bounds);
193 // Out-of-bounds. Check the prototype chain to see if we can just return 193 // Out-of-bounds. Check the prototype chain to see if we can just return
194 // 'undefined'. 194 // 'undefined'.
195 __ cmp(key, 0); 195 __ cmp(key, 0);
196 __ j(less, slow); // Negative keys can't take the fast OOB path. 196 __ j(less, slow); // Negative keys can't take the fast OOB path.
197 __ bind(&check_prototypes); 197 __ bind(&check_prototypes);
198 __ mov(scratch2, FieldOperand(receiver, HeapObject::kMapOffset)); 198 __ mov(scratch2, FieldOperand(receiver, HeapObject::kMapOffset));
199 __ bind(&check_next_prototype); 199 __ bind(&check_next_prototype);
200 __ mov(scratch2, FieldOperand(scratch2, Map::kPrototypeOffset)); 200 __ mov(scratch2, FieldOperand(scratch2, Map::kPrototypeOffset));
201 // scratch2: current prototype 201 // scratch2: current prototype
202 __ cmp(scratch2, masm->isolate()->factory()->null_value()); 202 __ cmp(scratch2, masm->isolate()->factory()->null_value());
203 __ j(equal, &return_undefined); 203 __ j(equal, &absent);
204 __ mov(scratch, FieldOperand(scratch2, JSObject::kElementsOffset)); 204 __ mov(scratch, FieldOperand(scratch2, JSObject::kElementsOffset));
205 __ mov(scratch2, FieldOperand(scratch2, HeapObject::kMapOffset)); 205 __ mov(scratch2, FieldOperand(scratch2, HeapObject::kMapOffset));
206 // scratch: elements of current prototype 206 // scratch: elements of current prototype
207 // scratch2: map of current prototype 207 // scratch2: map of current prototype
208 __ CmpInstanceType(scratch2, JS_OBJECT_TYPE); 208 __ CmpInstanceType(scratch2, JS_OBJECT_TYPE);
209 __ j(below, slow); 209 __ j(below, slow);
210 __ test_b( 210 __ test_b(
211 FieldOperand(scratch2, Map::kBitFieldOffset), 211 FieldOperand(scratch2, Map::kBitFieldOffset),
212 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor)); 212 (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor));
213 __ j(not_zero, slow); 213 __ j(not_zero, slow);
214 __ cmp(scratch, masm->isolate()->factory()->empty_fixed_array()); 214 __ cmp(scratch, masm->isolate()->factory()->empty_fixed_array());
215 __ j(not_equal, slow); 215 __ j(not_equal, slow);
216 __ jmp(&check_next_prototype); 216 __ jmp(&check_next_prototype);
217 217
218 __ bind(&return_undefined); 218 __ bind(&absent);
219 __ mov(result, masm->isolate()->factory()->undefined_value()); 219 if (is_strong(language_mode)) {
220 __ jmp(&done); 220 // Strong mode accesses must throw in this case, so call the runtime.
221 __ jmp(slow);
222 } else {
223 __ mov(result, masm->isolate()->factory()->undefined_value());
224 __ jmp(&done);
225 }
221 226
222 __ bind(&in_bounds); 227 __ bind(&in_bounds);
223 // Fast case: Do the load. 228 // Fast case: Do the load.
224 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); 229 STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0));
225 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); 230 __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
226 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value())); 231 __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value()));
227 // In case the loaded value is the_hole we have to check the prototype chain. 232 // In case the loaded value is the_hole we have to check the prototype chain.
228 __ j(equal, &check_prototypes); 233 __ j(equal, &check_prototypes);
229 __ Move(result, scratch); 234 __ Move(result, scratch);
230 __ bind(&done); 235 __ bind(&done);
(...skipping 25 matching lines...) Expand all
256 // bit test is enough. 261 // bit test is enough.
257 STATIC_ASSERT(kNotInternalizedTag != 0); 262 STATIC_ASSERT(kNotInternalizedTag != 0);
258 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), 263 __ test_b(FieldOperand(map, Map::kInstanceTypeOffset),
259 kIsNotInternalizedMask); 264 kIsNotInternalizedMask);
260 __ j(not_zero, not_unique); 265 __ j(not_zero, not_unique);
261 266
262 __ bind(&unique); 267 __ bind(&unique);
263 } 268 }
264 269
265 270
266 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { 271 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
272 LanguageMode language_mode) {
267 // The return address is on the stack. 273 // The return address is on the stack.
268 Label slow, check_name, index_smi, index_name, property_array_property; 274 Label slow, check_name, index_smi, index_name, property_array_property;
269 Label probe_dictionary, check_number_dictionary; 275 Label probe_dictionary, check_number_dictionary;
270 276
271 Register receiver = LoadDescriptor::ReceiverRegister(); 277 Register receiver = LoadDescriptor::ReceiverRegister();
272 Register key = LoadDescriptor::NameRegister(); 278 Register key = LoadDescriptor::NameRegister();
273 DCHECK(receiver.is(edx)); 279 DCHECK(receiver.is(edx));
274 DCHECK(key.is(ecx)); 280 DCHECK(key.is(ecx));
275 281
276 // Check that the key is a smi. 282 // Check that the key is a smi.
277 __ JumpIfNotSmi(key, &check_name); 283 __ JumpIfNotSmi(key, &check_name);
278 __ bind(&index_smi); 284 __ bind(&index_smi);
279 // Now the key is known to be a smi. This place is also jumped to from 285 // Now the key is known to be a smi. This place is also jumped to from
280 // where a numeric string is converted to a smi. 286 // where a numeric string is converted to a smi.
281 287
282 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, 288 GenerateKeyedLoadReceiverCheck(masm, receiver, eax,
283 Map::kHasIndexedInterceptor, &slow); 289 Map::kHasIndexedInterceptor, &slow);
284 290
285 // Check the receiver's map to see if it has fast elements. 291 // Check the receiver's map to see if it has fast elements.
286 __ CheckFastElements(eax, &check_number_dictionary); 292 __ CheckFastElements(eax, &check_number_dictionary);
287 293
288 GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow); 294 GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow,
295 language_mode);
289 Isolate* isolate = masm->isolate(); 296 Isolate* isolate = masm->isolate();
290 Counters* counters = isolate->counters(); 297 Counters* counters = isolate->counters();
291 __ IncrementCounter(counters->keyed_load_generic_smi(), 1); 298 __ IncrementCounter(counters->keyed_load_generic_smi(), 1);
292 __ ret(0); 299 __ ret(0);
293 300
294 __ bind(&check_number_dictionary); 301 __ bind(&check_number_dictionary);
295 __ mov(ebx, key); 302 __ mov(ebx, key);
296 __ SmiUntag(ebx); 303 __ SmiUntag(ebx);
297 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset)); 304 __ mov(eax, FieldOperand(receiver, JSObject::kElementsOffset));
298 305
(...skipping 11 matching lines...) Expand all
310 __ pop(receiver); 317 __ pop(receiver);
311 __ ret(0); 318 __ ret(0);
312 319
313 __ bind(&slow_pop_receiver); 320 __ bind(&slow_pop_receiver);
314 // Pop the receiver from the stack and jump to runtime. 321 // Pop the receiver from the stack and jump to runtime.
315 __ pop(receiver); 322 __ pop(receiver);
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 GenerateRuntimeGetProperty(masm, language_mode);
321 328
322 __ bind(&check_name); 329 __ bind(&check_name);
323 GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow); 330 GenerateKeyNameCheck(masm, key, eax, ebx, &index_name, &slow);
324 331
325 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, Map::kHasNamedInterceptor, 332 GenerateKeyedLoadReceiverCheck(masm, receiver, eax, 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 __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset)); 337 __ mov(ebx, FieldOperand(receiver, JSObject::kPropertiesOffset));
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 kCheckMap, kDontIncrementLength); 626 kCheckMap, kDontIncrementLength);
620 KeyedStoreGenerateMegamorphicHelper(masm, &fast_object_grow, 627 KeyedStoreGenerateMegamorphicHelper(masm, &fast_object_grow,
621 &fast_double_grow, &slow, kDontCheckMap, 628 &fast_double_grow, &slow, kDontCheckMap,
622 kIncrementLength); 629 kIncrementLength);
623 630
624 __ bind(&miss); 631 __ bind(&miss);
625 GenerateMiss(masm); 632 GenerateMiss(masm);
626 } 633 }
627 634
628 635
629 void LoadIC::GenerateNormal(MacroAssembler* masm) { 636 void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) {
630 Register dictionary = eax; 637 Register dictionary = eax;
631 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); 638 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
632 DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); 639 DCHECK(!dictionary.is(LoadDescriptor::NameRegister()));
633 640
634 Label slow; 641 Label slow;
635 642
636 __ mov(dictionary, FieldOperand(LoadDescriptor::ReceiverRegister(), 643 __ mov(dictionary, FieldOperand(LoadDescriptor::ReceiverRegister(),
637 JSObject::kPropertiesOffset)); 644 JSObject::kPropertiesOffset));
638 GenerateDictionaryLoad(masm, &slow, dictionary, 645 GenerateDictionaryLoad(masm, &slow, dictionary,
639 LoadDescriptor::NameRegister(), edi, ebx, eax); 646 LoadDescriptor::NameRegister(), edi, ebx, eax);
640 __ ret(0); 647 __ ret(0);
641 648
642 // Dictionary load failed, go slow (but don't miss). 649 // Dictionary load failed, go slow (but don't miss).
643 __ bind(&slow); 650 __ bind(&slow);
644 GenerateRuntimeGetProperty(masm); 651 GenerateRuntimeGetProperty(masm, language_mode);
645 } 652 }
646 653
647 654
648 static void LoadIC_PushArgs(MacroAssembler* masm) { 655 static void LoadIC_PushArgs(MacroAssembler* masm) {
649 Register receiver = LoadDescriptor::ReceiverRegister(); 656 Register receiver = LoadDescriptor::ReceiverRegister();
650 Register name = LoadDescriptor::NameRegister(); 657 Register name = LoadDescriptor::NameRegister();
651 658
652 Register slot = LoadDescriptor::SlotRegister(); 659 Register slot = LoadDescriptor::SlotRegister();
653 Register vector = LoadWithVectorDescriptor::VectorRegister(); 660 Register vector = LoadWithVectorDescriptor::VectorRegister();
654 DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) && 661 DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) &&
(...skipping 14 matching lines...) Expand all
669 LoadIC_PushArgs(masm); 676 LoadIC_PushArgs(masm);
670 677
671 // Perform tail call to the entry. 678 // Perform tail call to the entry.
672 ExternalReference ref = 679 ExternalReference ref =
673 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate()); 680 ExternalReference(IC_Utility(kLoadIC_Miss), masm->isolate());
674 int arg_count = 4; 681 int arg_count = 4;
675 __ TailCallExternalReference(ref, arg_count, 1); 682 __ TailCallExternalReference(ref, arg_count, 1);
676 } 683 }
677 684
678 685
679 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 686 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm,
687 LanguageMode language_mode) {
680 // Return address is on the stack. 688 // Return address is on the stack.
681 Register receiver = LoadDescriptor::ReceiverRegister(); 689 Register receiver = LoadDescriptor::ReceiverRegister();
682 Register name = LoadDescriptor::NameRegister(); 690 Register name = LoadDescriptor::NameRegister();
683 DCHECK(!ebx.is(receiver) && !ebx.is(name)); 691 DCHECK(!ebx.is(receiver) && !ebx.is(name));
684 692
685 __ pop(ebx); 693 __ pop(ebx);
686 __ push(receiver); 694 __ push(receiver);
687 __ push(name); 695 __ push(name);
688 __ push(ebx); 696 __ push(ebx);
689 697
690 // Perform tail call to the entry. 698 // Do tail-call to runtime routine.
691 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); 699 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong
700 : Runtime::kGetProperty,
701 2, 1);
692 } 702 }
693 703
694 704
695 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 705 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
696 // Return address is on the stack. 706 // Return address is on the stack.
697 __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1); 707 __ IncrementCounter(masm->isolate()->counters()->keyed_load_miss(), 1);
698 708
699 LoadIC_PushArgs(masm); 709 LoadIC_PushArgs(masm);
700 710
701 // Perform tail call to the entry. 711 // Perform tail call to the entry.
702 ExternalReference ref = 712 ExternalReference ref =
703 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate()); 713 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), masm->isolate());
704 int arg_count = 4; 714 int arg_count = 4;
705 __ TailCallExternalReference(ref, arg_count, 1); 715 __ TailCallExternalReference(ref, arg_count, 1);
706 } 716 }
707 717
708 718
709 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 719 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm,
720 LanguageMode language_mode) {
710 // Return address is on the stack. 721 // Return address is on the stack.
711 Register receiver = LoadDescriptor::ReceiverRegister(); 722 Register receiver = LoadDescriptor::ReceiverRegister();
712 Register name = LoadDescriptor::NameRegister(); 723 Register name = LoadDescriptor::NameRegister();
713 DCHECK(!ebx.is(receiver) && !ebx.is(name)); 724 DCHECK(!ebx.is(receiver) && !ebx.is(name));
714 725
715 __ pop(ebx); 726 __ pop(ebx);
716 __ push(receiver); 727 __ push(receiver);
717 __ push(name); 728 __ push(name);
718 __ push(ebx); 729 __ push(ebx);
719 730
720 // Perform tail call to the entry. 731 // Do tail-call to runtime routine.
721 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 732 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong
733 : Runtime::kKeyedGetProperty,
734 2, 1);
722 } 735 }
723 736
724 737
725 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 738 void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
726 // Return address is on the stack. 739 // Return address is on the stack.
727 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 740 Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
728 Code::ComputeHandlerFlags(Code::STORE_IC)); 741 Code::ComputeHandlerFlags(Code::STORE_IC));
729 masm->isolate()->stub_cache()->GenerateProbe( 742 masm->isolate()->stub_cache()->GenerateProbe(
730 masm, Code::STORE_IC, flags, false, StoreDescriptor::ReceiverRegister(), 743 masm, Code::STORE_IC, flags, false, StoreDescriptor::ReceiverRegister(),
731 StoreDescriptor::NameRegister(), ebx, no_reg); 744 StoreDescriptor::NameRegister(), ebx, no_reg);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 Condition cc = 879 Condition cc =
867 (check == ENABLE_INLINED_SMI_CHECK) 880 (check == ENABLE_INLINED_SMI_CHECK)
868 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero) 881 ? (*jmp_address == Assembler::kJncShortOpcode ? not_zero : zero)
869 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry); 882 : (*jmp_address == Assembler::kJnzShortOpcode ? not_carry : carry);
870 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc); 883 *jmp_address = static_cast<byte>(Assembler::kJccShortPrefix | cc);
871 } 884 }
872 } // namespace internal 885 } // namespace internal
873 } // namespace v8 886 } // namespace v8
874 887
875 #endif // V8_TARGET_ARCH_IA32 888 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ic/handler-compiler.cc ('k') | src/ic/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698