[cleanup] Port KeyedLoadIC_{Slow,Miss} to TF and drop unused IC handler code
BUG=v8:5269 Review-Url: https://codereview.chromium.org/2623483002 Cr-Commit-Position: refs/heads/master@{#42171}
This commit is contained in:
parent
32c0dff263
commit
099abc58a1
@ -18,11 +18,32 @@ void Builtins::Generate_KeyedLoadIC_Megamorphic_TF(
|
|||||||
AccessorAssembler::GenerateKeyedLoadICMegamorphic(state);
|
AccessorAssembler::GenerateKeyedLoadICMegamorphic(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builtins::Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
|
void Builtins::Generate_KeyedLoadIC_Miss(compiler::CodeAssemblerState* state) {
|
||||||
KeyedLoadIC::GenerateMiss(masm);
|
typedef compiler::Node Node;
|
||||||
|
typedef LoadWithVectorDescriptor Descriptor;
|
||||||
|
CodeStubAssembler assembler(state);
|
||||||
|
|
||||||
|
Node* receiver = assembler.Parameter(Descriptor::kReceiver);
|
||||||
|
Node* name = assembler.Parameter(Descriptor::kName);
|
||||||
|
Node* slot = assembler.Parameter(Descriptor::kSlot);
|
||||||
|
Node* vector = assembler.Parameter(Descriptor::kVector);
|
||||||
|
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||||
|
|
||||||
|
assembler.TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, name,
|
||||||
|
slot, vector);
|
||||||
}
|
}
|
||||||
void Builtins::Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
|
|
||||||
KeyedLoadIC::GenerateRuntimeGetProperty(masm);
|
void Builtins::Generate_KeyedLoadIC_Slow(compiler::CodeAssemblerState* state) {
|
||||||
|
typedef compiler::Node Node;
|
||||||
|
typedef LoadWithVectorDescriptor Descriptor;
|
||||||
|
CodeStubAssembler assembler(state);
|
||||||
|
|
||||||
|
Node* receiver = assembler.Parameter(Descriptor::kReceiver);
|
||||||
|
Node* name = assembler.Parameter(Descriptor::kName);
|
||||||
|
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||||
|
|
||||||
|
assembler.TailCallRuntime(Runtime::kKeyedGetProperty, context, receiver,
|
||||||
|
name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builtins::Generate_KeyedStoreIC_Megamorphic_TF(
|
void Builtins::Generate_KeyedStoreIC_Megamorphic_TF(
|
||||||
|
@ -212,8 +212,8 @@ namespace internal {
|
|||||||
/* Handlers */ \
|
/* Handlers */ \
|
||||||
TFS(KeyedLoadIC_Megamorphic_TF, KEYED_LOAD_IC, kNoExtraICState, \
|
TFS(KeyedLoadIC_Megamorphic_TF, KEYED_LOAD_IC, kNoExtraICState, \
|
||||||
LoadWithVector) \
|
LoadWithVector) \
|
||||||
ASM(KeyedLoadIC_Miss) \
|
TFS(KeyedLoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector) \
|
||||||
ASH(KeyedLoadIC_Slow, HANDLER, Code::KEYED_LOAD_IC) \
|
TFS(KeyedLoadIC_Slow, HANDLER, Code::KEYED_LOAD_IC, LoadWithVector) \
|
||||||
TFS(KeyedStoreIC_Megamorphic_TF, KEYED_STORE_IC, kNoExtraICState, \
|
TFS(KeyedStoreIC_Megamorphic_TF, KEYED_STORE_IC, kNoExtraICState, \
|
||||||
StoreWithVector) \
|
StoreWithVector) \
|
||||||
TFS(KeyedStoreIC_Megamorphic_Strict_TF, KEYED_STORE_IC, \
|
TFS(KeyedStoreIC_Megamorphic_Strict_TF, KEYED_STORE_IC, \
|
||||||
|
@ -1092,8 +1092,6 @@ class RuntimeCallTimerScope {
|
|||||||
SC(ic_compare_miss, V8.ICCompareMiss) \
|
SC(ic_compare_miss, V8.ICCompareMiss) \
|
||||||
SC(ic_call_miss, V8.ICCallMiss) \
|
SC(ic_call_miss, V8.ICCallMiss) \
|
||||||
SC(ic_keyed_call_miss, V8.ICKeyedCallMiss) \
|
SC(ic_keyed_call_miss, V8.ICKeyedCallMiss) \
|
||||||
SC(ic_load_miss, V8.ICLoadMiss) \
|
|
||||||
SC(ic_keyed_load_miss, V8.ICKeyedLoadMiss) \
|
|
||||||
SC(ic_store_miss, V8.ICStoreMiss) \
|
SC(ic_store_miss, V8.ICStoreMiss) \
|
||||||
SC(ic_keyed_store_miss, V8.ICKeyedStoreMiss) \
|
SC(ic_keyed_store_miss, V8.ICKeyedStoreMiss) \
|
||||||
SC(cow_arrays_created_runtime, V8.COWArraysCreatedRuntime) \
|
SC(cow_arrays_created_runtime, V8.COWArraysCreatedRuntime) \
|
||||||
|
@ -135,14 +135,6 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
|
|||||||
__ add(sp, sp, Operand(2 * kPointerSize));
|
__ add(sp, sp, Operand(2 * kPointerSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in lr register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in lr register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||||
MacroAssembler* masm, Label* miss_label, Register receiver,
|
MacroAssembler* masm, Label* miss_label, Register receiver,
|
||||||
Handle<Name> name, Register scratch0, Register scratch1) {
|
Handle<Name> name, Register scratch0, Register scratch1) {
|
||||||
@ -189,18 +181,6 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
|||||||
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
|
||||||
MacroAssembler* masm, int index, Register result, Label* miss) {
|
|
||||||
__ LoadNativeContextSlot(index, result);
|
|
||||||
// Load its initial map. The global functions all have initial maps.
|
|
||||||
__ ldr(result,
|
|
||||||
FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
// Load the prototype from the initial map.
|
|
||||||
__ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||||
MacroAssembler* masm, Register receiver, Register scratch1,
|
MacroAssembler* masm, Register receiver, Register scratch1,
|
||||||
Register scratch2, Label* miss_label) {
|
Register scratch2, Label* miss_label) {
|
||||||
@ -355,58 +335,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
|
|
||||||
__ mov(this->name(), Operand(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
|
|
||||||
Register map_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss) {
|
|
||||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
__ LoadWeakValue(map_reg, cell, miss);
|
|
||||||
if (transition->CanBeDeprecated()) {
|
|
||||||
__ ldr(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset));
|
|
||||||
__ tst(scratch, Operand(Map::Deprecated::kMask));
|
|
||||||
__ b(ne, miss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
|
|
||||||
int descriptor,
|
|
||||||
Register value_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss_label) {
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
DCHECK(!map_reg.is(value_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ LoadInstanceDescriptors(map_reg, scratch);
|
|
||||||
__ ldr(scratch,
|
|
||||||
FieldMemOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
|
|
||||||
__ cmp(value_reg, scratch);
|
|
||||||
__ b(ne, miss_label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
|
|
||||||
Register value_reg,
|
|
||||||
Label* miss_label) {
|
|
||||||
Register map_reg = scratch1();
|
|
||||||
Register scratch = scratch2();
|
|
||||||
DCHECK(!value_reg.is(map_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
|
||||||
if (field_type->IsClass()) {
|
|
||||||
__ ldr(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
|
||||||
__ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()),
|
|
||||||
scratch);
|
|
||||||
__ b(ne, miss_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||||
Label* miss, bool compare_native_contexts_only) {
|
Label* miss, bool compare_native_contexts_only) {
|
||||||
@ -538,13 +466,6 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
||||||
// Return the constant value.
|
|
||||||
__ Move(r0, value);
|
|
||||||
__ Ret();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupIterator* it, Register holder_reg) {
|
LookupIterator* it, Register holder_reg) {
|
||||||
DCHECK(holder()->HasNamedInterceptor());
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
|
@ -136,31 +136,6 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
|||||||
// A register that isn't one of the parameters to the load ic.
|
// A register that isn't one of the parameters to the load ic.
|
||||||
static const Register LoadIC_TempRegister() { return r3; }
|
static const Register LoadIC_TempRegister() { return r3; }
|
||||||
|
|
||||||
|
|
||||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
Register slot = LoadDescriptor::SlotRegister();
|
|
||||||
Register vector = LoadWithVectorDescriptor::VectorRegister();
|
|
||||||
|
|
||||||
__ Push(receiver, name, slot, vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_load_miss(), 1, r4, r5);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||||
// The return address is in lr.
|
// The return address is in lr.
|
||||||
|
|
||||||
@ -171,31 +146,6 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kGetProperty);
|
__ TailCallRuntime(Runtime::kGetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_keyed_load_miss(), 1, r4, r5);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
|
|
||||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
// Do tail-call to runtime routine.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedGetProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
||||||
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
||||||
StoreWithVectorDescriptor::SlotRegister(),
|
StoreWithVectorDescriptor::SlotRegister(),
|
||||||
|
@ -44,14 +44,6 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
|
|||||||
__ Drop(2);
|
__ Drop(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in lr register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in lr register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||||
MacroAssembler* masm, Label* miss_label, Register receiver,
|
MacroAssembler* masm, Label* miss_label, Register receiver,
|
||||||
Handle<Name> name, Register scratch0, Register scratch1) {
|
Handle<Name> name, Register scratch0, Register scratch1) {
|
||||||
@ -91,18 +83,6 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
|||||||
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
|
||||||
MacroAssembler* masm, int index, Register result, Label* miss) {
|
|
||||||
__ LoadNativeContextSlot(index, result);
|
|
||||||
// Load its initial map. The global functions all have initial maps.
|
|
||||||
__ Ldr(result,
|
|
||||||
FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
// Load the prototype from the initial map.
|
|
||||||
__ Ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||||
MacroAssembler* masm, Register receiver, Register scratch1,
|
MacroAssembler* masm, Register receiver, Register scratch1,
|
||||||
Register scratch2, Label* miss_label) {
|
Register scratch2, Label* miss_label) {
|
||||||
@ -386,57 +366,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
|
|
||||||
__ Mov(this->name(), Operand(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
|
|
||||||
Register map_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss) {
|
|
||||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
__ LoadWeakValue(map_reg, cell, miss);
|
|
||||||
if (transition->CanBeDeprecated()) {
|
|
||||||
__ Ldrsw(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset));
|
|
||||||
__ TestAndBranchIfAnySet(scratch, Map::Deprecated::kMask, miss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
|
|
||||||
int descriptor,
|
|
||||||
Register value_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss_label) {
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
DCHECK(!map_reg.is(value_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ LoadInstanceDescriptors(map_reg, scratch);
|
|
||||||
__ Ldr(scratch,
|
|
||||||
FieldMemOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
|
|
||||||
__ Cmp(value_reg, scratch);
|
|
||||||
__ B(ne, miss_label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
|
|
||||||
Register value_reg,
|
|
||||||
Label* miss_label) {
|
|
||||||
Register map_reg = scratch1();
|
|
||||||
Register scratch = scratch2();
|
|
||||||
DCHECK(!value_reg.is(map_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
|
||||||
if (field_type->IsClass()) {
|
|
||||||
__ Ldr(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
|
||||||
__ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()),
|
|
||||||
scratch);
|
|
||||||
__ B(ne, miss_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||||
Label* miss, bool compare_native_contexts_only) {
|
Label* miss, bool compare_native_contexts_only) {
|
||||||
@ -572,13 +501,6 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
||||||
// Return the constant value.
|
|
||||||
__ LoadObject(x0, value);
|
|
||||||
__ Ret();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupIterator* it, Register holder_reg) {
|
LookupIterator* it, Register holder_reg) {
|
||||||
DCHECK(!AreAliased(receiver(), this->name(), scratch1(), scratch2(),
|
DCHECK(!AreAliased(receiver(), this->name(), scratch1(), scratch2(),
|
||||||
|
@ -121,24 +121,6 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
|||||||
GenerateRuntimeGetProperty(masm);
|
GenerateRuntimeGetProperty(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
ASM_LOCATION("LoadIC::GenerateMiss");
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(x4, x5, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_load_miss(), 1, x4, x5);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ Push(LoadWithVectorDescriptor::ReceiverRegister(),
|
|
||||||
LoadWithVectorDescriptor::NameRegister(),
|
|
||||||
LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister());
|
|
||||||
__ TailCallRuntime(Runtime::kLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||||
// The return address is in lr.
|
// The return address is in lr.
|
||||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
||||||
@ -147,32 +129,6 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kGetProperty);
|
__ TailCallRuntime(Runtime::kGetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(x10, x11, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_keyed_load_miss(), 1, x10, x11);
|
|
||||||
|
|
||||||
__ Push(LoadWithVectorDescriptor::ReceiverRegister(),
|
|
||||||
LoadWithVectorDescriptor::NameRegister(),
|
|
||||||
LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister());
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
|
||||||
|
|
||||||
// Do tail-call to runtime routine.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedGetProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
||||||
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
||||||
StoreWithVectorDescriptor::SlotRegister(),
|
StoreWithVectorDescriptor::SlotRegister(),
|
||||||
|
@ -24,60 +24,6 @@ Handle<Code> PropertyHandlerCompiler::Find(Handle<Name> name,
|
|||||||
return handle(code);
|
return handle(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent(
|
|
||||||
Handle<Name> name, Handle<Map> receiver_map) {
|
|
||||||
Isolate* isolate = name->GetIsolate();
|
|
||||||
if (receiver_map->prototype()->IsNull(isolate)) {
|
|
||||||
// TODO(jkummerow/verwaest): If there is no prototype and the property
|
|
||||||
// is nonexistent, introduce a builtin to handle this (fast properties
|
|
||||||
// -> return undefined, dictionary properties -> do negative lookup).
|
|
||||||
return Handle<Code>();
|
|
||||||
}
|
|
||||||
CacheHolderFlag flag;
|
|
||||||
Handle<Map> stub_holder_map =
|
|
||||||
IC::GetHandlerCacheHolder(receiver_map, false, isolate, &flag);
|
|
||||||
|
|
||||||
// If no dictionary mode objects are present in the prototype chain, the load
|
|
||||||
// nonexistent IC stub can be shared for all names for a given map and we use
|
|
||||||
// the empty string for the map cache in that case. If there are dictionary
|
|
||||||
// mode objects involved, we need to do negative lookups in the stub and
|
|
||||||
// therefore the stub will be specific to the name.
|
|
||||||
Handle<Name> cache_name =
|
|
||||||
receiver_map->is_dictionary_map()
|
|
||||||
? name
|
|
||||||
: Handle<Name>::cast(isolate->factory()->nonexistent_symbol());
|
|
||||||
Handle<Map> current_map = stub_holder_map;
|
|
||||||
Handle<JSObject> last(JSObject::cast(receiver_map->prototype()));
|
|
||||||
while (true) {
|
|
||||||
if (current_map->is_dictionary_map()) cache_name = name;
|
|
||||||
if (current_map->prototype()->IsNull(isolate)) break;
|
|
||||||
if (name->IsPrivate()) {
|
|
||||||
// TODO(verwaest): Use nonexistent_private_symbol.
|
|
||||||
cache_name = name;
|
|
||||||
if (!current_map->has_hidden_prototype()) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
last = handle(JSObject::cast(current_map->prototype()));
|
|
||||||
current_map = handle(last->map());
|
|
||||||
}
|
|
||||||
// Compile the stub that is either shared for all names or
|
|
||||||
// name specific if there are global objects involved.
|
|
||||||
Handle<Code> handler = PropertyHandlerCompiler::Find(
|
|
||||||
cache_name, stub_holder_map, Code::LOAD_IC, flag);
|
|
||||||
if (!handler.is_null()) {
|
|
||||||
TRACE_HANDLER_STATS(isolate, LoadIC_HandlerCacheHit_NonExistent);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRACE_HANDLER_STATS(isolate, LoadIC_LoadNonexistent);
|
|
||||||
NamedLoadHandlerCompiler compiler(isolate, receiver_map, last, flag);
|
|
||||||
handler = compiler.CompileLoadNonexistent(cache_name);
|
|
||||||
Map::UpdateCodeCache(stub_holder_map, cache_name, handler);
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind,
|
Handle<Code> PropertyHandlerCompiler::GetCode(Code::Kind kind,
|
||||||
Handle<Name> name) {
|
Handle<Name> name) {
|
||||||
Code::Flags flags = Code::ComputeHandlerFlags(kind, cache_holder());
|
Code::Flags flags = Code::ComputeHandlerFlags(kind, cache_holder());
|
||||||
@ -149,66 +95,6 @@ Register PropertyHandlerCompiler::Frontend(Handle<Name> name) {
|
|||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::NonexistentFrontendHeader(Handle<Name> name,
|
|
||||||
Label* miss,
|
|
||||||
Register scratch1,
|
|
||||||
Register scratch2) {
|
|
||||||
Register holder_reg;
|
|
||||||
Handle<Map> last_map;
|
|
||||||
if (holder().is_null()) {
|
|
||||||
holder_reg = receiver();
|
|
||||||
last_map = map();
|
|
||||||
// If |type| has null as its prototype, |holder()| is
|
|
||||||
// Handle<JSObject>::null().
|
|
||||||
DCHECK(last_map->prototype()->IsNull(isolate()));
|
|
||||||
} else {
|
|
||||||
last_map = handle(holder()->map());
|
|
||||||
// This condition matches the branches below.
|
|
||||||
bool need_holder =
|
|
||||||
last_map->is_dictionary_map() && !last_map->IsJSGlobalObjectMap();
|
|
||||||
holder_reg =
|
|
||||||
FrontendHeader(receiver(), name, miss,
|
|
||||||
need_holder ? RETURN_HOLDER : DONT_RETURN_ANYTHING);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last_map->is_dictionary_map()) {
|
|
||||||
if (last_map->IsJSGlobalObjectMap()) {
|
|
||||||
Handle<JSGlobalObject> global =
|
|
||||||
holder().is_null()
|
|
||||||
? Handle<JSGlobalObject>::cast(isolate()->global_object())
|
|
||||||
: Handle<JSGlobalObject>::cast(holder());
|
|
||||||
GenerateCheckPropertyCell(masm(), global, name, scratch1, miss);
|
|
||||||
} else {
|
|
||||||
if (!name->IsUniqueName()) {
|
|
||||||
DCHECK(name->IsString());
|
|
||||||
name = factory()->InternalizeString(Handle<String>::cast(name));
|
|
||||||
}
|
|
||||||
DCHECK(holder().is_null() ||
|
|
||||||
holder()->property_dictionary()->FindEntry(name) ==
|
|
||||||
NameDictionary::kNotFound);
|
|
||||||
GenerateDictionaryNegativeLookup(masm(), miss, holder_reg, name, scratch1,
|
|
||||||
scratch2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent(
|
|
||||||
Handle<Name> name) {
|
|
||||||
Label miss;
|
|
||||||
if (IC::ShouldPushPopSlotAndVector(kind())) {
|
|
||||||
DCHECK(kind() == Code::LOAD_IC);
|
|
||||||
PushVectorAndSlot();
|
|
||||||
}
|
|
||||||
NonexistentFrontendHeader(name, &miss, scratch2(), scratch3());
|
|
||||||
if (IC::ShouldPushPopSlotAndVector(kind())) {
|
|
||||||
DiscardVectorAndSlot();
|
|
||||||
}
|
|
||||||
GenerateLoadConstant(isolate()->factory()->undefined_value());
|
|
||||||
FrontendFooter(name, &miss);
|
|
||||||
return GetCode(kind(), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
|
Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback(
|
||||||
Handle<Name> name, Handle<AccessorInfo> callback, Handle<Code> slow_stub) {
|
Handle<Name> name, Handle<AccessorInfo> callback, Handle<Code> slow_stub) {
|
||||||
if (V8_UNLIKELY(FLAG_runtime_stats)) {
|
if (V8_UNLIKELY(FLAG_runtime_stats)) {
|
||||||
@ -422,11 +308,6 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadViaGetter(
|
|||||||
return GetCode(kind(), name);
|
return GetCode(kind(), name);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NamedStoreHandlerCompiler::RequiresFieldTypeChecks(
|
|
||||||
FieldType* field_type) const {
|
|
||||||
return field_type->IsClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
|
Handle<Code> NamedStoreHandlerCompiler::CompileStoreViaSetter(
|
||||||
Handle<JSObject> object, Handle<Name> name, int accessor_index,
|
Handle<JSObject> object, Handle<Name> name, int accessor_index,
|
||||||
int expected_arguments) {
|
int expected_arguments) {
|
||||||
|
@ -40,8 +40,6 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
|
|||||||
// Frontend loads from receiver(), returns holder register which may be
|
// Frontend loads from receiver(), returns holder register which may be
|
||||||
// different.
|
// different.
|
||||||
Register Frontend(Handle<Name> name);
|
Register Frontend(Handle<Name> name);
|
||||||
void NonexistentFrontendHeader(Handle<Name> name, Label* miss,
|
|
||||||
Register scratch1, Register scratch2);
|
|
||||||
|
|
||||||
// When FLAG_vector_ics is true, handlers that have the possibility of missing
|
// When FLAG_vector_ics is true, handlers that have the possibility of missing
|
||||||
// will need to save and pass these to miss handlers.
|
// will need to save and pass these to miss handlers.
|
||||||
@ -52,9 +50,6 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler {
|
|||||||
|
|
||||||
void DiscardVectorAndSlot();
|
void DiscardVectorAndSlot();
|
||||||
|
|
||||||
void PushReturnAddress(Register tmp);
|
|
||||||
void PopReturnAddress(Register tmp);
|
|
||||||
|
|
||||||
// TODO(verwaest): Make non-static.
|
// TODO(verwaest): Make non-static.
|
||||||
static void GenerateApiAccessorCall(MacroAssembler* masm,
|
static void GenerateApiAccessorCall(MacroAssembler* masm,
|
||||||
const CallOptimization& optimization,
|
const CallOptimization& optimization,
|
||||||
@ -153,10 +148,6 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
|
|||||||
Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
|
Handle<Code> CompileLoadGlobal(Handle<PropertyCell> cell, Handle<Name> name,
|
||||||
bool is_configurable);
|
bool is_configurable);
|
||||||
|
|
||||||
// Static interface
|
|
||||||
static Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
|
|
||||||
Handle<Map> map);
|
|
||||||
|
|
||||||
static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
|
static void GenerateLoadViaGetter(MacroAssembler* masm, Handle<Map> map,
|
||||||
Register receiver, Register holder,
|
Register receiver, Register holder,
|
||||||
int accessor_index, int expected_arguments,
|
int accessor_index, int expected_arguments,
|
||||||
@ -189,11 +180,7 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
|
|||||||
virtual void FrontendFooter(Handle<Name> name, Label* miss);
|
virtual void FrontendFooter(Handle<Name> name, Label* miss);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Handle<Code> CompileLoadNonexistent(Handle<Name> name);
|
|
||||||
void GenerateLoadConstant(Handle<Object> value);
|
|
||||||
void GenerateLoadCallback(Register reg, Handle<AccessorInfo> callback);
|
void GenerateLoadCallback(Register reg, Handle<AccessorInfo> callback);
|
||||||
void GenerateLoadCallback(const CallOptimization& call_optimization,
|
|
||||||
Handle<Map> receiver_map);
|
|
||||||
|
|
||||||
// Helper emits no code if vector-ics are disabled.
|
// Helper emits no code if vector-ics are disabled.
|
||||||
void InterceptorVectorSlotPush(Register holder_reg);
|
void InterceptorVectorSlotPush(Register holder_reg);
|
||||||
@ -205,17 +192,6 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler {
|
|||||||
Register holder_reg);
|
Register holder_reg);
|
||||||
void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
|
void GenerateLoadPostInterceptor(LookupIterator* it, Register reg);
|
||||||
|
|
||||||
// Generates prototype loading code that uses the objects from the
|
|
||||||
// context we were in when this function was called. If the context
|
|
||||||
// has changed, a jump to miss is performed. This ties the generated
|
|
||||||
// code to a particular context and so must not be used in cases
|
|
||||||
// where the generated code is not allowed to have references to
|
|
||||||
// objects from a context.
|
|
||||||
static void GenerateDirectLoadGlobalFunctionPrototype(MacroAssembler* masm,
|
|
||||||
int index,
|
|
||||||
Register prototype,
|
|
||||||
Label* miss);
|
|
||||||
|
|
||||||
Register scratch3() { return registers_[4]; }
|
Register scratch3() { return registers_[4]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -268,18 +244,6 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler {
|
|||||||
void GenerateRestoreName(Label* label, Handle<Name> name);
|
void GenerateRestoreName(Label* label, Handle<Name> name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GenerateRestoreName(Handle<Name> name);
|
|
||||||
void GenerateRestoreMap(Handle<Map> transition, Register map_reg,
|
|
||||||
Register scratch, Label* miss);
|
|
||||||
|
|
||||||
void GenerateConstantCheck(Register map_reg, int descriptor,
|
|
||||||
Register value_reg, Register scratch,
|
|
||||||
Label* miss_label);
|
|
||||||
|
|
||||||
bool RequiresFieldTypeChecks(FieldType* field_type) const;
|
|
||||||
void GenerateFieldTypeChecks(FieldType* field_type, Register value_reg,
|
|
||||||
Label* miss_label);
|
|
||||||
|
|
||||||
static Register value();
|
static Register value();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,16 +83,6 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
|
|||||||
__ add(esp, Immediate(2 * kPointerSize));
|
__ add(esp, Immediate(2 * kPointerSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
|
|
||||||
MacroAssembler* masm = this->masm();
|
|
||||||
__ push(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
|
|
||||||
MacroAssembler* masm = this->masm();
|
|
||||||
__ pop(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||||
MacroAssembler* masm, Label* miss_label, Register receiver,
|
MacroAssembler* masm, Label* miss_label, Register receiver,
|
||||||
Handle<Name> name, Register scratch0, Register scratch1) {
|
Handle<Name> name, Register scratch0, Register scratch1) {
|
||||||
@ -132,18 +122,6 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
|||||||
__ DecrementCounter(counters->negative_lookups_miss(), 1);
|
__ DecrementCounter(counters->negative_lookups_miss(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
|
||||||
MacroAssembler* masm, int index, Register result, Label* miss) {
|
|
||||||
__ LoadGlobalFunction(index, result);
|
|
||||||
// Load its initial map. The global functions all have initial maps.
|
|
||||||
__ mov(result,
|
|
||||||
FieldOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
// Load the prototype from the initial map.
|
|
||||||
__ mov(result, FieldOperand(result, Map::kPrototypeOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||||
MacroAssembler* masm, Register receiver, Register scratch1,
|
MacroAssembler* masm, Register receiver, Register scratch1,
|
||||||
Register scratch2, Label* miss_label) {
|
Register scratch2, Label* miss_label) {
|
||||||
@ -359,58 +337,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
|
|
||||||
__ mov(this->name(), Immediate(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
|
|
||||||
Register map_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss) {
|
|
||||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
__ LoadWeakValue(map_reg, cell, miss);
|
|
||||||
if (transition->CanBeDeprecated()) {
|
|
||||||
__ mov(scratch, FieldOperand(map_reg, Map::kBitField3Offset));
|
|
||||||
__ and_(scratch, Immediate(Map::Deprecated::kMask));
|
|
||||||
__ j(not_zero, miss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
|
|
||||||
int descriptor,
|
|
||||||
Register value_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss_label) {
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
DCHECK(!map_reg.is(value_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ LoadInstanceDescriptors(map_reg, scratch);
|
|
||||||
__ mov(scratch,
|
|
||||||
FieldOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
|
|
||||||
__ cmp(value_reg, scratch);
|
|
||||||
__ j(not_equal, miss_label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
|
|
||||||
Register value_reg,
|
|
||||||
Label* miss_label) {
|
|
||||||
Register map_reg = scratch1();
|
|
||||||
Register scratch = scratch2();
|
|
||||||
DCHECK(!value_reg.is(map_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
|
||||||
if (field_type->IsClass()) {
|
|
||||||
__ mov(map_reg, FieldOperand(value_reg, HeapObject::kMapOffset));
|
|
||||||
__ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()),
|
|
||||||
scratch);
|
|
||||||
__ j(not_equal, miss_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||||
Label* miss, bool compare_native_contexts_only) {
|
Label* miss, bool compare_native_contexts_only) {
|
||||||
@ -540,14 +466,6 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
||||||
// Return the constant value.
|
|
||||||
__ LoadObject(eax, value);
|
|
||||||
__ ret(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupIterator* it, Register holder_reg) {
|
LookupIterator* it, Register holder_reg) {
|
||||||
DCHECK(holder()->HasNamedInterceptor());
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
|
@ -138,34 +138,6 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
|||||||
GenerateRuntimeGetProperty(masm);
|
GenerateRuntimeGetProperty(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
|
|
||||||
Register slot = LoadDescriptor::SlotRegister();
|
|
||||||
Register vector = LoadWithVectorDescriptor::VectorRegister();
|
|
||||||
DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) &&
|
|
||||||
!edi.is(vector));
|
|
||||||
|
|
||||||
__ pop(edi);
|
|
||||||
__ push(receiver);
|
|
||||||
__ push(name);
|
|
||||||
__ push(slot);
|
|
||||||
__ push(vector);
|
|
||||||
__ push(edi);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// Return address is on the stack.
|
|
||||||
__ IncrementCounter(masm->isolate()->counters()->ic_load_miss(), 1);
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||||
// Return address is on the stack.
|
// Return address is on the stack.
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||||
@ -181,32 +153,6 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kGetProperty);
|
__ TailCallRuntime(Runtime::kGetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// Return address is on the stack.
|
|
||||||
__ IncrementCounter(masm->isolate()->counters()->ic_keyed_load_miss(), 1);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|
||||||
// Return address is on the stack.
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
DCHECK(!ebx.is(receiver) && !ebx.is(name));
|
|
||||||
|
|
||||||
__ pop(ebx);
|
|
||||||
__ push(receiver);
|
|
||||||
__ push(name);
|
|
||||||
__ push(ebx);
|
|
||||||
|
|
||||||
// Do tail-call to runtime routine.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedGetProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
||||||
Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
|
Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
|
||||||
Register name = StoreWithVectorDescriptor::NameRegister();
|
Register name = StoreWithVectorDescriptor::NameRegister();
|
||||||
|
@ -286,8 +286,6 @@ class LoadIC : public IC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Code generator routines.
|
// Code generator routines.
|
||||||
|
|
||||||
static void GenerateMiss(MacroAssembler* masm);
|
|
||||||
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
|
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
|
||||||
static void GenerateNormal(MacroAssembler* masm);
|
static void GenerateNormal(MacroAssembler* masm);
|
||||||
|
|
||||||
@ -354,10 +352,6 @@ class KeyedLoadIC : public LoadIC {
|
|||||||
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
|
MUST_USE_RESULT MaybeHandle<Object> Load(Handle<Object> object,
|
||||||
Handle<Object> key);
|
Handle<Object> key);
|
||||||
|
|
||||||
// Code generator routines.
|
|
||||||
static void GenerateMiss(MacroAssembler* masm);
|
|
||||||
static void GenerateRuntimeGetProperty(MacroAssembler* masm);
|
|
||||||
|
|
||||||
static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus);
|
static void Clear(Isolate* isolate, Code* host, KeyedLoadICNexus* nexus);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -129,14 +129,6 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
|
|||||||
__ Addu(sp, sp, Operand(2 * kPointerSize));
|
__ Addu(sp, sp, Operand(2 * kPointerSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in ra register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in ra register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||||
MacroAssembler* masm, Label* miss_label, Register receiver,
|
MacroAssembler* masm, Label* miss_label, Register receiver,
|
||||||
Handle<Name> name, Register scratch0, Register scratch1) {
|
Handle<Name> name, Register scratch0, Register scratch1) {
|
||||||
@ -181,18 +173,6 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
|||||||
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
|
||||||
MacroAssembler* masm, int index, Register result, Label* miss) {
|
|
||||||
__ LoadNativeContextSlot(index, result);
|
|
||||||
// Load its initial map. The global functions all have initial maps.
|
|
||||||
__ lw(result,
|
|
||||||
FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
// Load the prototype from the initial map.
|
|
||||||
__ lw(result, FieldMemOperand(result, Map::kPrototypeOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||||
MacroAssembler* masm, Register receiver, Register scratch1,
|
MacroAssembler* masm, Register receiver, Register scratch1,
|
||||||
Register scratch2, Label* miss_label) {
|
Register scratch2, Label* miss_label) {
|
||||||
@ -342,57 +322,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
|
|
||||||
__ li(this->name(), Operand(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
|
|
||||||
Register map_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss) {
|
|
||||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
__ LoadWeakValue(map_reg, cell, miss);
|
|
||||||
if (transition->CanBeDeprecated()) {
|
|
||||||
__ lw(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset));
|
|
||||||
__ And(at, scratch, Operand(Map::Deprecated::kMask));
|
|
||||||
__ Branch(miss, ne, at, Operand(zero_reg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
|
|
||||||
int descriptor,
|
|
||||||
Register value_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss_label) {
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
DCHECK(!map_reg.is(value_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ LoadInstanceDescriptors(map_reg, scratch);
|
|
||||||
__ lw(scratch,
|
|
||||||
FieldMemOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
|
|
||||||
__ Branch(miss_label, ne, value_reg, Operand(scratch));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
|
|
||||||
Register value_reg,
|
|
||||||
Label* miss_label) {
|
|
||||||
Register map_reg = scratch1();
|
|
||||||
Register scratch = scratch2();
|
|
||||||
DCHECK(!value_reg.is(map_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
|
||||||
if (field_type->IsClass()) {
|
|
||||||
__ lw(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
|
||||||
// Compare map directly within the Branch() functions.
|
|
||||||
__ GetWeakValue(scratch, Map::WeakCellForMap(field_type->AsClass()));
|
|
||||||
__ Branch(miss_label, ne, map_reg, Operand(scratch));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||||
Label* miss, bool compare_native_contexts_only) {
|
Label* miss, bool compare_native_contexts_only) {
|
||||||
@ -520,14 +449,6 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
||||||
// Return the constant value.
|
|
||||||
__ li(v0, value);
|
|
||||||
__ Ret();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupIterator* it, Register holder_reg) {
|
LookupIterator* it, Register holder_reg) {
|
||||||
DCHECK(holder()->HasNamedInterceptor());
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
|
@ -141,31 +141,6 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
|||||||
// A register that isn't one of the parameters to the load ic.
|
// A register that isn't one of the parameters to the load ic.
|
||||||
static const Register LoadIC_TempRegister() { return a3; }
|
static const Register LoadIC_TempRegister() { return a3; }
|
||||||
|
|
||||||
|
|
||||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
Register slot = LoadDescriptor::SlotRegister();
|
|
||||||
Register vector = LoadWithVectorDescriptor::VectorRegister();
|
|
||||||
|
|
||||||
__ Push(receiver, name, slot, vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in ra.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(t0, t1, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_load_miss(), 1, t0, t1);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||||
// The return address is in ra.
|
// The return address is in ra.
|
||||||
|
|
||||||
@ -176,30 +151,6 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kGetProperty);
|
__ TailCallRuntime(Runtime::kGetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in ra.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(t0, t1, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_keyed_load_miss(), 1, t0, t1);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|
||||||
// The return address is in ra.
|
|
||||||
|
|
||||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
|
||||||
|
|
||||||
// Do tail-call to runtime routine.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedGetProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
||||||
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
||||||
StoreWithVectorDescriptor::SlotRegister(),
|
StoreWithVectorDescriptor::SlotRegister(),
|
||||||
|
@ -129,14 +129,6 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
|
|||||||
__ Daddu(sp, sp, Operand(2 * kPointerSize));
|
__ Daddu(sp, sp, Operand(2 * kPointerSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in ra register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in ra register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||||
MacroAssembler* masm, Label* miss_label, Register receiver,
|
MacroAssembler* masm, Label* miss_label, Register receiver,
|
||||||
Handle<Name> name, Register scratch0, Register scratch1) {
|
Handle<Name> name, Register scratch0, Register scratch1) {
|
||||||
@ -181,18 +173,6 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
|||||||
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
|
||||||
MacroAssembler* masm, int index, Register result, Label* miss) {
|
|
||||||
__ LoadNativeContextSlot(index, result);
|
|
||||||
// Load its initial map. The global functions all have initial maps.
|
|
||||||
__ ld(result,
|
|
||||||
FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
// Load the prototype from the initial map.
|
|
||||||
__ ld(result, FieldMemOperand(result, Map::kPrototypeOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||||
MacroAssembler* masm, Register receiver, Register scratch1,
|
MacroAssembler* masm, Register receiver, Register scratch1,
|
||||||
Register scratch2, Label* miss_label) {
|
Register scratch2, Label* miss_label) {
|
||||||
@ -342,57 +322,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
|
|
||||||
__ li(this->name(), Operand(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
|
|
||||||
Register map_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss) {
|
|
||||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
__ LoadWeakValue(map_reg, cell, miss);
|
|
||||||
if (transition->CanBeDeprecated()) {
|
|
||||||
__ lwu(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset));
|
|
||||||
__ And(at, scratch, Operand(Map::Deprecated::kMask));
|
|
||||||
__ Branch(miss, ne, at, Operand(zero_reg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
|
|
||||||
int descriptor,
|
|
||||||
Register value_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss_label) {
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
DCHECK(!map_reg.is(value_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ LoadInstanceDescriptors(map_reg, scratch);
|
|
||||||
__ ld(scratch,
|
|
||||||
FieldMemOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
|
|
||||||
__ Branch(miss_label, ne, value_reg, Operand(scratch));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
|
|
||||||
Register value_reg,
|
|
||||||
Label* miss_label) {
|
|
||||||
Register map_reg = scratch1();
|
|
||||||
Register scratch = scratch2();
|
|
||||||
DCHECK(!value_reg.is(map_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
|
||||||
if (field_type->IsClass()) {
|
|
||||||
__ ld(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
|
||||||
// Compare map directly within the Branch() functions.
|
|
||||||
__ GetWeakValue(scratch, Map::WeakCellForMap(field_type->AsClass()));
|
|
||||||
__ Branch(miss_label, ne, map_reg, Operand(scratch));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||||
Label* miss, bool compare_native_contexts_only) {
|
Label* miss, bool compare_native_contexts_only) {
|
||||||
@ -520,14 +449,6 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
||||||
// Return the constant value.
|
|
||||||
__ li(v0, value);
|
|
||||||
__ Ret();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupIterator* it, Register holder_reg) {
|
LookupIterator* it, Register holder_reg) {
|
||||||
DCHECK(holder()->HasNamedInterceptor());
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
|
@ -139,31 +139,6 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
|||||||
// A register that isn't one of the parameters to the load ic.
|
// A register that isn't one of the parameters to the load ic.
|
||||||
static const Register LoadIC_TempRegister() { return a3; }
|
static const Register LoadIC_TempRegister() { return a3; }
|
||||||
|
|
||||||
|
|
||||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
Register slot = LoadDescriptor::SlotRegister();
|
|
||||||
Register vector = LoadWithVectorDescriptor::VectorRegister();
|
|
||||||
|
|
||||||
__ Push(receiver, name, slot, vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is on the stack.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(a4, a5, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_load_miss(), 1, a4, a5);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||||
// The return address is in ra.
|
// The return address is in ra.
|
||||||
|
|
||||||
@ -174,30 +149,6 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kGetProperty);
|
__ TailCallRuntime(Runtime::kGetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in ra.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(a4, a5, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_keyed_load_miss(), 1, a4, a5);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|
||||||
// The return address is in ra.
|
|
||||||
|
|
||||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
|
||||||
|
|
||||||
// Do tail-call to runtime routine.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedGetProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
||||||
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
||||||
StoreWithVectorDescriptor::SlotRegister(),
|
StoreWithVectorDescriptor::SlotRegister(),
|
||||||
|
@ -130,14 +130,6 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
|
|||||||
__ addi(sp, sp, Operand(2 * kPointerSize));
|
__ addi(sp, sp, Operand(2 * kPointerSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in lr register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in lr register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||||
MacroAssembler* masm, Label* miss_label, Register receiver,
|
MacroAssembler* masm, Label* miss_label, Register receiver,
|
||||||
Handle<Name> name, Register scratch0, Register scratch1) {
|
Handle<Name> name, Register scratch0, Register scratch1) {
|
||||||
@ -184,18 +176,6 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
|||||||
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
|
||||||
MacroAssembler* masm, int index, Register result, Label* miss) {
|
|
||||||
__ LoadNativeContextSlot(index, result);
|
|
||||||
// Load its initial map. The global functions all have initial maps.
|
|
||||||
__ LoadP(result,
|
|
||||||
FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
// Load the prototype from the initial map.
|
|
||||||
__ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||||
MacroAssembler* masm, Register receiver, Register scratch1,
|
MacroAssembler* masm, Register receiver, Register scratch1,
|
||||||
Register scratch2, Label* miss_label) {
|
Register scratch2, Label* miss_label) {
|
||||||
@ -350,58 +330,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
|
|
||||||
__ mov(this->name(), Operand(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
|
|
||||||
Register map_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss) {
|
|
||||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
__ LoadWeakValue(map_reg, cell, miss);
|
|
||||||
if (transition->CanBeDeprecated()) {
|
|
||||||
__ lwz(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset));
|
|
||||||
__ DecodeField<Map::Deprecated>(r0, scratch, SetRC);
|
|
||||||
__ bne(miss, cr0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
|
|
||||||
int descriptor,
|
|
||||||
Register value_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss_label) {
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
DCHECK(!map_reg.is(value_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ LoadInstanceDescriptors(map_reg, scratch);
|
|
||||||
__ LoadP(scratch, FieldMemOperand(
|
|
||||||
scratch, DescriptorArray::GetValueOffset(descriptor)));
|
|
||||||
__ cmp(value_reg, scratch);
|
|
||||||
__ bne(miss_label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
|
|
||||||
Register value_reg,
|
|
||||||
Label* miss_label) {
|
|
||||||
Register map_reg = scratch1();
|
|
||||||
Register scratch = scratch2();
|
|
||||||
DCHECK(!value_reg.is(map_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
|
||||||
if (field_type->IsClass()) {
|
|
||||||
__ LoadP(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
|
||||||
__ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()),
|
|
||||||
scratch);
|
|
||||||
__ bne(miss_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||||
Label* miss, bool compare_native_contexts_only) {
|
Label* miss, bool compare_native_contexts_only) {
|
||||||
@ -538,14 +466,6 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
||||||
// Return the constant value.
|
|
||||||
__ Move(r3, value);
|
|
||||||
__ Ret();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupIterator* it, Register holder_reg) {
|
LookupIterator* it, Register holder_reg) {
|
||||||
DCHECK(holder()->HasNamedInterceptor());
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
|
@ -141,31 +141,6 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
|||||||
// A register that isn't one of the parameters to the load ic.
|
// A register that isn't one of the parameters to the load ic.
|
||||||
static const Register LoadIC_TempRegister() { return r6; }
|
static const Register LoadIC_TempRegister() { return r6; }
|
||||||
|
|
||||||
|
|
||||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
Register slot = LoadDescriptor::SlotRegister();
|
|
||||||
Register vector = LoadWithVectorDescriptor::VectorRegister();
|
|
||||||
|
|
||||||
__ Push(receiver, name, slot, vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(r7, r8, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_load_miss(), 1, r7, r8);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||||
// The return address is in lr.
|
// The return address is in lr.
|
||||||
|
|
||||||
@ -176,30 +151,6 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kGetProperty);
|
__ TailCallRuntime(Runtime::kGetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(r7, r8, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_keyed_load_miss(), 1, r7, r8);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
|
|
||||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
|
||||||
|
|
||||||
// Do tail-call to runtime routine.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedGetProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
||||||
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
||||||
StoreWithVectorDescriptor::SlotRegister(),
|
StoreWithVectorDescriptor::SlotRegister(),
|
||||||
|
@ -125,14 +125,6 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
|
|||||||
__ la(sp, MemOperand(sp, 2 * kPointerSize));
|
__ la(sp, MemOperand(sp, 2 * kPointerSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in lr register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
|
|
||||||
// No-op. Return address is in lr register.
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||||
MacroAssembler* masm, Label* miss_label, Register receiver,
|
MacroAssembler* masm, Label* miss_label, Register receiver,
|
||||||
Handle<Name> name, Register scratch0, Register scratch1) {
|
Handle<Name> name, Register scratch0, Register scratch1) {
|
||||||
@ -177,16 +169,6 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
|||||||
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
__ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
|
||||||
MacroAssembler* masm, int index, Register result, Label* miss) {
|
|
||||||
__ LoadNativeContextSlot(index, result);
|
|
||||||
// Load its initial map. The global functions all have initial maps.
|
|
||||||
__ LoadP(result,
|
|
||||||
FieldMemOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
// Load the prototype from the initial map.
|
|
||||||
__ LoadP(result, FieldMemOperand(result, Map::kPrototypeOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||||
MacroAssembler* masm, Register receiver, Register scratch1,
|
MacroAssembler* masm, Register receiver, Register scratch1,
|
||||||
Register scratch2, Label* miss_label) {
|
Register scratch2, Label* miss_label) {
|
||||||
@ -335,54 +317,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
|
|
||||||
__ mov(this->name(), Operand(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
|
|
||||||
Register map_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss) {
|
|
||||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
__ LoadWeakValue(map_reg, cell, miss);
|
|
||||||
if (transition->CanBeDeprecated()) {
|
|
||||||
__ LoadlW(scratch, FieldMemOperand(map_reg, Map::kBitField3Offset));
|
|
||||||
__ DecodeField<Map::Deprecated>(r0, scratch);
|
|
||||||
__ bne(miss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
|
|
||||||
int descriptor,
|
|
||||||
Register value_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss_label) {
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
DCHECK(!map_reg.is(value_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ LoadInstanceDescriptors(map_reg, scratch);
|
|
||||||
__ CmpP(value_reg, FieldMemOperand(
|
|
||||||
scratch, DescriptorArray::GetValueOffset(descriptor)));
|
|
||||||
__ bne(miss_label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
|
|
||||||
Register value_reg,
|
|
||||||
Label* miss_label) {
|
|
||||||
Register map_reg = scratch1();
|
|
||||||
Register scratch = scratch2();
|
|
||||||
DCHECK(!value_reg.is(map_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
|
||||||
if (field_type->IsClass()) {
|
|
||||||
__ LoadP(map_reg, FieldMemOperand(value_reg, HeapObject::kMapOffset));
|
|
||||||
__ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()),
|
|
||||||
scratch);
|
|
||||||
__ bne(miss_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||||
Label* miss, bool compare_native_contexts_only) {
|
Label* miss, bool compare_native_contexts_only) {
|
||||||
@ -512,12 +446,6 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
||||||
// Return the constant value.
|
|
||||||
__ Move(r2, value);
|
|
||||||
__ Ret();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupIterator* it, Register holder_reg) {
|
LookupIterator* it, Register holder_reg) {
|
||||||
DCHECK(holder()->HasNamedInterceptor());
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
|
@ -138,29 +138,6 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
|||||||
// A register that isn't one of the parameters to the load ic.
|
// A register that isn't one of the parameters to the load ic.
|
||||||
static const Register LoadIC_TempRegister() { return r5; }
|
static const Register LoadIC_TempRegister() { return r5; }
|
||||||
|
|
||||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
Register slot = LoadDescriptor::SlotRegister();
|
|
||||||
Register vector = LoadWithVectorDescriptor::VectorRegister();
|
|
||||||
|
|
||||||
__ Push(receiver, name, slot, vector);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(r6, r7, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_load_miss(), 1, r6, r7);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||||
// The return address is in lr.
|
// The return address is in lr.
|
||||||
|
|
||||||
@ -171,29 +148,6 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kGetProperty);
|
__ TailCallRuntime(Runtime::kGetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
Isolate* isolate = masm->isolate();
|
|
||||||
|
|
||||||
DCHECK(!AreAliased(r6, r7, LoadWithVectorDescriptor::SlotRegister(),
|
|
||||||
LoadWithVectorDescriptor::VectorRegister()));
|
|
||||||
__ IncrementCounter(isolate->counters()->ic_keyed_load_miss(), 1, r6, r7);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|
||||||
// The return address is in lr.
|
|
||||||
|
|
||||||
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
|
|
||||||
|
|
||||||
// Do tail-call to runtime routine.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedGetProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
||||||
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
__ Push(StoreWithVectorDescriptor::ValueRegister(),
|
||||||
StoreWithVectorDescriptor::SlotRegister(),
|
StoreWithVectorDescriptor::SlotRegister(),
|
||||||
|
@ -44,16 +44,6 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
|
|||||||
__ addp(rsp, Immediate(2 * kPointerSize));
|
__ addp(rsp, Immediate(2 * kPointerSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
|
|
||||||
MacroAssembler* masm = this->masm();
|
|
||||||
__ Push(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
|
|
||||||
MacroAssembler* masm = this->masm();
|
|
||||||
__ Pop(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||||
MacroAssembler* masm, Label* miss_label, Register receiver,
|
MacroAssembler* masm, Label* miss_label, Register receiver,
|
||||||
Handle<Name> name, Register scratch0, Register scratch1) {
|
Handle<Name> name, Register scratch0, Register scratch1) {
|
||||||
@ -93,18 +83,6 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
|||||||
__ DecrementCounter(counters->negative_lookups_miss(), 1);
|
__ DecrementCounter(counters->negative_lookups_miss(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
|
||||||
MacroAssembler* masm, int index, Register result, Label* miss) {
|
|
||||||
__ LoadNativeContextSlot(index, result);
|
|
||||||
// Load its initial map. The global functions all have initial maps.
|
|
||||||
__ movp(result,
|
|
||||||
FieldOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
// Load the prototype from the initial map.
|
|
||||||
__ movp(result, FieldOperand(result, Map::kPrototypeOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||||
MacroAssembler* masm, Register receiver, Register result, Register scratch,
|
MacroAssembler* masm, Register receiver, Register result, Register scratch,
|
||||||
Label* miss_label) {
|
Label* miss_label) {
|
||||||
@ -348,59 +326,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
|
|
||||||
__ Move(this->name(), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
|
|
||||||
Register map_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss) {
|
|
||||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
__ LoadWeakValue(map_reg, cell, miss);
|
|
||||||
if (transition->CanBeDeprecated()) {
|
|
||||||
__ movl(scratch, FieldOperand(map_reg, Map::kBitField3Offset));
|
|
||||||
__ andl(scratch, Immediate(Map::Deprecated::kMask));
|
|
||||||
__ j(not_zero, miss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
|
|
||||||
int descriptor,
|
|
||||||
Register value_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss_label) {
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
DCHECK(!map_reg.is(value_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ LoadInstanceDescriptors(map_reg, scratch);
|
|
||||||
__ movp(scratch,
|
|
||||||
FieldOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
|
|
||||||
__ cmpp(value_reg, scratch);
|
|
||||||
__ j(not_equal, miss_label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
|
|
||||||
Register value_reg,
|
|
||||||
Label* miss_label) {
|
|
||||||
Register map_reg = scratch1();
|
|
||||||
Register scratch = scratch2();
|
|
||||||
DCHECK(!value_reg.is(map_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
|
||||||
if (field_type->IsClass()) {
|
|
||||||
Label do_store;
|
|
||||||
__ movp(map_reg, FieldOperand(value_reg, HeapObject::kMapOffset));
|
|
||||||
__ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()),
|
|
||||||
scratch);
|
|
||||||
__ j(not_equal, miss_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||||
Label* miss, bool compare_native_contexts_only) {
|
Label* miss, bool compare_native_contexts_only) {
|
||||||
@ -533,13 +458,6 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
||||||
// Return the constant value.
|
|
||||||
__ Move(rax, value);
|
|
||||||
__ ret(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupIterator* it, Register holder_reg) {
|
LookupIterator* it, Register holder_reg) {
|
||||||
DCHECK(holder()->HasNamedInterceptor());
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
|
@ -139,36 +139,6 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
|||||||
LoadIC::GenerateRuntimeGetProperty(masm);
|
LoadIC::GenerateRuntimeGetProperty(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
Register slot = LoadDescriptor::SlotRegister();
|
|
||||||
Register vector = LoadWithVectorDescriptor::VectorRegister();
|
|
||||||
DCHECK(!rdi.is(receiver) && !rdi.is(name) && !rdi.is(slot) &&
|
|
||||||
!rdi.is(vector));
|
|
||||||
|
|
||||||
__ PopReturnAddressTo(rdi);
|
|
||||||
__ Push(receiver);
|
|
||||||
__ Push(name);
|
|
||||||
__ Push(slot);
|
|
||||||
__ Push(vector);
|
|
||||||
__ PushReturnAddressFrom(rdi);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is on the stack.
|
|
||||||
|
|
||||||
Counters* counters = masm->isolate()->counters();
|
|
||||||
__ IncrementCounter(counters->ic_load_miss(), 1);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||||
// The return address is on the stack.
|
// The return address is on the stack.
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||||
@ -185,34 +155,6 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kGetProperty);
|
__ TailCallRuntime(Runtime::kGetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// The return address is on the stack.
|
|
||||||
Counters* counters = masm->isolate()->counters();
|
|
||||||
__ IncrementCounter(counters->ic_keyed_load_miss(), 1);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|
||||||
// The return address is on the stack.
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
|
|
||||||
DCHECK(!rbx.is(receiver) && !rbx.is(name));
|
|
||||||
|
|
||||||
__ PopReturnAddressTo(rbx);
|
|
||||||
__ Push(receiver);
|
|
||||||
__ Push(name);
|
|
||||||
__ PushReturnAddressFrom(rbx);
|
|
||||||
|
|
||||||
// Do tail-call to runtime routine.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedGetProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
||||||
Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
|
Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
|
||||||
Register name = StoreWithVectorDescriptor::NameRegister();
|
Register name = StoreWithVectorDescriptor::NameRegister();
|
||||||
|
@ -83,16 +83,6 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() {
|
|||||||
__ add(esp, Immediate(2 * kPointerSize));
|
__ add(esp, Immediate(2 * kPointerSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PushReturnAddress(Register tmp) {
|
|
||||||
MacroAssembler* masm = this->masm();
|
|
||||||
__ push(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::PopReturnAddress(Register tmp) {
|
|
||||||
MacroAssembler* masm = this->masm();
|
|
||||||
__ pop(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
||||||
MacroAssembler* masm, Label* miss_label, Register receiver,
|
MacroAssembler* masm, Label* miss_label, Register receiver,
|
||||||
Handle<Name> name, Register scratch0, Register scratch1) {
|
Handle<Name> name, Register scratch0, Register scratch1) {
|
||||||
@ -132,18 +122,6 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
|||||||
__ DecrementCounter(counters->negative_lookups_miss(), 1);
|
__ DecrementCounter(counters->negative_lookups_miss(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
|
||||||
MacroAssembler* masm, int index, Register result, Label* miss) {
|
|
||||||
__ LoadGlobalFunction(index, result);
|
|
||||||
// Load its initial map. The global functions all have initial maps.
|
|
||||||
__ mov(result,
|
|
||||||
FieldOperand(result, JSFunction::kPrototypeOrInitialMapOffset));
|
|
||||||
// Load the prototype from the initial map.
|
|
||||||
__ mov(result, FieldOperand(result, Map::kPrototypeOffset));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
||||||
MacroAssembler* masm, Register receiver, Register scratch1,
|
MacroAssembler* masm, Register receiver, Register scratch1,
|
||||||
Register scratch2, Label* miss_label) {
|
Register scratch2, Label* miss_label) {
|
||||||
@ -359,58 +337,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) {
|
|
||||||
__ mov(this->name(), Immediate(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition,
|
|
||||||
Register map_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss) {
|
|
||||||
Handle<WeakCell> cell = Map::WeakCellForMap(transition);
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
__ LoadWeakValue(map_reg, cell, miss);
|
|
||||||
if (transition->CanBeDeprecated()) {
|
|
||||||
__ mov(scratch, FieldOperand(map_reg, Map::kBitField3Offset));
|
|
||||||
__ and_(scratch, Immediate(Map::Deprecated::kMask));
|
|
||||||
__ j(not_zero, miss);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateConstantCheck(Register map_reg,
|
|
||||||
int descriptor,
|
|
||||||
Register value_reg,
|
|
||||||
Register scratch,
|
|
||||||
Label* miss_label) {
|
|
||||||
DCHECK(!map_reg.is(scratch));
|
|
||||||
DCHECK(!map_reg.is(value_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ LoadInstanceDescriptors(map_reg, scratch);
|
|
||||||
__ mov(scratch,
|
|
||||||
FieldOperand(scratch, DescriptorArray::GetValueOffset(descriptor)));
|
|
||||||
__ cmp(value_reg, scratch);
|
|
||||||
__ j(not_equal, miss_label);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(FieldType* field_type,
|
|
||||||
Register value_reg,
|
|
||||||
Label* miss_label) {
|
|
||||||
Register map_reg = scratch1();
|
|
||||||
Register scratch = scratch2();
|
|
||||||
DCHECK(!value_reg.is(map_reg));
|
|
||||||
DCHECK(!value_reg.is(scratch));
|
|
||||||
__ JumpIfSmi(value_reg, miss_label);
|
|
||||||
if (field_type->IsClass()) {
|
|
||||||
__ mov(map_reg, FieldOperand(value_reg, HeapObject::kMapOffset));
|
|
||||||
__ CmpWeakValue(map_reg, Map::WeakCellForMap(field_type->AsClass()),
|
|
||||||
scratch);
|
|
||||||
__ j(not_equal, miss_label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PropertyHandlerCompiler::GenerateAccessCheck(
|
void PropertyHandlerCompiler::GenerateAccessCheck(
|
||||||
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
Handle<WeakCell> native_context_cell, Register scratch1, Register scratch2,
|
||||||
Label* miss, bool compare_native_contexts_only) {
|
Label* miss, bool compare_native_contexts_only) {
|
||||||
@ -540,14 +466,6 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadConstant(Handle<Object> value) {
|
|
||||||
// Return the constant value.
|
|
||||||
__ LoadObject(eax, value);
|
|
||||||
__ ret(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
void NamedLoadHandlerCompiler::GenerateLoadInterceptorWithFollowup(
|
||||||
LookupIterator* it, Register holder_reg) {
|
LookupIterator* it, Register holder_reg) {
|
||||||
DCHECK(holder()->HasNamedInterceptor());
|
DCHECK(holder()->HasNamedInterceptor());
|
||||||
|
@ -138,34 +138,6 @@ void LoadIC::GenerateNormal(MacroAssembler* masm) {
|
|||||||
GenerateRuntimeGetProperty(masm);
|
GenerateRuntimeGetProperty(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void LoadIC_PushArgs(MacroAssembler* masm) {
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
|
|
||||||
Register slot = LoadDescriptor::SlotRegister();
|
|
||||||
Register vector = LoadWithVectorDescriptor::VectorRegister();
|
|
||||||
DCHECK(!edi.is(receiver) && !edi.is(name) && !edi.is(slot) &&
|
|
||||||
!edi.is(vector));
|
|
||||||
|
|
||||||
__ pop(edi);
|
|
||||||
__ push(receiver);
|
|
||||||
__ push(name);
|
|
||||||
__ push(slot);
|
|
||||||
__ push(vector);
|
|
||||||
__ push(edi);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// Return address is on the stack.
|
|
||||||
__ IncrementCounter(masm->isolate()->counters()->ic_load_miss(), 1);
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
||||||
// Return address is on the stack.
|
// Return address is on the stack.
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
Register receiver = LoadDescriptor::ReceiverRegister();
|
||||||
@ -181,32 +153,6 @@ void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|||||||
__ TailCallRuntime(Runtime::kGetProperty);
|
__ TailCallRuntime(Runtime::kGetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
|
||||||
// Return address is on the stack.
|
|
||||||
__ IncrementCounter(masm->isolate()->counters()->ic_keyed_load_miss(), 1);
|
|
||||||
|
|
||||||
LoadIC_PushArgs(masm);
|
|
||||||
|
|
||||||
// Perform tail call to the entry.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedLoadIC_Miss);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
|
||||||
// Return address is on the stack.
|
|
||||||
Register receiver = LoadDescriptor::ReceiverRegister();
|
|
||||||
Register name = LoadDescriptor::NameRegister();
|
|
||||||
DCHECK(!ebx.is(receiver) && !ebx.is(name));
|
|
||||||
|
|
||||||
__ pop(ebx);
|
|
||||||
__ push(receiver);
|
|
||||||
__ push(name);
|
|
||||||
__ push(ebx);
|
|
||||||
|
|
||||||
// Do tail-call to runtime routine.
|
|
||||||
__ TailCallRuntime(Runtime::kKeyedGetProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
static void StoreIC_PushArgs(MacroAssembler* masm) {
|
||||||
Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
|
Register receiver = StoreWithVectorDescriptor::ReceiverRegister();
|
||||||
Register name = StoreWithVectorDescriptor::NameRegister();
|
Register name = StoreWithVectorDescriptor::NameRegister();
|
||||||
|
Loading…
Reference in New Issue
Block a user