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 |