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

Side by Side Diff: src/arm/builtins-arm.cc

Issue 1468073004: Reshuffle registers in JSConstructStub to avoid trashing costructor and new.target on fast path (so… (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years 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 | « no previous file | src/arm/code-stubs-arm.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 #if V8_TARGET_ARCH_ARM 5 #if V8_TARGET_ARCH_ARM
6 6
7 #include "src/codegen.h" 7 #include "src/codegen.h"
8 #include "src/debug/debug.h" 8 #include "src/debug/debug.h"
9 #include "src/deoptimizer.h" 9 #include "src/deoptimizer.h"
10 #include "src/full-codegen/full-codegen.h" 10 #include "src/full-codegen/full-codegen.h"
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 { 355 {
356 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); 356 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT);
357 357
358 // Preserve the incoming parameters on the stack. 358 // Preserve the incoming parameters on the stack.
359 __ AssertUndefinedOrAllocationSite(r2, r4); 359 __ AssertUndefinedOrAllocationSite(r2, r4);
360 __ push(r2); 360 __ push(r2);
361 __ SmiTag(r0); 361 __ SmiTag(r0);
362 __ push(r0); 362 __ push(r0);
363 363
364 if (create_implicit_receiver) { 364 if (create_implicit_receiver) {
365 __ push(r1);
366 __ push(r3);
367
368 // Try to allocate the object without transitioning into C code. If any of 365 // Try to allocate the object without transitioning into C code. If any of
369 // the preconditions is not met, the code bails out to the runtime call. 366 // the preconditions is not met, the code bails out to the runtime call.
370 Label rt_call, allocated; 367 Label rt_call, allocated;
371 if (FLAG_inline_new) { 368 if (FLAG_inline_new) {
372 // Verify that the new target is a JSFunction. 369 // Verify that the new target is a JSFunction.
373 __ CompareObjectType(r3, r5, r4, JS_FUNCTION_TYPE); 370 __ CompareObjectType(r3, r5, r4, JS_FUNCTION_TYPE);
374 __ b(ne, &rt_call); 371 __ b(ne, &rt_call);
375 372
376 // Load the initial map and verify that it is in fact a map. 373 // Load the initial map and verify that it is in fact a map.
377 // r3: new target 374 // r3: new target
378 __ ldr(r2, 375 __ ldr(r2,
379 FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset)); 376 FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset));
380 __ JumpIfSmi(r2, &rt_call); 377 __ JumpIfSmi(r2, &rt_call);
381 __ CompareObjectType(r2, r5, r4, MAP_TYPE); 378 __ CompareObjectType(r2, r5, r4, MAP_TYPE);
382 __ b(ne, &rt_call); 379 __ b(ne, &rt_call);
383 380
384 // Fall back to runtime if the expected base constructor and base 381 // Fall back to runtime if the expected base constructor and base
385 // constructor differ. 382 // constructor differ.
386 __ ldr(r5, FieldMemOperand(r2, Map::kConstructorOrBackPointerOffset)); 383 __ ldr(r5, FieldMemOperand(r2, Map::kConstructorOrBackPointerOffset));
387 __ cmp(r1, r5); 384 __ cmp(r1, r5);
388 __ b(ne, &rt_call); 385 __ b(ne, &rt_call);
389 386
390 // Check that the constructor is not constructing a JSFunction (see 387 // Check that the constructor is not constructing a JSFunction (see
391 // comments in Runtime_NewObject in runtime.cc). In which case the 388 // comments in Runtime_NewObject in runtime.cc). In which case the
392 // initial map's instance type would be JS_FUNCTION_TYPE. 389 // initial map's instance type would be JS_FUNCTION_TYPE.
393 // r1: constructor function 390 // r1: constructor function
394 // r2: initial map 391 // r2: initial map
392 // r3: new target
395 __ CompareInstanceType(r2, r5, JS_FUNCTION_TYPE); 393 __ CompareInstanceType(r2, r5, JS_FUNCTION_TYPE);
396 __ b(eq, &rt_call); 394 __ b(eq, &rt_call);
397 395
398 if (!is_api_function) { 396 if (!is_api_function) {
399 Label allocate; 397 Label allocate;
400 MemOperand bit_field3 = FieldMemOperand(r2, Map::kBitField3Offset); 398 MemOperand bit_field3 = FieldMemOperand(r2, Map::kBitField3Offset);
401 // Check if slack tracking is enabled. 399 // Check if slack tracking is enabled.
402 __ ldr(r4, bit_field3); 400 __ ldr(r4, bit_field3);
403 __ DecodeField<Map::Counter>(r3, r4); 401 __ DecodeField<Map::Counter>(r0, r4);
404 __ cmp(r3, Operand(Map::kSlackTrackingCounterEnd)); 402 __ cmp(r0, Operand(Map::kSlackTrackingCounterEnd));
405 __ b(lt, &allocate); 403 __ b(lt, &allocate);
406 // Decrease generous allocation count. 404 // Decrease generous allocation count.
407 __ sub(r4, r4, Operand(1 << Map::Counter::kShift)); 405 __ sub(r4, r4, Operand(1 << Map::Counter::kShift));
408 __ str(r4, bit_field3); 406 __ str(r4, bit_field3);
409 __ cmp(r3, Operand(Map::kSlackTrackingCounterEnd)); 407 __ cmp(r0, Operand(Map::kSlackTrackingCounterEnd));
410 __ b(ne, &allocate); 408 __ b(ne, &allocate);
411 409
412 __ Push(r1, r2); 410 // Push the constructor, new_target and map to the stack, and
411 // the map again as an argument to the runtime call.
412 __ Push(r1, r3, r2);
413 413
414 __ push(r2); // r2 = intial map 414 __ push(r2);
415 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 415 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
416 416
417 __ pop(r2); 417 __ Pop(r1, r3, r2);
418 __ pop(r1); 418 __ mov(r0, Operand(Map::kSlackTrackingCounterEnd - 1));
419 419
420 __ bind(&allocate); 420 __ bind(&allocate);
421 } 421 }
422 422
423 // Now allocate the JSObject on the heap. 423 // Now allocate the JSObject on the heap.
424 // r1: constructor function 424 // r1: constructor function
425 // r2: initial map 425 // r2: initial map
426 Label rt_call_reload_new_target; 426 // r3: new target
427 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); 427 // r0: slack tracking counter (non-API function case)
428 __ ldrb(r9, FieldMemOperand(r2, Map::kInstanceSizeOffset));
428 429
429 __ Allocate(r3, r4, r3, r6, &rt_call_reload_new_target, SIZE_IN_WORDS); 430 __ Allocate(r9, r4, r9, r6, &rt_call, SIZE_IN_WORDS);
430 431
431 // Allocated the JSObject, now initialize the fields. Map is set to 432 // Allocated the JSObject, now initialize the fields. Map is set to
432 // initial map and properties and elements are set to empty fixed array. 433 // initial map and properties and elements are set to empty fixed array.
433 // r1: constructor function 434 // r1: constructor function
434 // r2: initial map 435 // r2: initial map
436 // r3: new target
435 // r4: JSObject (not tagged) 437 // r4: JSObject (not tagged)
436 // r3: start of next object 438 // r9: start of next object
439 // r0: slack tracking counter (non-API function case)
437 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); 440 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
438 __ mov(r5, r4); 441 __ mov(r5, r4);
439 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset); 442 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset);
440 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); 443 __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
441 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset); 444 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset);
442 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 445 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
443 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset); 446 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset);
444 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); 447 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
448 STATIC_ASSERT(3 * kPointerSize == JSObject::kHeaderSize);
445 449
446 // Fill all the in-object properties with the appropriate filler. 450 // Fill all the in-object properties with the appropriate filler.
447 // r1: constructor function
448 // r2: initial map
449 // r4: JSObject (not tagged)
450 // r3: start of next object
451 // r5: First in-object property of JSObject (not tagged) 451 // r5: First in-object property of JSObject (not tagged)
452 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
453 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); 452 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
454 453
455 if (!is_api_function) { 454 if (!is_api_function) {
456 Label no_inobject_slack_tracking; 455 Label no_inobject_slack_tracking;
457 456
458 // Check if slack tracking is enabled. 457 // Check if slack tracking is enabled.
459 __ ldr(ip, FieldMemOperand(r2, Map::kBitField3Offset)); 458 __ cmp(r0, Operand(Map::kSlackTrackingCounterEnd));
460 __ DecodeField<Map::Counter>(ip);
461 __ cmp(ip, Operand(Map::kSlackTrackingCounterEnd));
462 __ b(lt, &no_inobject_slack_tracking); 459 __ b(lt, &no_inobject_slack_tracking);
463 460
464 // Allocate object with a slack. 461 // Allocate object with a slack.
465 __ ldr(r2, FieldMemOperand(r2, Map::kInstanceAttributesOffset)); 462 __ ldr(r2, FieldMemOperand(r2, Map::kInstanceAttributesOffset));
466 __ Ubfx(r2, r2, Map::kUnusedPropertyFieldsByte * kBitsPerByte, 463 __ Ubfx(r2, r2, Map::kUnusedPropertyFieldsByte * kBitsPerByte,
467 kBitsPerByte); 464 kBitsPerByte);
468 __ sub(r0, r3, Operand(r2, LSL, kPointerSizeLog2)); 465 __ sub(r0, r9, Operand(r2, LSL, kPointerSizeLog2));
469 // r0: offset of first field after pre-allocated fields 466 // r0: offset of first field after pre-allocated fields
470 if (FLAG_debug_code) { 467 if (FLAG_debug_code) {
471 __ cmp(r5, r0); 468 __ cmp(r5, r0);
472 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); 469 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
473 } 470 }
474 __ InitializeFieldsWithFiller(r5, r0, r6); 471 __ InitializeFieldsWithFiller(r5, r0, r6);
475 // To allow for truncation. 472
473 // To allow truncation fill the remaining fields with one pointer
474 // filler map.
476 __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex); 475 __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex);
477 // Fill the remaining fields with one pointer filler map.
478 476
479 __ bind(&no_inobject_slack_tracking); 477 __ bind(&no_inobject_slack_tracking);
480 } 478 }
481 479
482 __ InitializeFieldsWithFiller(r5, r3, r6); 480 __ InitializeFieldsWithFiller(r5, r9, r6);
483 481
484 // Add the object tag to make the JSObject real, so that we can continue 482 // Add the object tag to make the JSObject real, so that we can continue
485 // and jump into the continuation code at any time from now on. 483 // and jump into the continuation code at any time from now on.
486 __ add(r4, r4, Operand(kHeapObjectTag)); 484 __ add(r4, r4, Operand(kHeapObjectTag));
487 485
488 // Continue with JSObject being successfully allocated 486 // Continue with JSObject being successfully allocated
487 // r1: constructor function
488 // r3: new target
489 // r4: JSObject 489 // r4: JSObject
490 __ jmp(&allocated); 490 __ jmp(&allocated);
491
492 // Reload the new target and fall-through.
493 __ bind(&rt_call_reload_new_target);
494 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
495 } 491 }
496 492
497 // Allocate the new receiver object using the runtime call. 493 // Allocate the new receiver object using the runtime call.
498 // r1: constructor function 494 // r1: constructor function
499 // r3: new target 495 // r3: new target
500 __ bind(&rt_call); 496 __ bind(&rt_call);
501 497
502 __ push(r1); // constructor function 498 // Push the constructor and new_target twice, second pair as arguments
503 __ push(r3); // new target 499 // to the runtime call.
500 __ Push(r1, r3);
501 __ Push(r1, r3); // constructor function, new target
504 __ CallRuntime(Runtime::kNewObject, 2); 502 __ CallRuntime(Runtime::kNewObject, 2);
505 __ mov(r4, r0); 503 __ mov(r4, r0);
504 __ Pop(r1, r3);
506 505
507 // Receiver for constructor call allocated. 506 // Receiver for constructor call allocated.
507 // r1: constructor function
508 // r3: new target
508 // r4: JSObject 509 // r4: JSObject
509 __ bind(&allocated); 510 __ bind(&allocated);
510 511
511 // Restore the parameters.
512 __ pop(r3);
513 __ pop(r1);
514
515 // Retrieve smi-tagged arguments count from the stack. 512 // Retrieve smi-tagged arguments count from the stack.
516 __ ldr(r0, MemOperand(sp)); 513 __ ldr(r0, MemOperand(sp));
517 } 514 }
518 515
519 __ SmiUntag(r0); 516 __ SmiUntag(r0);
520 517
521 // Push new.target onto the construct frame. This is stored just below the 518 // Push new.target onto the construct frame. This is stored just below the
522 // receiver on the stack. 519 // receiver on the stack.
523 __ push(r3); 520 __ push(r3);
524 521
(...skipping 1313 matching lines...) Expand 10 before | Expand all | Expand 10 after
1838 } 1835 }
1839 } 1836 }
1840 1837
1841 1838
1842 #undef __ 1839 #undef __
1843 1840
1844 } // namespace internal 1841 } // namespace internal
1845 } // namespace v8 1842 } // namespace v8
1846 1843
1847 #endif // V8_TARGET_ARCH_ARM 1844 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « no previous file | src/arm/code-stubs-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698