OLD | NEW |
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 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 | 378 |
379 // Check that the constructor is not constructing a JSFunction (see | 379 // Check that the constructor is not constructing a JSFunction (see |
380 // comments in Runtime_NewObject in runtime.cc). In which case the | 380 // comments in Runtime_NewObject in runtime.cc). In which case the |
381 // initial map's instance type would be JS_FUNCTION_TYPE. | 381 // initial map's instance type would be JS_FUNCTION_TYPE. |
382 // r1: constructor function | 382 // r1: constructor function |
383 // r2: initial map | 383 // r2: initial map |
384 // r3: new target | 384 // r3: new target |
385 __ CompareInstanceType(r2, r5, JS_FUNCTION_TYPE); | 385 __ CompareInstanceType(r2, r5, JS_FUNCTION_TYPE); |
386 __ b(eq, &rt_call); | 386 __ b(eq, &rt_call); |
387 | 387 |
388 if (!is_api_function) { | |
389 Label allocate; | |
390 MemOperand bit_field3 = FieldMemOperand(r2, Map::kBitField3Offset); | |
391 // Check if slack tracking is enabled. | |
392 __ ldr(r4, bit_field3); | |
393 __ DecodeField<Map::Counter>(r0, r4); | |
394 __ cmp(r0, Operand(Map::kSlackTrackingCounterEnd)); | |
395 __ b(lt, &allocate); | |
396 // Decrease generous allocation count. | |
397 __ sub(r4, r4, Operand(1 << Map::Counter::kShift)); | |
398 __ str(r4, bit_field3); | |
399 __ cmp(r0, Operand(Map::kSlackTrackingCounterEnd)); | |
400 __ b(ne, &allocate); | |
401 | |
402 // Push the constructor, new_target and map to the stack, and | |
403 // the map again as an argument to the runtime call. | |
404 __ Push(r1, r3, r2); | |
405 | |
406 __ push(r2); | |
407 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | |
408 | |
409 __ Pop(r1, r3, r2); | |
410 __ mov(r0, Operand(Map::kSlackTrackingCounterEnd - 1)); | |
411 | |
412 __ bind(&allocate); | |
413 } | |
414 | |
415 // Now allocate the JSObject on the heap. | 388 // Now allocate the JSObject on the heap. |
416 // r1: constructor function | 389 // r1: constructor function |
417 // r2: initial map | 390 // r2: initial map |
418 // r3: new target | 391 // r3: new target |
419 // r0: slack tracking counter (non-API function case) | |
420 __ ldrb(r9, FieldMemOperand(r2, Map::kInstanceSizeOffset)); | 392 __ ldrb(r9, FieldMemOperand(r2, Map::kInstanceSizeOffset)); |
421 | 393 |
422 __ Allocate(r9, r4, r9, r6, &rt_call, SIZE_IN_WORDS); | 394 __ Allocate(r9, r4, r9, r6, &rt_call, SIZE_IN_WORDS); |
423 | 395 |
424 // Allocated the JSObject, now initialize the fields. Map is set to | 396 // Allocated the JSObject, now initialize the fields. Map is set to |
425 // initial map and properties and elements are set to empty fixed array. | 397 // initial map and properties and elements are set to empty fixed array. |
426 // r1: constructor function | 398 // r1: constructor function |
427 // r2: initial map | 399 // r2: initial map |
428 // r3: new target | 400 // r3: new target |
429 // r4: JSObject (not tagged) | 401 // r4: JSObject (not HeapObject tagged - the actual address). |
430 // r9: start of next object | 402 // r9: start of next object |
431 // r0: slack tracking counter (non-API function case) | |
432 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); | 403 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); |
433 __ mov(r5, r4); | 404 __ mov(r5, r4); |
434 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset); | 405 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset); |
435 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); | 406 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); |
436 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset); | 407 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset); |
437 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); | 408 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
438 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset); | 409 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset); |
439 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); | 410 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
440 STATIC_ASSERT(3 * kPointerSize == JSObject::kHeaderSize); | 411 STATIC_ASSERT(3 * kPointerSize == JSObject::kHeaderSize); |
441 | 412 |
| 413 // Add the object tag to make the JSObject real, so that we can continue |
| 414 // and jump into the continuation code at any time from now on. |
| 415 __ add(r4, r4, Operand(kHeapObjectTag)); |
| 416 |
442 // Fill all the in-object properties with the appropriate filler. | 417 // Fill all the in-object properties with the appropriate filler. |
| 418 // r4: JSObject (tagged) |
443 // r5: First in-object property of JSObject (not tagged) | 419 // r5: First in-object property of JSObject (not tagged) |
444 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); | 420 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex); |
445 | 421 |
446 if (!is_api_function) { | 422 if (!is_api_function) { |
447 Label no_inobject_slack_tracking; | 423 Label no_inobject_slack_tracking; |
448 | 424 |
449 // Check if slack tracking is enabled. | 425 // Check if slack tracking is enabled. |
450 __ cmp(r0, Operand(Map::kSlackTrackingCounterEnd)); | 426 MemOperand bit_field3 = FieldMemOperand(r2, Map::kBitField3Offset); |
| 427 // Check if slack tracking is enabled. |
| 428 __ ldr(r0, bit_field3); |
| 429 __ DecodeField<Map::Counter>(ip, r0); |
| 430 // ip: slack tracking counter |
| 431 __ cmp(ip, Operand(Map::kSlackTrackingCounterEnd)); |
451 __ b(lt, &no_inobject_slack_tracking); | 432 __ b(lt, &no_inobject_slack_tracking); |
| 433 __ push(ip); // Save allocation count value. |
| 434 // Decrease generous allocation count. |
| 435 __ sub(r0, r0, Operand(1 << Map::Counter::kShift)); |
| 436 __ str(r0, bit_field3); |
452 | 437 |
453 // Allocate object with a slack. | 438 // Allocate object with a slack. |
454 __ ldr(r2, FieldMemOperand(r2, Map::kInstanceAttributesOffset)); | 439 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceAttributesOffset)); |
455 __ Ubfx(r2, r2, Map::kUnusedPropertyFieldsByte * kBitsPerByte, | 440 __ Ubfx(r0, r0, Map::kUnusedPropertyFieldsByte * kBitsPerByte, |
456 kBitsPerByte); | 441 kBitsPerByte); |
457 __ sub(r0, r9, Operand(r2, LSL, kPointerSizeLog2)); | 442 __ sub(r0, r9, Operand(r0, LSL, kPointerSizeLog2)); |
458 // r0: offset of first field after pre-allocated fields | 443 // r0: offset of first field after pre-allocated fields |
459 if (FLAG_debug_code) { | 444 if (FLAG_debug_code) { |
460 __ cmp(r5, r0); | 445 __ cmp(r5, r0); |
461 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); | 446 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields); |
462 } | 447 } |
463 __ InitializeFieldsWithFiller(r5, r0, r6); | 448 __ InitializeFieldsWithFiller(r5, r0, r6); |
464 | 449 |
465 // To allow truncation fill the remaining fields with one pointer | 450 // To allow truncation fill the remaining fields with one pointer |
466 // filler map. | 451 // filler map. |
467 __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex); | 452 __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex); |
| 453 __ InitializeFieldsWithFiller(r5, r9, r6); |
| 454 |
| 455 __ pop(r0); // Restore allocation count value before decreasing. |
| 456 __ cmp(r0, Operand(Map::kSlackTrackingCounterEnd)); |
| 457 __ b(ne, &allocated); |
| 458 |
| 459 // Push the constructor, new_target and the object to the stack, |
| 460 // and then the initial map as an argument to the runtime call. |
| 461 __ Push(r1, r3, r4, r2); |
| 462 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
| 463 __ Pop(r1, r3, r4); |
| 464 |
| 465 // Continue with JSObject being successfully allocated |
| 466 // r1: constructor function |
| 467 // r3: new target |
| 468 // r4: JSObject |
| 469 __ jmp(&allocated); |
468 | 470 |
469 __ bind(&no_inobject_slack_tracking); | 471 __ bind(&no_inobject_slack_tracking); |
470 } | 472 } |
471 | 473 |
472 __ InitializeFieldsWithFiller(r5, r9, r6); | 474 __ InitializeFieldsWithFiller(r5, r9, r6); |
473 | 475 |
474 // Add the object tag to make the JSObject real, so that we can continue | |
475 // and jump into the continuation code at any time from now on. | |
476 __ add(r4, r4, Operand(kHeapObjectTag)); | |
477 | |
478 // Continue with JSObject being successfully allocated | 476 // Continue with JSObject being successfully allocated |
479 // r1: constructor function | 477 // r1: constructor function |
480 // r3: new target | 478 // r3: new target |
481 // r4: JSObject | 479 // r4: JSObject |
482 __ jmp(&allocated); | 480 __ jmp(&allocated); |
483 } | 481 } |
484 | 482 |
485 // Allocate the new receiver object using the runtime call. | 483 // Allocate the new receiver object using the runtime call. |
486 // r1: constructor function | 484 // r1: constructor function |
487 // r3: new target | 485 // r3: new target |
(...skipping 1469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1957 } | 1955 } |
1958 } | 1956 } |
1959 | 1957 |
1960 | 1958 |
1961 #undef __ | 1959 #undef __ |
1962 | 1960 |
1963 } // namespace internal | 1961 } // namespace internal |
1964 } // namespace v8 | 1962 } // namespace v8 |
1965 | 1963 |
1966 #endif // V8_TARGET_ARCH_ARM | 1964 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |