| 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_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
| 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 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 __ Branch(&rt_call, ne, a1, Operand(t1)); | 386 __ Branch(&rt_call, ne, a1, Operand(t1)); |
| 387 | 387 |
| 388 // Check that the constructor is not constructing a JSFunction (see | 388 // Check that the constructor is not constructing a JSFunction (see |
| 389 // comments in Runtime_NewObject in runtime.cc). In which case the | 389 // comments in Runtime_NewObject in runtime.cc). In which case the |
| 390 // initial map's instance type would be JS_FUNCTION_TYPE. | 390 // initial map's instance type would be JS_FUNCTION_TYPE. |
| 391 // a1: constructor function | 391 // a1: constructor function |
| 392 // a2: initial map | 392 // a2: initial map |
| 393 __ lbu(t5, FieldMemOperand(a2, Map::kInstanceTypeOffset)); | 393 __ lbu(t5, FieldMemOperand(a2, Map::kInstanceTypeOffset)); |
| 394 __ Branch(&rt_call, eq, t5, Operand(JS_FUNCTION_TYPE)); | 394 __ Branch(&rt_call, eq, t5, Operand(JS_FUNCTION_TYPE)); |
| 395 | 395 |
| 396 if (!is_api_function) { | |
| 397 Label allocate; | |
| 398 MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset); | |
| 399 // Check if slack tracking is enabled. | |
| 400 __ lw(t0, bit_field3); | |
| 401 __ DecodeField<Map::Counter>(t2, t0); | |
| 402 __ Branch(&allocate, lt, t2, Operand(Map::kSlackTrackingCounterEnd)); | |
| 403 // Decrease generous allocation count. | |
| 404 __ Subu(t0, t0, Operand(1 << Map::Counter::kShift)); | |
| 405 __ Branch(USE_DELAY_SLOT, &allocate, ne, t2, | |
| 406 Operand(Map::kSlackTrackingCounterEnd)); | |
| 407 __ sw(t0, bit_field3); // In delay slot. | |
| 408 | |
| 409 // Push the constructor, new_target and map to the stack, and | |
| 410 // the map again as an argument to the runtime call. | |
| 411 __ Push(a1, a3, a2, a2); | |
| 412 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | |
| 413 | |
| 414 __ Pop(a1, a3, a2); | |
| 415 __ li(t2, Operand(Map::kSlackTrackingCounterEnd - 1)); | |
| 416 | |
| 417 __ bind(&allocate); | |
| 418 } | |
| 419 | |
| 420 // Now allocate the JSObject on the heap. | 396 // Now allocate the JSObject on the heap. |
| 421 // a1: constructor function | 397 // a1: constructor function |
| 422 // a2: initial map | 398 // a2: initial map |
| 423 // a3: new target | 399 // a3: new target |
| 424 // t2: slack tracking counter (non-API function case) | |
| 425 __ lbu(t3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); | 400 __ lbu(t3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); |
| 426 | 401 |
| 427 __ Allocate(t3, t4, t3, t6, &rt_call, SIZE_IN_WORDS); | 402 __ Allocate(t3, t4, t3, t6, &rt_call, SIZE_IN_WORDS); |
| 428 | 403 |
| 429 // Allocated the JSObject, now initialize the fields. Map is set to | 404 // Allocated the JSObject, now initialize the fields. Map is set to |
| 430 // initial map and properties and elements are set to empty fixed array. | 405 // initial map and properties and elements are set to empty fixed array. |
| 431 // a1: constructor function | 406 // a1: constructor function |
| 432 // a2: initial map | 407 // a2: initial map |
| 433 // a3: new target | 408 // a3: new target |
| 434 // t4: JSObject (not tagged) | 409 // t4: JSObject (not HeapObject tagged - the actual address). |
| 435 // t3: start of next object | 410 // t3: start of next object |
| 436 // t2: slack tracking counter (non-API function case) | |
| 437 __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex); | 411 __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex); |
| 438 __ mov(t5, t4); | 412 __ mov(t5, t4); |
| 439 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset); | 413 STATIC_ASSERT(0 * kPointerSize == JSObject::kMapOffset); |
| 440 __ sw(a2, MemOperand(t5, JSObject::kMapOffset)); | 414 __ sw(a2, MemOperand(t5, JSObject::kMapOffset)); |
| 441 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset); | 415 STATIC_ASSERT(1 * kPointerSize == JSObject::kPropertiesOffset); |
| 442 __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset)); | 416 __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset)); |
| 443 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset); | 417 STATIC_ASSERT(2 * kPointerSize == JSObject::kElementsOffset); |
| 444 __ sw(t6, MemOperand(t5, JSObject::kElementsOffset)); | 418 __ sw(t6, MemOperand(t5, JSObject::kElementsOffset)); |
| 445 STATIC_ASSERT(3 * kPointerSize == JSObject::kHeaderSize); | 419 STATIC_ASSERT(3 * kPointerSize == JSObject::kHeaderSize); |
| 446 __ Addu(t5, t5, Operand(3 * kPointerSize)); | 420 __ Addu(t5, t5, Operand(3 * kPointerSize)); |
| 447 | 421 |
| 422 // Add the object tag to make the JSObject real, so that we can continue |
| 423 // and jump into the continuation code at any time from now on. |
| 424 __ Addu(t4, t4, Operand(kHeapObjectTag)); |
| 425 |
| 448 // Fill all the in-object properties with appropriate filler. | 426 // Fill all the in-object properties with appropriate filler. |
| 427 // t4: JSObject (tagged) |
| 449 // t5: First in-object property of JSObject (not tagged) | 428 // t5: First in-object property of JSObject (not tagged) |
| 450 | |
| 451 // Use t7 to hold undefined, which is used in several places below. | |
| 452 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); | 429 __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); |
| 453 | 430 |
| 454 if (!is_api_function) { | 431 if (!is_api_function) { |
| 455 Label no_inobject_slack_tracking; | 432 Label no_inobject_slack_tracking; |
| 456 | 433 |
| 434 MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset); |
| 457 // Check if slack tracking is enabled. | 435 // Check if slack tracking is enabled. |
| 436 __ lw(t0, bit_field3); |
| 437 __ DecodeField<Map::Counter>(t2, t0); |
| 438 // t2: slack tracking counter |
| 458 __ Branch(&no_inobject_slack_tracking, lt, t2, | 439 __ Branch(&no_inobject_slack_tracking, lt, t2, |
| 459 Operand(Map::kSlackTrackingCounterEnd)); | 440 Operand(Map::kSlackTrackingCounterEnd)); |
| 441 // Decrease generous allocation count. |
| 442 __ Subu(t0, t0, Operand(1 << Map::Counter::kShift)); |
| 443 __ sw(t0, bit_field3); |
| 460 | 444 |
| 461 // Allocate object with a slack. | 445 // Allocate object with a slack. |
| 462 __ lbu(a0, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset)); | 446 __ lbu(a0, FieldMemOperand(a2, Map::kUnusedPropertyFieldsOffset)); |
| 463 __ sll(a0, a0, kPointerSizeLog2); | 447 __ sll(a0, a0, kPointerSizeLog2); |
| 464 __ subu(a0, t3, a0); | 448 __ subu(a0, t3, a0); |
| 465 // a0: offset of first field after pre-allocated fields | 449 // a0: offset of first field after pre-allocated fields |
| 466 if (FLAG_debug_code) { | 450 if (FLAG_debug_code) { |
| 467 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields, t5, | 451 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields, t5, |
| 468 Operand(a0)); | 452 Operand(a0)); |
| 469 } | 453 } |
| 470 __ InitializeFieldsWithFiller(t5, a0, t7); | 454 __ InitializeFieldsWithFiller(t5, a0, t7); |
| 471 | 455 |
| 472 // To allow truncation fill the remaining fields with one pointer | 456 // To allow truncation fill the remaining fields with one pointer |
| 473 // filler map. | 457 // filler map. |
| 474 __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex); | 458 __ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex); |
| 459 __ InitializeFieldsWithFiller(t5, t3, t7); |
| 460 |
| 461 // t2: slack tracking counter value before decreasing. |
| 462 __ Branch(&allocated, ne, t2, Operand(Map::kSlackTrackingCounterEnd)); |
| 463 |
| 464 // Push the constructor, new_target and the object to the stack, |
| 465 // and then the initial map as an argument to the runtime call. |
| 466 __ Push(a1, a3, t4, a2); |
| 467 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
| 468 __ Pop(a1, a3, t4); |
| 469 |
| 470 // Continue with JSObject being successfully allocated. |
| 471 // a1: constructor function |
| 472 // a3: new target |
| 473 // t4: JSObject |
| 474 __ jmp(&allocated); |
| 475 | 475 |
| 476 __ bind(&no_inobject_slack_tracking); | 476 __ bind(&no_inobject_slack_tracking); |
| 477 } | 477 } |
| 478 | 478 |
| 479 __ InitializeFieldsWithFiller(t5, t3, t7); | 479 __ InitializeFieldsWithFiller(t5, t3, t7); |
| 480 | 480 |
| 481 // Add the object tag to make the JSObject real, so that we can continue | |
| 482 // and jump into the continuation code at any time from now on. | |
| 483 __ Addu(t4, t4, Operand(kHeapObjectTag)); | |
| 484 | |
| 485 // Continue with JSObject being successfully allocated. | 481 // Continue with JSObject being successfully allocated. |
| 486 // a1: constructor function | 482 // a1: constructor function |
| 487 // a3: new target | 483 // a3: new target |
| 488 // t4: JSObject | 484 // t4: JSObject |
| 489 __ jmp(&allocated); | 485 __ jmp(&allocated); |
| 490 } | 486 } |
| 491 | 487 |
| 492 // Allocate the new receiver object using the runtime call. | 488 // Allocate the new receiver object using the runtime call. |
| 493 // a1: constructor function | 489 // a1: constructor function |
| 494 // a3: new target | 490 // a3: new target |
| (...skipping 1490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1985 } | 1981 } |
| 1986 } | 1982 } |
| 1987 | 1983 |
| 1988 | 1984 |
| 1989 #undef __ | 1985 #undef __ |
| 1990 | 1986 |
| 1991 } // namespace internal | 1987 } // namespace internal |
| 1992 } // namespace v8 | 1988 } // namespace v8 |
| 1993 | 1989 |
| 1994 #endif // V8_TARGET_ARCH_MIPS | 1990 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |