Port to x64 and ARM and some refactoring of ia32.
Review URL: http://codereview.chromium.org/8111006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10174 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c5c6cc5284
commit
066822a2cf
@ -1793,6 +1793,8 @@ class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
|
|||||||
inputs_[0] = value;
|
inputs_[0] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOperand* value() { return InputAt(0); }
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function")
|
DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function")
|
||||||
DECLARE_HYDROGEN_ACCESSOR(CheckFunction)
|
DECLARE_HYDROGEN_ACCESSOR(CheckFunction)
|
||||||
};
|
};
|
||||||
|
@ -321,7 +321,22 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) {
|
|||||||
if (op->IsRegister()) {
|
if (op->IsRegister()) {
|
||||||
return ToRegister(op->index());
|
return ToRegister(op->index());
|
||||||
} else if (op->IsConstantOperand()) {
|
} else if (op->IsConstantOperand()) {
|
||||||
__ mov(scratch, ToOperand(op));
|
LConstantOperand* const_op = LConstantOperand::cast(op);
|
||||||
|
Handle<Object> literal = chunk_->LookupLiteral(const_op);
|
||||||
|
Representation r = chunk_->LookupLiteralRepresentation(const_op);
|
||||||
|
if (r.IsInteger32()) {
|
||||||
|
ASSERT(literal->IsNumber());
|
||||||
|
__ mov(scratch, Operand(static_cast<int32_t>(literal->Number())));
|
||||||
|
} else if (r.IsDouble()) {
|
||||||
|
Abort("EmitLoadRegister: Unsupported double immediate.");
|
||||||
|
} else {
|
||||||
|
ASSERT(r.IsTagged());
|
||||||
|
if (literal->IsSmi()) {
|
||||||
|
__ mov(scratch, Operand(literal));
|
||||||
|
} else {
|
||||||
|
__ LoadHeapObject(scratch, Handle<HeapObject>::cast(literal));
|
||||||
|
}
|
||||||
|
}
|
||||||
return scratch;
|
return scratch;
|
||||||
} else if (op->IsStackSlot() || op->IsArgument()) {
|
} else if (op->IsStackSlot() || op->IsArgument()) {
|
||||||
__ ldr(scratch, ToMemOperand(op));
|
__ ldr(scratch, ToMemOperand(op));
|
||||||
@ -1337,8 +1352,13 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoConstantT(LConstantT* instr) {
|
void LCodeGen::DoConstantT(LConstantT* instr) {
|
||||||
ASSERT(instr->result()->IsRegister());
|
Handle<Object> value = instr->value();
|
||||||
__ mov(ToRegister(instr->result()), Operand(instr->value()));
|
if (value->IsSmi()) {
|
||||||
|
__ mov(ToRegister(instr->result()), Operand(value));
|
||||||
|
} else {
|
||||||
|
__ LoadHeapObject(ToRegister(instr->result()),
|
||||||
|
Handle<HeapObject>::cast(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2164,7 +2184,7 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
|||||||
// offset to the location of the map check.
|
// offset to the location of the map check.
|
||||||
Register temp = ToRegister(instr->TempAt(0));
|
Register temp = ToRegister(instr->TempAt(0));
|
||||||
ASSERT(temp.is(r4));
|
ASSERT(temp.is(r4));
|
||||||
__ mov(InstanceofStub::right(), Operand(instr->function()));
|
__ LoadHeapObject(InstanceofStub::right(), instr->function());
|
||||||
static const int kAdditionalDelta = 4;
|
static const int kAdditionalDelta = 4;
|
||||||
int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta;
|
int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta;
|
||||||
Label before_push_delta;
|
Label before_push_delta;
|
||||||
@ -2355,7 +2375,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
|
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
|
||||||
LoadHeapObject(result, Handle<HeapObject>::cast(function));
|
__ LoadHeapObject(result, function);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2800,7 +2820,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
||||||
Register result = ToRegister(instr->result());
|
Register result = ToRegister(instr->result());
|
||||||
LoadHeapObject(result, instr->hydrogen()->closure());
|
__ LoadHeapObject(result, instr->hydrogen()->closure());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2868,7 +2888,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
|||||||
|
|
||||||
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
||||||
ASSERT(ToRegister(instr->result()).is(r0));
|
ASSERT(ToRegister(instr->result()).is(r0));
|
||||||
__ mov(r1, Operand(instr->function()));
|
__ LoadHeapObject(r1, instr->function());
|
||||||
CallKnownFunction(instr->function(),
|
CallKnownFunction(instr->function(),
|
||||||
instr->arity(),
|
instr->arity(),
|
||||||
instr,
|
instr,
|
||||||
@ -3306,7 +3326,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
||||||
ASSERT(ToRegister(instr->result()).is(r0));
|
ASSERT(ToRegister(instr->result()).is(r0));
|
||||||
__ mov(r1, Operand(instr->target()));
|
__ LoadHeapObject(r1, instr->target());
|
||||||
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4130,9 +4150,18 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
|
void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
|
||||||
ASSERT(instr->InputAt(0)->IsRegister());
|
Register reg = ToRegister(instr->value());
|
||||||
Register reg = ToRegister(instr->InputAt(0));
|
Handle<JSFunction> target = instr->hydrogen()->target();
|
||||||
__ cmp(reg, Operand(instr->hydrogen()->target()));
|
if (isolate()->heap()->InNewSpace(*target)) {
|
||||||
|
Register reg = ToRegister(instr->value());
|
||||||
|
Handle<JSGlobalPropertyCell> cell =
|
||||||
|
isolate()->factory()->NewJSGlobalPropertyCell(target);
|
||||||
|
__ mov(ip, Operand(Handle<Object>(cell)));
|
||||||
|
__ ldr(ip, FieldMemOperand(ip, JSGlobalPropertyCell::kValueOffset));
|
||||||
|
__ cmp(reg, ip);
|
||||||
|
} else {
|
||||||
|
__ cmp(reg, Operand(target));
|
||||||
|
}
|
||||||
DeoptimizeIf(ne, instr->environment());
|
DeoptimizeIf(ne, instr->environment());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4201,19 +4230,6 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LCodeGen::LoadHeapObject(Register result,
|
|
||||||
Handle<HeapObject> object) {
|
|
||||||
if (heap()->InNewSpace(*object)) {
|
|
||||||
Handle<JSGlobalPropertyCell> cell =
|
|
||||||
factory()->NewJSGlobalPropertyCell(object);
|
|
||||||
__ mov(result, Operand(cell));
|
|
||||||
__ ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
|
|
||||||
} else {
|
|
||||||
__ mov(result, Operand(object));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
||||||
Register temp1 = ToRegister(instr->TempAt(0));
|
Register temp1 = ToRegister(instr->TempAt(0));
|
||||||
Register temp2 = ToRegister(instr->TempAt(1));
|
Register temp2 = ToRegister(instr->TempAt(1));
|
||||||
@ -4222,7 +4238,7 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
|||||||
Handle<JSObject> current_prototype = instr->prototype();
|
Handle<JSObject> current_prototype = instr->prototype();
|
||||||
|
|
||||||
// Load prototype object.
|
// Load prototype object.
|
||||||
LoadHeapObject(temp1, current_prototype);
|
__ LoadHeapObject(temp1, current_prototype);
|
||||||
|
|
||||||
// Check prototype maps up to the holder.
|
// Check prototype maps up to the holder.
|
||||||
while (!current_prototype.is_identical_to(holder)) {
|
while (!current_prototype.is_identical_to(holder)) {
|
||||||
@ -4232,7 +4248,7 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
|||||||
current_prototype =
|
current_prototype =
|
||||||
Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
|
Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
|
||||||
// Load next prototype object.
|
// Load next prototype object.
|
||||||
LoadHeapObject(temp1, current_prototype);
|
__ LoadHeapObject(temp1, current_prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the holder map.
|
// Check the holder map.
|
||||||
@ -4251,7 +4267,7 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
|
|||||||
// than the expected one. The check isn't necessary if the boilerplate has
|
// than the expected one. The check isn't necessary if the boilerplate has
|
||||||
// already been converted to FAST_ELEMENTS.
|
// already been converted to FAST_ELEMENTS.
|
||||||
if (boilerplate_elements_kind != FAST_ELEMENTS) {
|
if (boilerplate_elements_kind != FAST_ELEMENTS) {
|
||||||
LoadHeapObject(r1, instr->hydrogen()->boilerplate_object());
|
__ LoadHeapObject(r1, instr->hydrogen()->boilerplate_object());
|
||||||
// Load map into r2.
|
// Load map into r2.
|
||||||
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
||||||
// Load the map's "bit field 2".
|
// Load the map's "bit field 2".
|
||||||
@ -4325,10 +4341,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
|
|||||||
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
||||||
__ add(r2, result, Operand(*offset));
|
__ add(r2, result, Operand(*offset));
|
||||||
__ str(r2, FieldMemOperand(result, total_offset));
|
__ str(r2, FieldMemOperand(result, total_offset));
|
||||||
LoadHeapObject(source, value_object);
|
__ LoadHeapObject(source, value_object);
|
||||||
EmitDeepCopy(value_object, result, source, offset);
|
EmitDeepCopy(value_object, result, source, offset);
|
||||||
} else if (value->IsHeapObject()) {
|
} else if (value->IsHeapObject()) {
|
||||||
LoadHeapObject(r2, Handle<HeapObject>::cast(value));
|
__ LoadHeapObject(r2, Handle<HeapObject>::cast(value));
|
||||||
__ str(r2, FieldMemOperand(result, total_offset));
|
__ str(r2, FieldMemOperand(result, total_offset));
|
||||||
} else {
|
} else {
|
||||||
__ mov(r2, Operand(value));
|
__ mov(r2, Operand(value));
|
||||||
@ -4354,7 +4370,7 @@ void LCodeGen::DoObjectLiteralFast(LObjectLiteralFast* instr) {
|
|||||||
|
|
||||||
__ bind(&allocated);
|
__ bind(&allocated);
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
LoadHeapObject(r1, instr->hydrogen()->boilerplate());
|
__ LoadHeapObject(r1, instr->hydrogen()->boilerplate());
|
||||||
EmitDeepCopy(instr->hydrogen()->boilerplate(), r0, r1, &offset);
|
EmitDeepCopy(instr->hydrogen()->boilerplate(), r0, r1, &offset);
|
||||||
ASSERT_EQ(size, offset);
|
ASSERT_EQ(size, offset);
|
||||||
}
|
}
|
||||||
|
@ -407,6 +407,19 @@ void MacroAssembler::StoreRoot(Register source,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::LoadHeapObject(Register result,
|
||||||
|
Handle<HeapObject> object) {
|
||||||
|
if (isolate()->heap()->InNewSpace(*object)) {
|
||||||
|
Handle<JSGlobalPropertyCell> cell =
|
||||||
|
isolate()->factory()->NewJSGlobalPropertyCell(object);
|
||||||
|
mov(result, Operand(cell));
|
||||||
|
ldr(result, FieldMemOperand(result, JSGlobalPropertyCell::kValueOffset));
|
||||||
|
} else {
|
||||||
|
mov(result, Operand(object));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::InNewSpace(Register object,
|
void MacroAssembler::InNewSpace(Register object,
|
||||||
Register scratch,
|
Register scratch,
|
||||||
Condition cond,
|
Condition cond,
|
||||||
@ -1111,7 +1124,7 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
|
|||||||
ASSERT(flag == JUMP_FUNCTION || has_frame());
|
ASSERT(flag == JUMP_FUNCTION || has_frame());
|
||||||
|
|
||||||
// Get the function and setup the context.
|
// Get the function and setup the context.
|
||||||
mov(r1, Operand(function));
|
LoadHeapObject(r1, function);
|
||||||
ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
|
ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
|
||||||
|
|
||||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||||
|
@ -166,6 +166,8 @@ class MacroAssembler: public Assembler {
|
|||||||
Heap::RootListIndex index,
|
Heap::RootListIndex index,
|
||||||
Condition cond = al);
|
Condition cond = al);
|
||||||
|
|
||||||
|
void LoadHeapObject(Register dst, Handle<HeapObject> object);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// GC Support
|
// GC Support
|
||||||
|
|
||||||
|
@ -575,7 +575,7 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
|
|||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
// Get the function and setup the context.
|
// Get the function and setup the context.
|
||||||
Handle<JSFunction> function = optimization.constant_function();
|
Handle<JSFunction> function = optimization.constant_function();
|
||||||
__ mov(r5, Operand(function));
|
__ LoadHeapObject(r5, function);
|
||||||
__ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset));
|
__ ldr(cp, FieldMemOperand(r5, JSFunction::kContextOffset));
|
||||||
|
|
||||||
// Pass the additional arguments FastHandleApiCall expects.
|
// Pass the additional arguments FastHandleApiCall expects.
|
||||||
@ -1099,7 +1099,7 @@ void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
|
|||||||
Register scratch1,
|
Register scratch1,
|
||||||
Register scratch2,
|
Register scratch2,
|
||||||
Register scratch3,
|
Register scratch3,
|
||||||
Handle<Object> value,
|
Handle<JSFunction> value,
|
||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
Label* miss) {
|
Label* miss) {
|
||||||
// Check that the receiver isn't a smi.
|
// Check that the receiver isn't a smi.
|
||||||
@ -1110,7 +1110,7 @@ void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
|
|||||||
object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
|
object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
|
||||||
|
|
||||||
// Return the constant value.
|
// Return the constant value.
|
||||||
__ mov(r0, Operand(value));
|
__ LoadHeapObject(r0, value);
|
||||||
__ Ret();
|
__ Ret();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2690,7 +2690,7 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback(
|
|||||||
|
|
||||||
Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
|
Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value,
|
Handle<JSFunction> value,
|
||||||
Handle<String> name) {
|
Handle<String> name) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- r0 : receiver
|
// -- r0 : receiver
|
||||||
@ -2830,7 +2830,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
|
|||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value) {
|
Handle<JSFunction> value) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- lr : return address
|
// -- lr : return address
|
||||||
// -- r0 : key
|
// -- r0 : key
|
||||||
|
@ -546,13 +546,6 @@ void Assembler::push(const Operand& src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Assembler::push(Handle<Object> handle) {
|
|
||||||
EnsureSpace ensure_space(this);
|
|
||||||
EMIT(0x68);
|
|
||||||
emit(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Assembler::pop(Register dst) {
|
void Assembler::pop(Register dst) {
|
||||||
ASSERT(reloc_info_writer.last_pc() != NULL);
|
ASSERT(reloc_info_writer.last_pc() != NULL);
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
|
@ -674,7 +674,6 @@ class Assembler : public AssemblerBase {
|
|||||||
void push_imm32(int32_t imm32);
|
void push_imm32(int32_t imm32);
|
||||||
void push(Register src);
|
void push(Register src);
|
||||||
void push(const Operand& src);
|
void push(const Operand& src);
|
||||||
void push(Handle<Object> handle);
|
|
||||||
|
|
||||||
void pop(Register dst);
|
void pop(Register dst);
|
||||||
void pop(const Operand& dst);
|
void pop(const Operand& dst);
|
||||||
|
@ -3787,7 +3787,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
if (context()->IsAccumulatorValue()) {
|
if (context()->IsAccumulatorValue()) {
|
||||||
__ mov(eax, isolate()->factory()->true_value());
|
__ mov(eax, isolate()->factory()->true_value());
|
||||||
} else {
|
} else {
|
||||||
__ push(isolate()->factory()->true_value());
|
__ Push(isolate()->factory()->true_value());
|
||||||
}
|
}
|
||||||
__ jmp(&done, Label::kNear);
|
__ jmp(&done, Label::kNear);
|
||||||
__ bind(&materialize_false);
|
__ bind(&materialize_false);
|
||||||
@ -3795,7 +3795,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
|
|||||||
if (context()->IsAccumulatorValue()) {
|
if (context()->IsAccumulatorValue()) {
|
||||||
__ mov(eax, isolate()->factory()->false_value());
|
__ mov(eax, isolate()->factory()->false_value());
|
||||||
} else {
|
} else {
|
||||||
__ push(isolate()->factory()->false_value());
|
__ Push(isolate()->factory()->false_value());
|
||||||
}
|
}
|
||||||
__ bind(&done);
|
__ bind(&done);
|
||||||
}
|
}
|
||||||
|
@ -341,6 +341,13 @@ int LCodeGen::ToInteger32(LConstantOperand* op) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
|
||||||
|
Handle<Object> literal = chunk_->LookupLiteral(op);
|
||||||
|
ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
|
||||||
|
return literal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double LCodeGen::ToDouble(LConstantOperand* op) const {
|
double LCodeGen::ToDouble(LConstantOperand* op) const {
|
||||||
Handle<Object> value = chunk_->LookupLiteral(op);
|
Handle<Object> value = chunk_->LookupLiteral(op);
|
||||||
return value->Number();
|
return value->Number();
|
||||||
@ -518,7 +525,7 @@ void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id,
|
|||||||
} else if (context->IsConstantOperand()) {
|
} else if (context->IsConstantOperand()) {
|
||||||
Handle<Object> literal =
|
Handle<Object> literal =
|
||||||
chunk_->LookupLiteral(LConstantOperand::cast(context));
|
chunk_->LookupLiteral(LConstantOperand::cast(context));
|
||||||
LoadHeapObject(esi, Handle<Context>::cast(literal));
|
__ LoadHeapObject(esi, Handle<Context>::cast(literal));
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -1219,7 +1226,7 @@ void LCodeGen::DoConstantT(LConstantT* instr) {
|
|||||||
Register reg = ToRegister(instr->result());
|
Register reg = ToRegister(instr->result());
|
||||||
Handle<Object> handle = instr->value();
|
Handle<Object> handle = instr->value();
|
||||||
if (handle->IsHeapObject()) {
|
if (handle->IsHeapObject()) {
|
||||||
LoadHeapObject(reg, Handle<HeapObject>::cast(handle));
|
__ LoadHeapObject(reg, Handle<HeapObject>::cast(handle));
|
||||||
} else {
|
} else {
|
||||||
__ Set(reg, Immediate(handle));
|
__ Set(reg, Immediate(handle));
|
||||||
}
|
}
|
||||||
@ -2030,7 +2037,7 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
|||||||
// the stub.
|
// the stub.
|
||||||
Register temp = ToRegister(instr->TempAt(0));
|
Register temp = ToRegister(instr->TempAt(0));
|
||||||
ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0);
|
ASSERT(MacroAssembler::SafepointRegisterStackIndex(temp) == 0);
|
||||||
__ mov(InstanceofStub::right(), Immediate(instr->function()));
|
__ LoadHeapObject(InstanceofStub::right(), instr->function());
|
||||||
static const int kAdditionalDelta = 13;
|
static const int kAdditionalDelta = 13;
|
||||||
int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
|
int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
|
||||||
__ mov(temp, Immediate(delta));
|
__ mov(temp, Immediate(delta));
|
||||||
@ -2229,7 +2236,24 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
|
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
|
||||||
LoadHeapObject(result, Handle<HeapObject>::cast(function));
|
__ LoadHeapObject(result, function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
|
||||||
|
ASSERT(!operand->IsDoubleRegister());
|
||||||
|
if (operand->IsConstantOperand()) {
|
||||||
|
Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
|
||||||
|
if (object->IsSmi()) {
|
||||||
|
__ Push(Handle<Smi>::cast(object));
|
||||||
|
} else {
|
||||||
|
__ PushHeapObject(Handle<HeapObject>::cast(object));
|
||||||
|
}
|
||||||
|
} else if (operand->IsRegister()) {
|
||||||
|
__ push(ToRegister(operand));
|
||||||
|
} else {
|
||||||
|
__ push(ToOperand(operand));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2639,17 +2663,13 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoPushArgument(LPushArgument* instr) {
|
void LCodeGen::DoPushArgument(LPushArgument* instr) {
|
||||||
LOperand* argument = instr->InputAt(0);
|
LOperand* argument = instr->InputAt(0);
|
||||||
if (argument->IsConstantOperand()) {
|
EmitPushTaggedOperand(argument);
|
||||||
__ push(ToImmediate(argument));
|
|
||||||
} else {
|
|
||||||
__ push(ToOperand(argument));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
||||||
Register result = ToRegister(instr->result());
|
Register result = ToRegister(instr->result());
|
||||||
LoadHeapObject(result, instr->hydrogen()->closure());
|
__ LoadHeapObject(result, instr->hydrogen()->closure());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2719,7 +2739,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
|||||||
|
|
||||||
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
||||||
ASSERT(ToRegister(instr->result()).is(eax));
|
ASSERT(ToRegister(instr->result()).is(eax));
|
||||||
__ mov(edi, instr->function());
|
__ LoadHeapObject(edi, instr->function());
|
||||||
CallKnownFunction(instr->function(),
|
CallKnownFunction(instr->function(),
|
||||||
instr->arity(),
|
instr->arity(),
|
||||||
instr,
|
instr,
|
||||||
@ -3148,7 +3168,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
||||||
ASSERT(ToRegister(instr->result()).is(eax));
|
ASSERT(ToRegister(instr->result()).is(eax));
|
||||||
__ mov(edi, instr->target());
|
__ LoadHeapObject(edi, instr->target());
|
||||||
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3513,16 +3533,8 @@ void LCodeGen::DoStringLength(LStringLength* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoStringAdd(LStringAdd* instr) {
|
void LCodeGen::DoStringAdd(LStringAdd* instr) {
|
||||||
if (instr->left()->IsConstantOperand()) {
|
EmitPushTaggedOperand(instr->left());
|
||||||
__ push(ToImmediate(instr->left()));
|
EmitPushTaggedOperand(instr->right());
|
||||||
} else {
|
|
||||||
__ push(ToOperand(instr->left()));
|
|
||||||
}
|
|
||||||
if (instr->right()->IsConstantOperand()) {
|
|
||||||
__ push(ToImmediate(instr->right()));
|
|
||||||
} else {
|
|
||||||
__ push(ToOperand(instr->right()));
|
|
||||||
}
|
|
||||||
StringAddStub stub(NO_STRING_CHECK_IN_STUB);
|
StringAddStub stub(NO_STRING_CHECK_IN_STUB);
|
||||||
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
|
||||||
}
|
}
|
||||||
@ -4021,7 +4033,7 @@ void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
|
|||||||
__ cmp(reg, Operand::Cell(cell));
|
__ cmp(reg, Operand::Cell(cell));
|
||||||
} else {
|
} else {
|
||||||
Operand operand = ToOperand(instr->value());
|
Operand operand = ToOperand(instr->value());
|
||||||
__ cmp(operand, instr->hydrogen()->target());
|
__ cmp(operand, target);
|
||||||
}
|
}
|
||||||
DeoptimizeIf(not_equal, instr->environment());
|
DeoptimizeIf(not_equal, instr->environment());
|
||||||
}
|
}
|
||||||
@ -4085,17 +4097,6 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) {
|
|
||||||
if (isolate()->heap()->InNewSpace(*object)) {
|
|
||||||
Handle<JSGlobalPropertyCell> cell =
|
|
||||||
isolate()->factory()->NewJSGlobalPropertyCell(object);
|
|
||||||
__ mov(result, Operand::Cell(cell));
|
|
||||||
} else {
|
|
||||||
__ mov(result, object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
||||||
Register reg = ToRegister(instr->TempAt(0));
|
Register reg = ToRegister(instr->TempAt(0));
|
||||||
|
|
||||||
@ -4103,7 +4104,7 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
|||||||
Handle<JSObject> current_prototype = instr->prototype();
|
Handle<JSObject> current_prototype = instr->prototype();
|
||||||
|
|
||||||
// Load prototype object.
|
// Load prototype object.
|
||||||
LoadHeapObject(reg, current_prototype);
|
__ LoadHeapObject(reg, current_prototype);
|
||||||
|
|
||||||
// Check prototype maps up to the holder.
|
// Check prototype maps up to the holder.
|
||||||
while (!current_prototype.is_identical_to(holder)) {
|
while (!current_prototype.is_identical_to(holder)) {
|
||||||
@ -4113,7 +4114,7 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
|||||||
current_prototype =
|
current_prototype =
|
||||||
Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
|
Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
|
||||||
// Load next prototype object.
|
// Load next prototype object.
|
||||||
LoadHeapObject(reg, current_prototype);
|
__ LoadHeapObject(reg, current_prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the holder map.
|
// Check the holder map.
|
||||||
@ -4133,7 +4134,7 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
|
|||||||
// than the expected one. The check isn't necessary if the boilerplate has
|
// than the expected one. The check isn't necessary if the boilerplate has
|
||||||
// already been converted to FAST_ELEMENTS.
|
// already been converted to FAST_ELEMENTS.
|
||||||
if (boilerplate_elements_kind != FAST_ELEMENTS) {
|
if (boilerplate_elements_kind != FAST_ELEMENTS) {
|
||||||
LoadHeapObject(eax, instr->hydrogen()->boilerplate_object());
|
__ LoadHeapObject(eax, instr->hydrogen()->boilerplate_object());
|
||||||
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
__ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||||
// Load the map's "bit field 2". We only need the first byte,
|
// Load the map's "bit field 2". We only need the first byte,
|
||||||
// but the following masking takes care of that anyway.
|
// but the following masking takes care of that anyway.
|
||||||
@ -4183,7 +4184,7 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
|
|||||||
ASSERT(!result.is(ecx));
|
ASSERT(!result.is(ecx));
|
||||||
|
|
||||||
if (FLAG_debug_code) {
|
if (FLAG_debug_code) {
|
||||||
LoadHeapObject(ecx, object);
|
__ LoadHeapObject(ecx, object);
|
||||||
__ cmp(source, ecx);
|
__ cmp(source, ecx);
|
||||||
__ Assert(equal, "Unexpected object literal boilerplate");
|
__ Assert(equal, "Unexpected object literal boilerplate");
|
||||||
}
|
}
|
||||||
@ -4213,10 +4214,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
|
|||||||
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
||||||
__ lea(ecx, Operand(result, *offset));
|
__ lea(ecx, Operand(result, *offset));
|
||||||
__ mov(FieldOperand(result, total_offset), ecx);
|
__ mov(FieldOperand(result, total_offset), ecx);
|
||||||
LoadHeapObject(source, value_object);
|
__ LoadHeapObject(source, value_object);
|
||||||
EmitDeepCopy(value_object, result, source, offset);
|
EmitDeepCopy(value_object, result, source, offset);
|
||||||
} else if (value->IsHeapObject()) {
|
} else if (value->IsHeapObject()) {
|
||||||
LoadHeapObject(ecx, Handle<HeapObject>::cast(value));
|
__ LoadHeapObject(ecx, Handle<HeapObject>::cast(value));
|
||||||
__ mov(FieldOperand(result, total_offset), ecx);
|
__ mov(FieldOperand(result, total_offset), ecx);
|
||||||
} else {
|
} else {
|
||||||
__ mov(FieldOperand(result, total_offset), Immediate(value));
|
__ mov(FieldOperand(result, total_offset), Immediate(value));
|
||||||
@ -4241,7 +4242,7 @@ void LCodeGen::DoObjectLiteralFast(LObjectLiteralFast* instr) {
|
|||||||
|
|
||||||
__ bind(&allocated);
|
__ bind(&allocated);
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
LoadHeapObject(ebx, instr->hydrogen()->boilerplate());
|
__ LoadHeapObject(ebx, instr->hydrogen()->boilerplate());
|
||||||
EmitDeepCopy(instr->hydrogen()->boilerplate(), eax, ebx, &offset);
|
EmitDeepCopy(instr->hydrogen()->boilerplate(), eax, ebx, &offset);
|
||||||
ASSERT_EQ(size, offset);
|
ASSERT_EQ(size, offset);
|
||||||
}
|
}
|
||||||
@ -4363,11 +4364,7 @@ void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoTypeof(LTypeof* instr) {
|
void LCodeGen::DoTypeof(LTypeof* instr) {
|
||||||
LOperand* input = instr->InputAt(1);
|
LOperand* input = instr->InputAt(1);
|
||||||
if (input->IsConstantOperand()) {
|
EmitPushTaggedOperand(input);
|
||||||
__ push(ToImmediate(input));
|
|
||||||
} else {
|
|
||||||
__ push(ToOperand(input));
|
|
||||||
}
|
|
||||||
CallRuntime(Runtime::kTypeof, 1, instr);
|
CallRuntime(Runtime::kTypeof, 1, instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4515,11 +4512,7 @@ void LCodeGen::DoDeleteProperty(LDeleteProperty* instr) {
|
|||||||
LOperand* obj = instr->object();
|
LOperand* obj = instr->object();
|
||||||
LOperand* key = instr->key();
|
LOperand* key = instr->key();
|
||||||
__ push(ToOperand(obj));
|
__ push(ToOperand(obj));
|
||||||
if (key->IsConstantOperand()) {
|
EmitPushTaggedOperand(key);
|
||||||
__ push(ToImmediate(key));
|
|
||||||
} else {
|
|
||||||
__ push(ToOperand(key));
|
|
||||||
}
|
|
||||||
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
||||||
LPointerMap* pointers = instr->pointer_map();
|
LPointerMap* pointers = instr->pointer_map();
|
||||||
RecordPosition(pointers->position());
|
RecordPosition(pointers->position());
|
||||||
@ -4616,16 +4609,8 @@ void LCodeGen::DoOsrEntry(LOsrEntry* instr) {
|
|||||||
void LCodeGen::DoIn(LIn* instr) {
|
void LCodeGen::DoIn(LIn* instr) {
|
||||||
LOperand* obj = instr->object();
|
LOperand* obj = instr->object();
|
||||||
LOperand* key = instr->key();
|
LOperand* key = instr->key();
|
||||||
if (key->IsConstantOperand()) {
|
EmitPushTaggedOperand(key);
|
||||||
__ push(ToImmediate(key));
|
EmitPushTaggedOperand(obj);
|
||||||
} else {
|
|
||||||
__ push(ToOperand(key));
|
|
||||||
}
|
|
||||||
if (obj->IsConstantOperand()) {
|
|
||||||
__ push(ToImmediate(obj));
|
|
||||||
} else {
|
|
||||||
__ push(ToOperand(obj));
|
|
||||||
}
|
|
||||||
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
||||||
LPointerMap* pointers = instr->pointer_map();
|
LPointerMap* pointers = instr->pointer_map();
|
||||||
RecordPosition(pointers->position());
|
RecordPosition(pointers->position());
|
||||||
|
@ -207,8 +207,6 @@ class LCodeGen BASE_EMBEDDED {
|
|||||||
LInstruction* instr,
|
LInstruction* instr,
|
||||||
CallKind call_kind);
|
CallKind call_kind);
|
||||||
|
|
||||||
void LoadHeapObject(Register result, Handle<HeapObject> object);
|
|
||||||
|
|
||||||
void RecordSafepointWithLazyDeopt(LInstruction* instr,
|
void RecordSafepointWithLazyDeopt(LInstruction* instr,
|
||||||
SafepointMode safepoint_mode);
|
SafepointMode safepoint_mode);
|
||||||
|
|
||||||
@ -227,6 +225,7 @@ class LCodeGen BASE_EMBEDDED {
|
|||||||
Register ToRegister(int index) const;
|
Register ToRegister(int index) const;
|
||||||
XMMRegister ToDoubleRegister(int index) const;
|
XMMRegister ToDoubleRegister(int index) const;
|
||||||
int ToInteger32(LConstantOperand* op) const;
|
int ToInteger32(LConstantOperand* op) const;
|
||||||
|
Handle<Object> ToHandle(LConstantOperand* op) const;
|
||||||
double ToDouble(LConstantOperand* op) const;
|
double ToDouble(LConstantOperand* op) const;
|
||||||
Operand BuildFastArrayOperand(LOperand* elements_pointer,
|
Operand BuildFastArrayOperand(LOperand* elements_pointer,
|
||||||
LOperand* key,
|
LOperand* key,
|
||||||
@ -305,6 +304,10 @@ class LCodeGen BASE_EMBEDDED {
|
|||||||
|
|
||||||
void EnsureSpaceForLazyDeopt();
|
void EnsureSpaceForLazyDeopt();
|
||||||
|
|
||||||
|
// Emits code for pushing either a tagged constant, a (non-double)
|
||||||
|
// register, or a stack slot operand.
|
||||||
|
void EmitPushTaggedOperand(LOperand* operand);
|
||||||
|
|
||||||
LChunk* const chunk_;
|
LChunk* const chunk_;
|
||||||
MacroAssembler* const masm_;
|
MacroAssembler* const masm_;
|
||||||
CompilationInfo* const info_;
|
CompilationInfo* const info_;
|
||||||
|
@ -755,7 +755,7 @@ void MacroAssembler::PushTryHandler(CodeLocation try_location,
|
|||||||
|
|
||||||
// Push the state and the code object.
|
// Push the state and the code object.
|
||||||
push(Immediate(state));
|
push(Immediate(state));
|
||||||
push(CodeObject());
|
Push(CodeObject());
|
||||||
|
|
||||||
// Link the current handler as the next handler.
|
// Link the current handler as the next handler.
|
||||||
ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
|
ExternalReference handler_address(Isolate::kHandlerAddress, isolate());
|
||||||
@ -2022,7 +2022,7 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
|
|||||||
ASSERT(flag == JUMP_FUNCTION || has_frame());
|
ASSERT(flag == JUMP_FUNCTION || has_frame());
|
||||||
|
|
||||||
// Get the function and setup the context.
|
// Get the function and setup the context.
|
||||||
mov(edi, Immediate(function));
|
LoadHeapObject(edi, function);
|
||||||
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
|
mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
|
||||||
|
|
||||||
ParameterCount expected(function->shared()->formal_parameter_count());
|
ParameterCount expected(function->shared()->formal_parameter_count());
|
||||||
@ -2151,6 +2151,29 @@ int MacroAssembler::SafepointRegisterStackIndex(int reg_code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::LoadHeapObject(Register result,
|
||||||
|
Handle<HeapObject> object) {
|
||||||
|
if (isolate()->heap()->InNewSpace(*object)) {
|
||||||
|
Handle<JSGlobalPropertyCell> cell =
|
||||||
|
isolate()->factory()->NewJSGlobalPropertyCell(object);
|
||||||
|
mov(result, Operand::Cell(cell));
|
||||||
|
} else {
|
||||||
|
mov(result, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
|
||||||
|
if (isolate()->heap()->InNewSpace(*object)) {
|
||||||
|
Handle<JSGlobalPropertyCell> cell =
|
||||||
|
isolate()->factory()->NewJSGlobalPropertyCell(object);
|
||||||
|
push(Operand::Cell(cell));
|
||||||
|
} else {
|
||||||
|
Push(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::Ret() {
|
void MacroAssembler::Ret() {
|
||||||
ret(0);
|
ret(0);
|
||||||
}
|
}
|
||||||
@ -2182,11 +2205,6 @@ void MacroAssembler::Move(Register dst, Register src) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::Move(Register dst, Handle<Object> value) {
|
|
||||||
mov(dst, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
|
void MacroAssembler::SetCounter(StatsCounter* counter, int value) {
|
||||||
if (FLAG_native_code_counters && counter->Enabled()) {
|
if (FLAG_native_code_counters && counter->Enabled()) {
|
||||||
mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
|
mov(Operand::StaticVariable(ExternalReference(counter)), Immediate(value));
|
||||||
|
@ -237,6 +237,9 @@ class MacroAssembler: public Assembler {
|
|||||||
void StoreToSafepointRegisterSlot(Register dst, Immediate src);
|
void StoreToSafepointRegisterSlot(Register dst, Immediate src);
|
||||||
void LoadFromSafepointRegisterSlot(Register dst, Register src);
|
void LoadFromSafepointRegisterSlot(Register dst, Register src);
|
||||||
|
|
||||||
|
void LoadHeapObject(Register result, Handle<HeapObject> object);
|
||||||
|
void PushHeapObject(Handle<HeapObject> object);
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// JavaScript invokes
|
// JavaScript invokes
|
||||||
|
|
||||||
@ -718,10 +721,8 @@ class MacroAssembler: public Assembler {
|
|||||||
// Move if the registers are not identical.
|
// Move if the registers are not identical.
|
||||||
void Move(Register target, Register source);
|
void Move(Register target, Register source);
|
||||||
|
|
||||||
void Move(Register target, Handle<Object> value);
|
|
||||||
|
|
||||||
// Push a handle value.
|
// Push a handle value.
|
||||||
void Push(Handle<Object> handle) { push(handle); }
|
void Push(Handle<Object> handle) { push(Immediate(handle)); }
|
||||||
|
|
||||||
Handle<Object> CodeObject() {
|
Handle<Object> CodeObject() {
|
||||||
ASSERT(!code_object_.is_null());
|
ASSERT(!code_object_.is_null());
|
||||||
|
@ -429,7 +429,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
|||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
// Get the function and setup the context.
|
// Get the function and setup the context.
|
||||||
Handle<JSFunction> function = optimization.constant_function();
|
Handle<JSFunction> function = optimization.constant_function();
|
||||||
__ mov(edi, Immediate(function));
|
__ LoadHeapObject(edi, function);
|
||||||
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
|
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
|
||||||
|
|
||||||
// Pass the additional arguments.
|
// Pass the additional arguments.
|
||||||
@ -1025,7 +1025,7 @@ void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
|
|||||||
Register scratch1,
|
Register scratch1,
|
||||||
Register scratch2,
|
Register scratch2,
|
||||||
Register scratch3,
|
Register scratch3,
|
||||||
Handle<Object> value,
|
Handle<JSFunction> value,
|
||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
Label* miss) {
|
Label* miss) {
|
||||||
// Check that the receiver isn't a smi.
|
// Check that the receiver isn't a smi.
|
||||||
@ -1036,7 +1036,7 @@ void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
|
|||||||
object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
|
object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
|
||||||
|
|
||||||
// Return the constant value.
|
// Return the constant value.
|
||||||
__ mov(eax, value);
|
__ LoadHeapObject(eax, value);
|
||||||
__ ret(0);
|
__ ret(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2729,7 +2729,7 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback(
|
|||||||
|
|
||||||
Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
|
Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value,
|
Handle<JSFunction> value,
|
||||||
Handle<String> name) {
|
Handle<String> name) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- eax : receiver
|
// -- eax : receiver
|
||||||
@ -2891,7 +2891,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
|
|||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value) {
|
Handle<JSFunction> value) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- eax : key
|
// -- eax : key
|
||||||
// -- edx : receiver
|
// -- edx : receiver
|
||||||
|
@ -912,7 +912,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
|
|||||||
name, receiver, holder, lookup->GetFieldIndex());
|
name, receiver, holder, lookup->GetFieldIndex());
|
||||||
break;
|
break;
|
||||||
case CONSTANT_FUNCTION: {
|
case CONSTANT_FUNCTION: {
|
||||||
Handle<Object> constant(lookup->GetConstantFunction());
|
Handle<JSFunction> constant(lookup->GetConstantFunction());
|
||||||
code = isolate()->stub_cache()->ComputeLoadConstant(
|
code = isolate()->stub_cache()->ComputeLoadConstant(
|
||||||
name, receiver, holder, constant);
|
name, receiver, holder, constant);
|
||||||
break;
|
break;
|
||||||
@ -1163,7 +1163,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
|
|||||||
name, receiver, holder, lookup->GetFieldIndex());
|
name, receiver, holder, lookup->GetFieldIndex());
|
||||||
break;
|
break;
|
||||||
case CONSTANT_FUNCTION: {
|
case CONSTANT_FUNCTION: {
|
||||||
Handle<Object> constant(lookup->GetConstantFunction());
|
Handle<JSFunction> constant(lookup->GetConstantFunction());
|
||||||
code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
|
code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
|
||||||
name, receiver, holder, constant);
|
name, receiver, holder, constant);
|
||||||
break;
|
break;
|
||||||
|
@ -1703,6 +1703,20 @@ void FixedArray::set(int index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
|
||||||
|
int index,
|
||||||
|
Object* value) {
|
||||||
|
ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
|
||||||
|
ASSERT(index >= 0 && index < array->length());
|
||||||
|
int offset = kHeaderSize + index * kPointerSize;
|
||||||
|
WRITE_FIELD(array, offset, value);
|
||||||
|
Heap* heap = array->GetHeap();
|
||||||
|
if (heap->InNewSpace(value)) {
|
||||||
|
heap->RecordWrite(array->address(), offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void FixedArray::NoWriteBarrierSet(FixedArray* array,
|
void FixedArray::NoWriteBarrierSet(FixedArray* array,
|
||||||
int index,
|
int index,
|
||||||
Object* value) {
|
Object* value) {
|
||||||
@ -1797,12 +1811,12 @@ void DescriptorArray::set_bit_field3_storage(int value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DescriptorArray::NoWriteBarrierSwap(FixedArray* array,
|
void DescriptorArray::NoIncrementalWriteBarrierSwap(FixedArray* array,
|
||||||
int first,
|
int first,
|
||||||
int second) {
|
int second) {
|
||||||
Object* tmp = array->get(first);
|
Object* tmp = array->get(first);
|
||||||
NoWriteBarrierSet(array, first, array->get(second));
|
NoIncrementalWriteBarrierSet(array, first, array->get(second));
|
||||||
NoWriteBarrierSet(array, second, tmp);
|
NoIncrementalWriteBarrierSet(array, second, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1914,18 +1928,14 @@ void DescriptorArray::Set(int descriptor_number,
|
|||||||
// Range check.
|
// Range check.
|
||||||
ASSERT(descriptor_number < number_of_descriptors());
|
ASSERT(descriptor_number < number_of_descriptors());
|
||||||
|
|
||||||
// Make sure none of the elements in desc are in new space.
|
NoIncrementalWriteBarrierSet(this,
|
||||||
ASSERT(!HEAP->InNewSpace(desc->GetKey()));
|
|
||||||
ASSERT(!HEAP->InNewSpace(desc->GetValue()));
|
|
||||||
|
|
||||||
NoWriteBarrierSet(this,
|
|
||||||
ToKeyIndex(descriptor_number),
|
ToKeyIndex(descriptor_number),
|
||||||
desc->GetKey());
|
desc->GetKey());
|
||||||
FixedArray* content_array = GetContentArray();
|
FixedArray* content_array = GetContentArray();
|
||||||
NoWriteBarrierSet(content_array,
|
NoIncrementalWriteBarrierSet(content_array,
|
||||||
ToValueIndex(descriptor_number),
|
ToValueIndex(descriptor_number),
|
||||||
desc->GetValue());
|
desc->GetValue());
|
||||||
NoWriteBarrierSet(content_array,
|
NoIncrementalWriteBarrierSet(content_array,
|
||||||
ToDetailsIndex(descriptor_number),
|
ToDetailsIndex(descriptor_number),
|
||||||
desc->GetDetails().AsSmi());
|
desc->GetDetails().AsSmi());
|
||||||
}
|
}
|
||||||
@ -1941,13 +1951,14 @@ void DescriptorArray::CopyFrom(int index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DescriptorArray::NoWriteBarrierSwapDescriptors(int first, int second) {
|
void DescriptorArray::NoIncrementalWriteBarrierSwapDescriptors(
|
||||||
NoWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
|
int first, int second) {
|
||||||
|
NoIncrementalWriteBarrierSwap(this, ToKeyIndex(first), ToKeyIndex(second));
|
||||||
FixedArray* content_array = GetContentArray();
|
FixedArray* content_array = GetContentArray();
|
||||||
NoWriteBarrierSwap(content_array,
|
NoIncrementalWriteBarrierSwap(content_array,
|
||||||
ToValueIndex(first),
|
ToValueIndex(first),
|
||||||
ToValueIndex(second));
|
ToValueIndex(second));
|
||||||
NoWriteBarrierSwap(content_array,
|
NoIncrementalWriteBarrierSwap(content_array,
|
||||||
ToDetailsIndex(first),
|
ToDetailsIndex(first),
|
||||||
ToDetailsIndex(second));
|
ToDetailsIndex(second));
|
||||||
}
|
}
|
||||||
|
@ -1640,8 +1640,6 @@ MaybeObject* JSObject::AddConstantFunctionProperty(
|
|||||||
String* name,
|
String* name,
|
||||||
JSFunction* function,
|
JSFunction* function,
|
||||||
PropertyAttributes attributes) {
|
PropertyAttributes attributes) {
|
||||||
ASSERT(!GetHeap()->InNewSpace(function));
|
|
||||||
|
|
||||||
// Allocate new instance descriptors with (name, function) added
|
// Allocate new instance descriptors with (name, function) added
|
||||||
ConstantFunctionDescriptor d(name, function, attributes);
|
ConstantFunctionDescriptor d(name, function, attributes);
|
||||||
Object* new_descriptors;
|
Object* new_descriptors;
|
||||||
@ -1756,7 +1754,7 @@ MaybeObject* JSObject::AddProperty(String* name,
|
|||||||
// Ensure the descriptor array does not get too big.
|
// Ensure the descriptor array does not get too big.
|
||||||
if (map_of_this->instance_descriptors()->number_of_descriptors() <
|
if (map_of_this->instance_descriptors()->number_of_descriptors() <
|
||||||
DescriptorArray::kMaxNumberOfDescriptors) {
|
DescriptorArray::kMaxNumberOfDescriptors) {
|
||||||
if (value->IsJSFunction() && !heap->InNewSpace(value)) {
|
if (value->IsJSFunction()) {
|
||||||
return AddConstantFunctionProperty(name,
|
return AddConstantFunctionProperty(name,
|
||||||
JSFunction::cast(value),
|
JSFunction::cast(value),
|
||||||
attributes);
|
attributes);
|
||||||
@ -2995,7 +2993,6 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
|
|||||||
ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
|
ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION);
|
||||||
JSFunction* function =
|
JSFunction* function =
|
||||||
JSFunction::cast(target_descriptors->GetValue(number));
|
JSFunction::cast(target_descriptors->GetValue(number));
|
||||||
ASSERT(!HEAP->InNewSpace(function));
|
|
||||||
if (value == function) {
|
if (value == function) {
|
||||||
set_map(target_map);
|
set_map(target_map);
|
||||||
return value;
|
return value;
|
||||||
@ -5635,7 +5632,7 @@ void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (child_hash <= parent_hash) break;
|
if (child_hash <= parent_hash) break;
|
||||||
NoWriteBarrierSwapDescriptors(parent_index, child_index);
|
NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
|
||||||
// Now element at child_index could be < its children.
|
// Now element at child_index could be < its children.
|
||||||
parent_index = child_index; // parent_hash remains correct.
|
parent_index = child_index; // parent_hash remains correct.
|
||||||
}
|
}
|
||||||
@ -5644,7 +5641,7 @@ void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
|
|||||||
// Extract elements and create sorted array.
|
// Extract elements and create sorted array.
|
||||||
for (int i = len - 1; i > 0; --i) {
|
for (int i = len - 1; i > 0; --i) {
|
||||||
// Put max element at the back of the array.
|
// Put max element at the back of the array.
|
||||||
NoWriteBarrierSwapDescriptors(0, i);
|
NoIncrementalWriteBarrierSwapDescriptors(0, i);
|
||||||
// Shift down the new top element.
|
// Shift down the new top element.
|
||||||
int parent_index = 0;
|
int parent_index = 0;
|
||||||
const uint32_t parent_hash = GetKey(parent_index)->Hash();
|
const uint32_t parent_hash = GetKey(parent_index)->Hash();
|
||||||
@ -5660,7 +5657,7 @@ void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (child_hash <= parent_hash) break;
|
if (child_hash <= parent_hash) break;
|
||||||
NoWriteBarrierSwapDescriptors(parent_index, child_index);
|
NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
|
||||||
parent_index = child_index;
|
parent_index = child_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2187,6 +2187,13 @@ class FixedArray: public FixedArrayBase {
|
|||||||
int index,
|
int index,
|
||||||
Object* value);
|
Object* value);
|
||||||
|
|
||||||
|
// Set operation on FixedArray without incremental write barrier. Can
|
||||||
|
// only be used if the object is guaranteed to be white (whiteness witness
|
||||||
|
// is present).
|
||||||
|
static inline void NoIncrementalWriteBarrierSet(FixedArray* array,
|
||||||
|
int index,
|
||||||
|
Object* value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
|
DISALLOW_IMPLICIT_CONSTRUCTORS(FixedArray);
|
||||||
};
|
};
|
||||||
@ -2465,12 +2472,12 @@ class DescriptorArray: public FixedArray {
|
|||||||
NULL_DESCRIPTOR;
|
NULL_DESCRIPTOR;
|
||||||
}
|
}
|
||||||
// Swap operation on FixedArray without using write barriers.
|
// Swap operation on FixedArray without using write barriers.
|
||||||
static inline void NoWriteBarrierSwap(FixedArray* array,
|
static inline void NoIncrementalWriteBarrierSwap(
|
||||||
int first,
|
FixedArray* array, int first, int second);
|
||||||
int second);
|
|
||||||
|
|
||||||
// Swap descriptor first and second.
|
// Swap descriptor first and second.
|
||||||
inline void NoWriteBarrierSwapDescriptors(int first, int second);
|
inline void NoIncrementalWriteBarrierSwapDescriptors(
|
||||||
|
int first, int second);
|
||||||
|
|
||||||
FixedArray* GetContentArray() {
|
FixedArray* GetContentArray() {
|
||||||
return FixedArray::cast(get(kContentArrayIndex));
|
return FixedArray::cast(get(kContentArrayIndex));
|
||||||
|
@ -184,7 +184,7 @@ Handle<Code> StubCache::ComputeLoadCallback(Handle<String> name,
|
|||||||
Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
|
Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value) {
|
Handle<JSFunction> value) {
|
||||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||||
Code::Flags flags =
|
Code::Flags flags =
|
||||||
Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
|
Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION);
|
||||||
@ -266,7 +266,7 @@ Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
|
|||||||
Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
|
Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value) {
|
Handle<JSFunction> value) {
|
||||||
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
|
||||||
Code::Flags flags =
|
Code::Flags flags =
|
||||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
|
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
|
||||||
|
@ -92,7 +92,7 @@ class StubCache {
|
|||||||
Handle<Code> ComputeLoadConstant(Handle<String> name,
|
Handle<Code> ComputeLoadConstant(Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value);
|
Handle<JSFunction> value);
|
||||||
|
|
||||||
Handle<Code> ComputeLoadInterceptor(Handle<String> name,
|
Handle<Code> ComputeLoadInterceptor(Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
@ -121,7 +121,7 @@ class StubCache {
|
|||||||
Handle<Code> ComputeKeyedLoadConstant(Handle<String> name,
|
Handle<Code> ComputeKeyedLoadConstant(Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value);
|
Handle<JSFunction> value);
|
||||||
|
|
||||||
Handle<Code> ComputeKeyedLoadInterceptor(Handle<String> name,
|
Handle<Code> ComputeKeyedLoadInterceptor(Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
@ -518,7 +518,7 @@ class StubCompiler BASE_EMBEDDED {
|
|||||||
Register scratch1,
|
Register scratch1,
|
||||||
Register scratch2,
|
Register scratch2,
|
||||||
Register scratch3,
|
Register scratch3,
|
||||||
Handle<Object> value,
|
Handle<JSFunction> value,
|
||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
Label* miss);
|
Label* miss);
|
||||||
|
|
||||||
@ -568,7 +568,7 @@ class LoadStubCompiler: public StubCompiler {
|
|||||||
|
|
||||||
Handle<Code> CompileLoadConstant(Handle<JSObject> object,
|
Handle<Code> CompileLoadConstant(Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value,
|
Handle<JSFunction> value,
|
||||||
Handle<String> name);
|
Handle<String> name);
|
||||||
|
|
||||||
Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
|
Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
|
||||||
@ -603,7 +603,7 @@ class KeyedLoadStubCompiler: public StubCompiler {
|
|||||||
Handle<Code> CompileLoadConstant(Handle<String> name,
|
Handle<Code> CompileLoadConstant(Handle<String> name,
|
||||||
Handle<JSObject> object,
|
Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value);
|
Handle<JSFunction> value);
|
||||||
|
|
||||||
Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
|
Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
|
@ -1154,8 +1154,13 @@ void LCodeGen::DoConstantD(LConstantD* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoConstantT(LConstantT* instr) {
|
void LCodeGen::DoConstantT(LConstantT* instr) {
|
||||||
ASSERT(instr->result()->IsRegister());
|
Handle<Object> value = instr->value();
|
||||||
__ Move(ToRegister(instr->result()), instr->value());
|
if (value->IsSmi()) {
|
||||||
|
__ Move(ToRegister(instr->result()), value);
|
||||||
|
} else {
|
||||||
|
__ LoadHeapObject(ToRegister(instr->result()),
|
||||||
|
Handle<HeapObject>::cast(value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1932,7 +1937,7 @@ void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
|
|||||||
InstanceofStub stub(flags);
|
InstanceofStub stub(flags);
|
||||||
|
|
||||||
__ push(ToRegister(instr->InputAt(0)));
|
__ push(ToRegister(instr->InputAt(0)));
|
||||||
__ Push(instr->function());
|
__ PushHeapObject(instr->function());
|
||||||
|
|
||||||
static const int kAdditionalDelta = 10;
|
static const int kAdditionalDelta = 10;
|
||||||
int delta =
|
int delta =
|
||||||
@ -2002,13 +2007,7 @@ void LCodeGen::DoReturn(LReturn* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
|
void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
|
||||||
Register result = ToRegister(instr->result());
|
Register result = ToRegister(instr->result());
|
||||||
if (result.is(rax)) {
|
__ LoadGlobalCell(result, instr->hydrogen()->cell());
|
||||||
__ load_rax(instr->hydrogen()->cell().location(),
|
|
||||||
RelocInfo::GLOBAL_PROPERTY_CELL);
|
|
||||||
} else {
|
|
||||||
__ movq(result, instr->hydrogen()->cell(), RelocInfo::GLOBAL_PROPERTY_CELL);
|
|
||||||
__ movq(result, Operand(result, 0));
|
|
||||||
}
|
|
||||||
if (instr->hydrogen()->RequiresHoleCheck()) {
|
if (instr->hydrogen()->RequiresHoleCheck()) {
|
||||||
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
|
__ CompareRoot(result, Heap::kTheHoleValueRootIndex);
|
||||||
DeoptimizeIf(equal, instr->environment());
|
DeoptimizeIf(equal, instr->environment());
|
||||||
@ -2144,7 +2143,7 @@ void LCodeGen::EmitLoadFieldOrConstantFunction(Register result,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
|
Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*type));
|
||||||
LoadHeapObject(result, Handle<HeapObject>::cast(function));
|
__ LoadHeapObject(result, function);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2566,7 +2565,7 @@ void LCodeGen::DoPushArgument(LPushArgument* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
void LCodeGen::DoThisFunction(LThisFunction* instr) {
|
||||||
Register result = ToRegister(instr->result());
|
Register result = ToRegister(instr->result());
|
||||||
LoadHeapObject(result, instr->hydrogen()->closure());
|
__ LoadHeapObject(result, instr->hydrogen()->closure());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2637,7 +2636,7 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
|
|||||||
|
|
||||||
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
|
||||||
ASSERT(ToRegister(instr->result()).is(rax));
|
ASSERT(ToRegister(instr->result()).is(rax));
|
||||||
__ Move(rdi, instr->function());
|
__ LoadHeapObject(rdi, instr->function());
|
||||||
CallKnownFunction(instr->function(),
|
CallKnownFunction(instr->function(),
|
||||||
instr->arity(),
|
instr->arity(),
|
||||||
instr,
|
instr,
|
||||||
@ -3064,7 +3063,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
|
|||||||
|
|
||||||
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
|
||||||
ASSERT(ToRegister(instr->result()).is(rax));
|
ASSERT(ToRegister(instr->result()).is(rax));
|
||||||
__ Move(rdi, instr->target());
|
__ LoadHeapObject(rdi, instr->target());
|
||||||
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
CallKnownFunction(instr->target(), instr->arity(), instr, CALL_AS_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3747,9 +3746,16 @@ void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
|
|||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
|
void LCodeGen::DoCheckFunction(LCheckFunction* instr) {
|
||||||
ASSERT(instr->InputAt(0)->IsRegister());
|
Register reg = ToRegister(instr->value());
|
||||||
Register reg = ToRegister(instr->InputAt(0));
|
Handle<JSFunction> target = instr->hydrogen()->target();
|
||||||
__ Cmp(reg, instr->hydrogen()->target());
|
if (isolate()->heap()->InNewSpace(*target)) {
|
||||||
|
Handle<JSGlobalPropertyCell> cell =
|
||||||
|
isolate()->factory()->NewJSGlobalPropertyCell(target);
|
||||||
|
__ movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
|
||||||
|
__ cmpq(reg, Operand(kScratchRegister, 0));
|
||||||
|
} else {
|
||||||
|
__ Cmp(reg, target);
|
||||||
|
}
|
||||||
DeoptimizeIf(not_equal, instr->environment());
|
DeoptimizeIf(not_equal, instr->environment());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3815,18 +3821,6 @@ void LCodeGen::DoClampTToUint8(LClampTToUint8* instr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) {
|
|
||||||
if (heap()->InNewSpace(*object)) {
|
|
||||||
Handle<JSGlobalPropertyCell> cell =
|
|
||||||
factory()->NewJSGlobalPropertyCell(object);
|
|
||||||
__ movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
|
|
||||||
__ movq(result, Operand(result, 0));
|
|
||||||
} else {
|
|
||||||
__ Move(result, object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
||||||
Register reg = ToRegister(instr->TempAt(0));
|
Register reg = ToRegister(instr->TempAt(0));
|
||||||
|
|
||||||
@ -3834,7 +3828,7 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
|||||||
Handle<JSObject> current_prototype = instr->prototype();
|
Handle<JSObject> current_prototype = instr->prototype();
|
||||||
|
|
||||||
// Load prototype object.
|
// Load prototype object.
|
||||||
LoadHeapObject(reg, current_prototype);
|
__ LoadHeapObject(reg, current_prototype);
|
||||||
|
|
||||||
// Check prototype maps up to the holder.
|
// Check prototype maps up to the holder.
|
||||||
while (!current_prototype.is_identical_to(holder)) {
|
while (!current_prototype.is_identical_to(holder)) {
|
||||||
@ -3844,7 +3838,7 @@ void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) {
|
|||||||
current_prototype =
|
current_prototype =
|
||||||
Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
|
Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype()));
|
||||||
// Load next prototype object.
|
// Load next prototype object.
|
||||||
LoadHeapObject(reg, current_prototype);
|
__ LoadHeapObject(reg, current_prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the holder map.
|
// Check the holder map.
|
||||||
@ -3863,7 +3857,7 @@ void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
|
|||||||
// than the expected one. The check isn't necessary if the boilerplate has
|
// than the expected one. The check isn't necessary if the boilerplate has
|
||||||
// already been converted to FAST_ELEMENTS.
|
// already been converted to FAST_ELEMENTS.
|
||||||
if (boilerplate_elements_kind != FAST_ELEMENTS) {
|
if (boilerplate_elements_kind != FAST_ELEMENTS) {
|
||||||
LoadHeapObject(rax, instr->hydrogen()->boilerplate_object());
|
__ LoadHeapObject(rax, instr->hydrogen()->boilerplate_object());
|
||||||
__ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
|
__ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
|
||||||
// Load the map's "bit field 2".
|
// Load the map's "bit field 2".
|
||||||
__ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset));
|
__ movb(rbx, FieldOperand(rbx, Map::kBitField2Offset));
|
||||||
@ -3937,10 +3931,10 @@ void LCodeGen::EmitDeepCopy(Handle<JSObject> object,
|
|||||||
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
Handle<JSObject> value_object = Handle<JSObject>::cast(value);
|
||||||
__ lea(rcx, Operand(result, *offset));
|
__ lea(rcx, Operand(result, *offset));
|
||||||
__ movq(FieldOperand(result, total_offset), rcx);
|
__ movq(FieldOperand(result, total_offset), rcx);
|
||||||
LoadHeapObject(source, value_object);
|
__ LoadHeapObject(source, value_object);
|
||||||
EmitDeepCopy(value_object, result, source, offset);
|
EmitDeepCopy(value_object, result, source, offset);
|
||||||
} else if (value->IsHeapObject()) {
|
} else if (value->IsHeapObject()) {
|
||||||
LoadHeapObject(rcx, Handle<HeapObject>::cast(value));
|
__ LoadHeapObject(rcx, Handle<HeapObject>::cast(value));
|
||||||
__ movq(FieldOperand(result, total_offset), rcx);
|
__ movq(FieldOperand(result, total_offset), rcx);
|
||||||
} else {
|
} else {
|
||||||
__ movq(rcx, value, RelocInfo::NONE);
|
__ movq(rcx, value, RelocInfo::NONE);
|
||||||
@ -3965,7 +3959,7 @@ void LCodeGen::DoObjectLiteralFast(LObjectLiteralFast* instr) {
|
|||||||
|
|
||||||
__ bind(&allocated);
|
__ bind(&allocated);
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
LoadHeapObject(rbx, instr->hydrogen()->boilerplate());
|
__ LoadHeapObject(rbx, instr->hydrogen()->boilerplate());
|
||||||
EmitDeepCopy(instr->hydrogen()->boilerplate(), rax, rbx, &offset);
|
EmitDeepCopy(instr->hydrogen()->boilerplate(), rax, rbx, &offset);
|
||||||
ASSERT_EQ(size, offset);
|
ASSERT_EQ(size, offset);
|
||||||
}
|
}
|
||||||
@ -4091,7 +4085,12 @@ void LCodeGen::DoTypeof(LTypeof* instr) {
|
|||||||
void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
|
void LCodeGen::EmitPushTaggedOperand(LOperand* operand) {
|
||||||
ASSERT(!operand->IsDoubleRegister());
|
ASSERT(!operand->IsDoubleRegister());
|
||||||
if (operand->IsConstantOperand()) {
|
if (operand->IsConstantOperand()) {
|
||||||
__ Push(ToHandle(LConstantOperand::cast(operand)));
|
Handle<Object> object = ToHandle(LConstantOperand::cast(operand));
|
||||||
|
if (object->IsSmi()) {
|
||||||
|
__ Push(Handle<Smi>::cast(object));
|
||||||
|
} else {
|
||||||
|
__ PushHeapObject(Handle<HeapObject>::cast(object));
|
||||||
|
}
|
||||||
} else if (operand->IsRegister()) {
|
} else if (operand->IsRegister()) {
|
||||||
__ push(ToRegister(operand));
|
__ push(ToRegister(operand));
|
||||||
} else {
|
} else {
|
||||||
|
@ -198,7 +198,6 @@ class LCodeGen BASE_EMBEDDED {
|
|||||||
LInstruction* instr,
|
LInstruction* instr,
|
||||||
CallKind call_kind);
|
CallKind call_kind);
|
||||||
|
|
||||||
void LoadHeapObject(Register result, Handle<HeapObject> object);
|
|
||||||
|
|
||||||
void RecordSafepointWithLazyDeopt(LInstruction* instr,
|
void RecordSafepointWithLazyDeopt(LInstruction* instr,
|
||||||
SafepointMode safepoint_mode,
|
SafepointMode safepoint_mode,
|
||||||
|
@ -1781,6 +1781,8 @@ class LCheckFunction: public LTemplateInstruction<0, 1, 0> {
|
|||||||
inputs_[0] = value;
|
inputs_[0] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOperand* value() { return InputAt(0); }
|
||||||
|
|
||||||
DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function")
|
DECLARE_CONCRETE_INSTRUCTION(CheckFunction, "check-function")
|
||||||
DECLARE_HYDROGEN_ACCESSOR(CheckFunction)
|
DECLARE_HYDROGEN_ACCESSOR(CheckFunction)
|
||||||
};
|
};
|
||||||
|
@ -2238,6 +2238,43 @@ void MacroAssembler::Push(Handle<Object> source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::LoadHeapObject(Register result,
|
||||||
|
Handle<HeapObject> object) {
|
||||||
|
if (isolate()->heap()->InNewSpace(*object)) {
|
||||||
|
Handle<JSGlobalPropertyCell> cell =
|
||||||
|
isolate()->factory()->NewJSGlobalPropertyCell(object);
|
||||||
|
movq(result, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
|
||||||
|
movq(result, Operand(result, 0));
|
||||||
|
} else {
|
||||||
|
Move(result, object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::PushHeapObject(Handle<HeapObject> object) {
|
||||||
|
if (isolate()->heap()->InNewSpace(*object)) {
|
||||||
|
Handle<JSGlobalPropertyCell> cell =
|
||||||
|
isolate()->factory()->NewJSGlobalPropertyCell(object);
|
||||||
|
movq(kScratchRegister, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
|
||||||
|
movq(kScratchRegister, Operand(kScratchRegister, 0));
|
||||||
|
push(kScratchRegister);
|
||||||
|
} else {
|
||||||
|
Push(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MacroAssembler::LoadGlobalCell(Register dst,
|
||||||
|
Handle<JSGlobalPropertyCell> cell) {
|
||||||
|
if (dst.is(rax)) {
|
||||||
|
load_rax(cell.location(), RelocInfo::GLOBAL_PROPERTY_CELL);
|
||||||
|
} else {
|
||||||
|
movq(dst, cell, RelocInfo::GLOBAL_PROPERTY_CELL);
|
||||||
|
movq(dst, Operand(dst, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void MacroAssembler::Push(Smi* source) {
|
void MacroAssembler::Push(Smi* source) {
|
||||||
intptr_t smi = reinterpret_cast<intptr_t>(source);
|
intptr_t smi = reinterpret_cast<intptr_t>(source);
|
||||||
if (is_int32(smi)) {
|
if (is_int32(smi)) {
|
||||||
@ -3049,7 +3086,7 @@ void MacroAssembler::InvokeFunction(Handle<JSFunction> function,
|
|||||||
ASSERT(flag == JUMP_FUNCTION || has_frame());
|
ASSERT(flag == JUMP_FUNCTION || has_frame());
|
||||||
|
|
||||||
// Get the function and setup the context.
|
// Get the function and setup the context.
|
||||||
Move(rdi, function);
|
LoadHeapObject(rdi, function);
|
||||||
movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
|
movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
|
||||||
|
|
||||||
// We call indirectly through the code field in the function to
|
// We call indirectly through the code field in the function to
|
||||||
|
@ -784,6 +784,14 @@ class MacroAssembler: public Assembler {
|
|||||||
void Cmp(const Operand& dst, Smi* src);
|
void Cmp(const Operand& dst, Smi* src);
|
||||||
void Push(Handle<Object> source);
|
void Push(Handle<Object> source);
|
||||||
|
|
||||||
|
// Load a heap object and handle the case of new-space objects by
|
||||||
|
// indirecting via a global cell.
|
||||||
|
void LoadHeapObject(Register result, Handle<HeapObject> object);
|
||||||
|
void PushHeapObject(Handle<HeapObject> object);
|
||||||
|
|
||||||
|
// Load a global cell into a register.
|
||||||
|
void LoadGlobalCell(Register dst, Handle<JSGlobalPropertyCell> cell);
|
||||||
|
|
||||||
// Emit code to discard a non-negative number of pointer-sized elements
|
// Emit code to discard a non-negative number of pointer-sized elements
|
||||||
// from the stack, clobbering only the rsp register.
|
// from the stack, clobbering only the rsp register.
|
||||||
void Drop(int stack_elements);
|
void Drop(int stack_elements);
|
||||||
|
@ -421,7 +421,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
|||||||
// -----------------------------------
|
// -----------------------------------
|
||||||
// Get the function and setup the context.
|
// Get the function and setup the context.
|
||||||
Handle<JSFunction> function = optimization.constant_function();
|
Handle<JSFunction> function = optimization.constant_function();
|
||||||
__ Move(rdi, function);
|
__ LoadHeapObject(rdi, function);
|
||||||
__ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
|
__ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
|
||||||
|
|
||||||
// Pass the additional arguments.
|
// Pass the additional arguments.
|
||||||
@ -1015,7 +1015,7 @@ void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
|
|||||||
Register scratch1,
|
Register scratch1,
|
||||||
Register scratch2,
|
Register scratch2,
|
||||||
Register scratch3,
|
Register scratch3,
|
||||||
Handle<Object> value,
|
Handle<JSFunction> value,
|
||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
Label* miss) {
|
Label* miss) {
|
||||||
// Check that the receiver isn't a smi.
|
// Check that the receiver isn't a smi.
|
||||||
@ -1026,7 +1026,7 @@ void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
|
|||||||
object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
|
object, receiver, holder, scratch1, scratch2, scratch3, name, miss);
|
||||||
|
|
||||||
// Return the constant value.
|
// Return the constant value.
|
||||||
__ Move(rax, value);
|
__ LoadHeapObject(rax, value);
|
||||||
__ ret(0);
|
__ ret(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2578,7 +2578,7 @@ Handle<Code> LoadStubCompiler::CompileLoadCallback(
|
|||||||
|
|
||||||
Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
|
Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value,
|
Handle<JSFunction> value,
|
||||||
Handle<String> name) {
|
Handle<String> name) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- rax : receiver
|
// -- rax : receiver
|
||||||
@ -2732,7 +2732,7 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
|
|||||||
Handle<String> name,
|
Handle<String> name,
|
||||||
Handle<JSObject> receiver,
|
Handle<JSObject> receiver,
|
||||||
Handle<JSObject> holder,
|
Handle<JSObject> holder,
|
||||||
Handle<Object> value) {
|
Handle<JSFunction> value) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- rax : key
|
// -- rax : key
|
||||||
// -- rdx : receiver
|
// -- rdx : receiver
|
||||||
|
Loading…
Reference in New Issue
Block a user