MIPS: Reland r21442 "Inobject slack tracking is done on a per-closure basis instead of per-shared info basis."
Port r21457 (8db39a8) Original commit message: This fixes inobject slack tracking for prototype inheritance pattern that uses closures. BUG= R=plind44@gmail.com Review URL: https://codereview.chromium.org/294973013 Patch from Balazs Kilvady <kilvadyb@homejinni.com>. git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21470 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9c485e182b
commit
50e9d22a44
@ -319,7 +319,6 @@ void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
|
||||
|
||||
static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
||||
bool is_api_function,
|
||||
bool count_constructions,
|
||||
bool create_memento) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a0 : number of arguments
|
||||
@ -329,15 +328,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
||||
// -- sp[...]: constructor arguments
|
||||
// -----------------------------------
|
||||
|
||||
// Should never count constructions for api objects.
|
||||
ASSERT(!is_api_function || !count_constructions);
|
||||
|
||||
// Should never create mementos for api functions.
|
||||
ASSERT(!is_api_function || !create_memento);
|
||||
|
||||
// Should never create mementos before slack tracking is finished.
|
||||
ASSERT(!count_constructions || !create_memento);
|
||||
|
||||
Isolate* isolate = masm->isolate();
|
||||
|
||||
// ----------- S t a t e -------------
|
||||
@ -360,9 +353,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
||||
__ sll(a0, a0, kSmiTagSize); // Tag arguments count.
|
||||
__ MultiPushReversed(a0.bit() | a1.bit());
|
||||
|
||||
// Use t7 to hold undefined, which is used in several places below.
|
||||
__ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
|
||||
|
||||
Label rt_call, allocated;
|
||||
// Try to allocate the object without transitioning into C code. If any of
|
||||
// the preconditions is not met, the code bails out to the runtime call.
|
||||
@ -389,19 +379,23 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
||||
__ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
|
||||
__ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
|
||||
|
||||
if (count_constructions) {
|
||||
// Use t7 to hold undefined, which is used in several places below.
|
||||
__ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
|
||||
|
||||
if (!is_api_function) {
|
||||
Label allocate;
|
||||
MemOperand bit_field3 = FieldMemOperand(a2, Map::kBitField3Offset);
|
||||
// Check if slack tracking is enabled.
|
||||
__ lw(t0, bit_field3);
|
||||
__ DecodeField<Map::ConstructionCount>(t2, t0);
|
||||
__ Branch(&allocate, eq, t2, Operand(JSFunction::kNoSlackTracking));
|
||||
// Decrease generous allocation count.
|
||||
__ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
|
||||
MemOperand constructor_count =
|
||||
FieldMemOperand(a3, SharedFunctionInfo::kConstructionCountOffset);
|
||||
__ lbu(t0, constructor_count);
|
||||
__ Subu(t0, t0, Operand(1));
|
||||
__ sb(t0, constructor_count);
|
||||
__ Branch(&allocate, ne, t0, Operand(zero_reg));
|
||||
__ Subu(t0, t0, Operand(1 << Map::ConstructionCount::kShift));
|
||||
__ Branch(USE_DELAY_SLOT,
|
||||
&allocate, ne, t2, Operand(JSFunction::kFinishSlackTracking));
|
||||
__ sw(t0, bit_field3); // In delay slot.
|
||||
|
||||
__ Push(a1, a2, a1); // a1 = Constructor.
|
||||
// The call will replace the stub, so the countdown is only done once.
|
||||
__ CallRuntime(Runtime::kHiddenFinalizeInstanceSize, 1);
|
||||
|
||||
__ Pop(a1, a2);
|
||||
@ -441,29 +435,39 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
||||
// a3: object size (in words, including memento if create_memento)
|
||||
// t4: JSObject (not tagged)
|
||||
// t5: First in-object property of JSObject (not tagged)
|
||||
// t2: slack tracking counter (non-API function case)
|
||||
ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize);
|
||||
|
||||
if (count_constructions) {
|
||||
__ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
|
||||
if (!is_api_function) {
|
||||
Label no_inobject_slack_tracking;
|
||||
|
||||
// Check if slack tracking is enabled.
|
||||
__ Branch(&no_inobject_slack_tracking,
|
||||
eq, t2, Operand(JSFunction::kNoSlackTracking));
|
||||
|
||||
// Allocate object with a slack.
|
||||
__ lbu(a0, FieldMemOperand(a2, Map::kPreAllocatedPropertyFieldsOffset));
|
||||
__ sll(at, a0, kPointerSizeLog2);
|
||||
__ addu(a0, t5, at);
|
||||
__ sll(at, a3, kPointerSizeLog2);
|
||||
__ Addu(t6, t4, Operand(at)); // End of object.
|
||||
// a0: offset of first field after pre-allocated fields
|
||||
if (FLAG_debug_code) {
|
||||
__ sll(at, a3, kPointerSizeLog2);
|
||||
__ Addu(t6, t4, Operand(at)); // End of object.
|
||||
__ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields,
|
||||
a0, Operand(t6));
|
||||
}
|
||||
__ InitializeFieldsWithFiller(t5, a0, t7);
|
||||
// To allow for truncation.
|
||||
__ LoadRoot(t7, Heap::kOnePointerFillerMapRootIndex);
|
||||
__ InitializeFieldsWithFiller(t5, t6, t7);
|
||||
} else if (create_memento) {
|
||||
__ Subu(t7, a3, Operand(AllocationMemento::kSize / kPointerSize));
|
||||
__ sll(at, t7, kPointerSizeLog2);
|
||||
__ Addu(a0, t4, Operand(at)); // End of object.
|
||||
__ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
|
||||
// Fill the remaining fields with one pointer filler map.
|
||||
|
||||
__ bind(&no_inobject_slack_tracking);
|
||||
}
|
||||
|
||||
if (create_memento) {
|
||||
__ Subu(a0, a3, Operand(AllocationMemento::kSize / kPointerSize));
|
||||
__ sll(a0, a0, kPointerSizeLog2);
|
||||
__ Addu(a0, t4, Operand(a0)); // End of object.
|
||||
__ InitializeFieldsWithFiller(t5, a0, t7);
|
||||
|
||||
// Fill in memento fields.
|
||||
@ -478,7 +482,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
||||
__ sw(t7, MemOperand(t5));
|
||||
__ Addu(t5, t5, kPointerSize);
|
||||
} else {
|
||||
__ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
|
||||
__ sll(at, a3, kPointerSizeLog2);
|
||||
__ Addu(a0, t4, Operand(at)); // End of object.
|
||||
__ InitializeFieldsWithFiller(t5, a0, t7);
|
||||
@ -548,11 +551,11 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
||||
__ addu(t6, a2, t3); // End of object.
|
||||
ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize);
|
||||
{ Label loop, entry;
|
||||
if (count_constructions) {
|
||||
if (!is_api_function || create_memento) {
|
||||
__ LoadRoot(t7, Heap::kUndefinedValueRootIndex);
|
||||
} else if (FLAG_debug_code) {
|
||||
__ LoadRoot(t8, Heap::kUndefinedValueRootIndex);
|
||||
__ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t8));
|
||||
__ LoadRoot(t2, Heap::kUndefinedValueRootIndex);
|
||||
__ Assert(eq, kUndefinedValueNotLoaded, t7, Operand(t2));
|
||||
}
|
||||
__ jmp(&entry);
|
||||
__ bind(&loop);
|
||||
@ -676,7 +679,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
// Store offset of return address for deoptimizer.
|
||||
if (!is_api_function && !count_constructions) {
|
||||
if (!is_api_function) {
|
||||
masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
|
||||
}
|
||||
|
||||
@ -725,18 +728,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) {
|
||||
Generate_JSConstructStubHelper(masm, false, true, false);
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
|
||||
Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new);
|
||||
Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new);
|
||||
}
|
||||
|
||||
|
||||
void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
|
||||
Generate_JSConstructStubHelper(masm, true, false, false);
|
||||
Generate_JSConstructStubHelper(masm, true, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1484,11 +1484,19 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
|
||||
void NumberOfOwnDescriptors(Register dst, Register map);
|
||||
|
||||
template<typename Field>
|
||||
void DecodeField(Register reg) {
|
||||
void DecodeField(Register dst, Register src) {
|
||||
static const int shift = Field::kShift;
|
||||
static const int mask = Field::kMask >> shift;
|
||||
srl(reg, reg, shift);
|
||||
And(reg, reg, Operand(mask));
|
||||
static const int size = Field::kSize;
|
||||
srl(dst, src, shift);
|
||||
if (shift + size != 32) {
|
||||
And(dst, dst, Operand(mask));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Field>
|
||||
void DecodeField(Register reg) {
|
||||
DecodeField<Field>(reg, reg);
|
||||
}
|
||||
|
||||
// Generates function and stub prologue code.
|
||||
|
Loading…
Reference in New Issue
Block a user