| 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 |