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

Side by Side Diff: src/ic/ppc/ic-ppc.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/mips64/ic-mips64.cc ('k') | src/ic/x64/ic-x64.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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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_PPC 7 #if V8_TARGET_ARCH_PPC
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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 __ lbz(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 160 __ lbz(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset));
161 __ cmpi(scratch, Operand(JS_OBJECT_TYPE)); 161 __ cmpi(scratch, Operand(JS_OBJECT_TYPE));
162 __ blt(slow); 162 __ blt(slow);
163 } 163 }
164 164
165 165
166 // Loads an indexed element from a fast case array. 166 // Loads an indexed element from a fast case array.
167 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, 167 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
168 Register key, Register elements, 168 Register key, Register elements,
169 Register scratch1, Register scratch2, 169 Register scratch1, Register scratch2,
170 Register result, Label* slow) { 170 Register result, Label* slow,
171 LanguageMode language_mode) {
171 // Register use: 172 // Register use:
172 // 173 //
173 // receiver - holds the receiver on entry. 174 // receiver - holds the receiver on entry.
174 // Unchanged unless 'result' is the same register. 175 // Unchanged unless 'result' is the same register.
175 // 176 //
176 // key - holds the smi key on entry. 177 // key - holds the smi key on entry.
177 // Unchanged unless 'result' is the same register. 178 // Unchanged unless 'result' is the same register.
178 // 179 //
179 // result - holds the result on exit if the load succeeded. 180 // result - holds the result on exit if the load succeeded.
180 // Allowed to be the the same as 'receiver' or 'key'. 181 // Allowed to be the the same as 'receiver' or 'key'.
181 // Unchanged on bailout so 'receiver' and 'key' can be safely 182 // Unchanged on bailout so 'receiver' and 'key' can be safely
182 // used by further computation. 183 // used by further computation.
183 // 184 //
184 // Scratch registers: 185 // Scratch registers:
185 // 186 //
186 // elements - holds the elements of the receiver and its protoypes. 187 // elements - holds the elements of the receiver and its protoypes.
187 // 188 //
188 // scratch1 - used to hold elements length, bit fields, base addresses. 189 // scratch1 - used to hold elements length, bit fields, base addresses.
189 // 190 //
190 // scratch2 - used to hold maps, prototypes, and the loaded value. 191 // scratch2 - used to hold maps, prototypes, and the loaded value.
191 Label check_prototypes, check_next_prototype; 192 Label check_prototypes, check_next_prototype;
192 Label done, in_bounds, return_undefined; 193 Label done, in_bounds, absent;
193 194
194 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 195 __ LoadP(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
195 __ AssertFastElements(elements); 196 __ AssertFastElements(elements);
196 197
197 // Check that the key (index) is within bounds. 198 // Check that the key (index) is within bounds.
198 __ LoadP(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); 199 __ LoadP(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset));
199 __ cmpl(key, scratch1); 200 __ cmpl(key, scratch1);
200 __ blt(&in_bounds); 201 __ blt(&in_bounds);
201 // Out-of-bounds. Check the prototype chain to see if we can just return 202 // Out-of-bounds. Check the prototype chain to see if we can just return
202 // 'undefined'. 203 // 'undefined'.
203 __ cmpi(key, Operand::Zero()); 204 __ cmpi(key, Operand::Zero());
204 __ blt(slow); // Negative keys can't take the fast OOB path. 205 __ blt(slow); // Negative keys can't take the fast OOB path.
205 __ bind(&check_prototypes); 206 __ bind(&check_prototypes);
206 __ LoadP(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); 207 __ LoadP(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset));
207 __ bind(&check_next_prototype); 208 __ bind(&check_next_prototype);
208 __ LoadP(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset)); 209 __ LoadP(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset));
209 // scratch2: current prototype 210 // scratch2: current prototype
210 __ CompareRoot(scratch2, Heap::kNullValueRootIndex); 211 __ CompareRoot(scratch2, Heap::kNullValueRootIndex);
211 __ beq(&return_undefined); 212 __ beq(&absent);
212 __ LoadP(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset)); 213 __ LoadP(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset));
213 __ LoadP(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset)); 214 __ LoadP(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset));
214 // elements: elements of current prototype 215 // elements: elements of current prototype
215 // scratch2: map of current prototype 216 // scratch2: map of current prototype
216 __ CompareInstanceType(scratch2, scratch1, JS_OBJECT_TYPE); 217 __ CompareInstanceType(scratch2, scratch1, JS_OBJECT_TYPE);
217 __ blt(slow); 218 __ blt(slow);
218 __ lbz(scratch1, FieldMemOperand(scratch2, Map::kBitFieldOffset)); 219 __ lbz(scratch1, FieldMemOperand(scratch2, Map::kBitFieldOffset));
219 __ andi(r0, scratch1, Operand((1 << Map::kIsAccessCheckNeeded) | 220 __ andi(r0, scratch1, Operand((1 << Map::kIsAccessCheckNeeded) |
220 (1 << Map::kHasIndexedInterceptor))); 221 (1 << Map::kHasIndexedInterceptor)));
221 __ bne(slow, cr0); 222 __ bne(slow, cr0);
222 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); 223 __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex);
223 __ bne(slow); 224 __ bne(slow);
224 __ jmp(&check_next_prototype); 225 __ jmp(&check_next_prototype);
225 226
226 __ bind(&return_undefined); 227 __ bind(&absent);
227 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 228 if (is_strong(language_mode)) {
228 __ jmp(&done); 229 // Strong mode accesses must throw in this case, so call the runtime.
230 __ jmp(slow);
231 } else {
232 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
233 __ jmp(&done);
234 }
229 235
230 __ bind(&in_bounds); 236 __ bind(&in_bounds);
231 // Fast case: Do the load. 237 // Fast case: Do the load.
232 __ addi(scratch1, elements, 238 __ addi(scratch1, elements,
233 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 239 Operand(FixedArray::kHeaderSize - kHeapObjectTag));
234 // The key is a smi. 240 // The key is a smi.
235 __ SmiToPtrArrayOffset(scratch2, key); 241 __ SmiToPtrArrayOffset(scratch2, key);
236 __ LoadPX(scratch2, MemOperand(scratch2, scratch1)); 242 __ LoadPX(scratch2, MemOperand(scratch2, scratch1));
237 __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex); 243 __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex);
238 // In case the loaded value is the_hole we have to check the prototype chain. 244 // In case the loaded value is the_hole we have to check the prototype chain.
(...skipping 27 matching lines...) Expand all
266 // map: key map 272 // map: key map
267 __ lbz(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); 273 __ lbz(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
268 STATIC_ASSERT(kInternalizedTag == 0); 274 STATIC_ASSERT(kInternalizedTag == 0);
269 __ andi(r0, hash, Operand(kIsNotInternalizedMask)); 275 __ andi(r0, hash, Operand(kIsNotInternalizedMask));
270 __ bne(not_unique, cr0); 276 __ bne(not_unique, cr0);
271 277
272 __ bind(&unique); 278 __ bind(&unique);
273 } 279 }
274 280
275 281
276 void LoadIC::GenerateNormal(MacroAssembler* masm) { 282 void LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) {
277 Register dictionary = r3; 283 Register dictionary = r3;
278 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); 284 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
279 DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); 285 DCHECK(!dictionary.is(LoadDescriptor::NameRegister()));
280 286
281 Label slow; 287 Label slow;
282 288
283 __ LoadP(dictionary, FieldMemOperand(LoadDescriptor::ReceiverRegister(), 289 __ LoadP(dictionary, FieldMemOperand(LoadDescriptor::ReceiverRegister(),
284 JSObject::kPropertiesOffset)); 290 JSObject::kPropertiesOffset));
285 GenerateDictionaryLoad(masm, &slow, dictionary, 291 GenerateDictionaryLoad(masm, &slow, dictionary,
286 LoadDescriptor::NameRegister(), r3, r6, r7); 292 LoadDescriptor::NameRegister(), r3, r6, r7);
287 __ Ret(); 293 __ Ret();
288 294
289 // Dictionary load failed, go slow (but don't miss). 295 // Dictionary load failed, go slow (but don't miss).
290 __ bind(&slow); 296 __ bind(&slow);
291 GenerateRuntimeGetProperty(masm); 297 GenerateRuntimeGetProperty(masm, language_mode);
292 } 298 }
293 299
294 300
295 // A register that isn't one of the parameters to the load ic. 301 // A register that isn't one of the parameters to the load ic.
296 static const Register LoadIC_TempRegister() { return r6; } 302 static const Register LoadIC_TempRegister() { return r6; }
297 303
298 304
299 static void LoadIC_PushArgs(MacroAssembler* masm) { 305 static void LoadIC_PushArgs(MacroAssembler* masm) {
300 Register receiver = LoadDescriptor::ReceiverRegister(); 306 Register receiver = LoadDescriptor::ReceiverRegister();
301 Register name = LoadDescriptor::NameRegister(); 307 Register name = LoadDescriptor::NameRegister();
(...skipping 14 matching lines...) Expand all
316 322
317 LoadIC_PushArgs(masm); 323 LoadIC_PushArgs(masm);
318 324
319 // Perform tail call to the entry. 325 // Perform tail call to the entry.
320 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); 326 ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate);
321 int arg_count = 4; 327 int arg_count = 4;
322 __ TailCallExternalReference(ref, arg_count, 1); 328 __ TailCallExternalReference(ref, arg_count, 1);
323 } 329 }
324 330
325 331
326 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 332 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm,
333 LanguageMode language_mode) {
327 // The return address is in lr. 334 // The return address is in lr.
328 335
329 __ mr(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); 336 __ mr(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister());
330 __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); 337 __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister());
331 338
332 __ TailCallRuntime(Runtime::kGetProperty, 2, 1); 339 // Do tail-call to runtime routine.
340 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong
341 : Runtime::kGetProperty,
342 2, 1);
333 } 343 }
334 344
335 345
336 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 346 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
337 // The return address is in lr. 347 // The return address is in lr.
338 Isolate* isolate = masm->isolate(); 348 Isolate* isolate = masm->isolate();
339 349
340 DCHECK(!AreAliased(r7, r8, LoadWithVectorDescriptor::SlotRegister(), 350 DCHECK(!AreAliased(r7, r8, LoadWithVectorDescriptor::SlotRegister(),
341 LoadWithVectorDescriptor::VectorRegister())); 351 LoadWithVectorDescriptor::VectorRegister()));
342 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r7, r8); 352 __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r7, r8);
343 353
344 LoadIC_PushArgs(masm); 354 LoadIC_PushArgs(masm);
345 355
346 // Perform tail call to the entry. 356 // Perform tail call to the entry.
347 ExternalReference ref = 357 ExternalReference ref =
348 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); 358 ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate);
349 int arg_count = 4; 359 int arg_count = 4;
350 __ TailCallExternalReference(ref, arg_count, 1); 360 __ TailCallExternalReference(ref, arg_count, 1);
351 } 361 }
352 362
353 363
354 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 364 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm,
365 LanguageMode language_mode) {
355 // The return address is in lr. 366 // The return address is in lr.
356 367
357 __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); 368 __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
358 369
359 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 370 // Do tail-call to runtime routine.
371 __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong
372 : Runtime::kKeyedGetProperty,
373 2, 1);
360 } 374 }
361 375
362 376
363 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { 377 void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm,
378 LanguageMode language_mode) {
364 // The return address is in lr. 379 // The return address is in lr.
365 Label slow, check_name, index_smi, index_name, property_array_property; 380 Label slow, check_name, index_smi, index_name, property_array_property;
366 Label probe_dictionary, check_number_dictionary; 381 Label probe_dictionary, check_number_dictionary;
367 382
368 Register key = LoadDescriptor::NameRegister(); 383 Register key = LoadDescriptor::NameRegister();
369 Register receiver = LoadDescriptor::ReceiverRegister(); 384 Register receiver = LoadDescriptor::ReceiverRegister();
370 DCHECK(key.is(r5)); 385 DCHECK(key.is(r5));
371 DCHECK(receiver.is(r4)); 386 DCHECK(receiver.is(r4));
372 387
373 Isolate* isolate = masm->isolate(); 388 Isolate* isolate = masm->isolate();
374 389
375 // Check that the key is a smi. 390 // Check that the key is a smi.
376 __ JumpIfNotSmi(key, &check_name); 391 __ JumpIfNotSmi(key, &check_name);
377 __ bind(&index_smi); 392 __ bind(&index_smi);
378 // Now the key is known to be a smi. This place is also jumped to from below 393 // Now the key is known to be a smi. This place is also jumped to from below
379 // where a numeric string is converted to a smi. 394 // where a numeric string is converted to a smi.
380 395
381 GenerateKeyedLoadReceiverCheck(masm, receiver, r3, r6, 396 GenerateKeyedLoadReceiverCheck(masm, receiver, r3, r6,
382 Map::kHasIndexedInterceptor, &slow); 397 Map::kHasIndexedInterceptor, &slow);
383 398
384 // Check the receiver's map to see if it has fast elements. 399 // Check the receiver's map to see if it has fast elements.
385 __ CheckFastElements(r3, r6, &check_number_dictionary); 400 __ CheckFastElements(r3, r6, &check_number_dictionary);
386 401
387 GenerateFastArrayLoad(masm, receiver, key, r3, r6, r7, r3, &slow); 402 GenerateFastArrayLoad(masm, receiver, key, r3, r6, r7, r3, &slow,
403 language_mode);
388 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r7, r6); 404 __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r7, r6);
389 __ Ret(); 405 __ Ret();
390 406
391 __ bind(&check_number_dictionary); 407 __ bind(&check_number_dictionary);
392 __ LoadP(r7, FieldMemOperand(receiver, JSObject::kElementsOffset)); 408 __ LoadP(r7, FieldMemOperand(receiver, JSObject::kElementsOffset));
393 __ LoadP(r6, FieldMemOperand(r7, JSObject::kMapOffset)); 409 __ LoadP(r6, FieldMemOperand(r7, JSObject::kMapOffset));
394 410
395 // Check whether the elements is a number dictionary. 411 // Check whether the elements is a number dictionary.
396 // r6: elements map 412 // r6: elements map
397 // r7: elements 413 // r7: elements
398 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 414 __ LoadRoot(ip, Heap::kHashTableMapRootIndex);
399 __ cmp(r6, ip); 415 __ cmp(r6, ip);
400 __ bne(&slow); 416 __ bne(&slow);
401 __ SmiUntag(r3, key); 417 __ SmiUntag(r3, key);
402 __ LoadFromNumberDictionary(&slow, r7, key, r3, r3, r6, r8); 418 __ LoadFromNumberDictionary(&slow, r7, key, r3, r3, r6, r8);
403 __ Ret(); 419 __ Ret();
404 420
405 // Slow case, key and receiver still in r3 and r4. 421 // Slow case, key and receiver still in r3 and r4.
406 __ bind(&slow); 422 __ bind(&slow);
407 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r7, 423 __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r7,
408 r6); 424 r6);
409 GenerateRuntimeGetProperty(masm); 425 GenerateRuntimeGetProperty(masm, language_mode);
410 426
411 __ bind(&check_name); 427 __ bind(&check_name);
412 GenerateKeyNameCheck(masm, key, r3, r6, &index_name, &slow); 428 GenerateKeyNameCheck(masm, key, r3, r6, &index_name, &slow);
413 429
414 GenerateKeyedLoadReceiverCheck(masm, receiver, r3, r6, 430 GenerateKeyedLoadReceiverCheck(masm, receiver, r3, r6,
415 Map::kHasNamedInterceptor, &slow); 431 Map::kHasNamedInterceptor, &slow);
416 432
417 // If the receiver is a fast-case object, check the stub cache. Otherwise 433 // If the receiver is a fast-case object, check the stub cache. Otherwise
418 // probe the dictionary. 434 // probe the dictionary.
419 __ LoadP(r6, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 435 __ LoadP(r6, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 patcher.EmitCondition(ne); 914 patcher.EmitCondition(ne);
899 } else { 915 } else {
900 DCHECK(Assembler::GetCondition(branch_instr) == ne); 916 DCHECK(Assembler::GetCondition(branch_instr) == ne);
901 patcher.EmitCondition(eq); 917 patcher.EmitCondition(eq);
902 } 918 }
903 } 919 }
904 } // namespace internal 920 } // namespace internal
905 } // namespace v8 921 } // namespace v8
906 922
907 #endif // V8_TARGET_ARCH_PPC 923 #endif // V8_TARGET_ARCH_PPC
OLDNEW
« no previous file with comments | « src/ic/mips64/ic-mips64.cc ('k') | src/ic/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698