Commit 1d5eb651 authored by ager@chromium.org's avatar ager@chromium.org

Reapply r4686: Complete version of full codegen for x64.

Already reviewed at: http://codereview.chromium.org/2078022/show

TBR=vegorov@chromium.org
Review URL: http://codereview.chromium.org/2137008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4689 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 955828e4
...@@ -121,7 +121,7 @@ static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) { ...@@ -121,7 +121,7 @@ static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) {
: (shared->is_toplevel() || shared->try_full_codegen()); : (shared->is_toplevel() || shared->try_full_codegen());
bool force_full_compiler = false; bool force_full_compiler = false;
#ifdef V8_TARGET_ARCH_IA32 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
// On ia32 the full compiler can compile all code whereas the other platforms // On ia32 the full compiler can compile all code whereas the other platforms
// the constructs supported is checked by the associated syntax checker. When // the constructs supported is checked by the associated syntax checker. When
// --always-full-compiler is used on ia32 the syntax checker is still in // --always-full-compiler is used on ia32 the syntax checker is still in
......
...@@ -149,7 +149,7 @@ DEFINE_bool(full_compiler, true, "enable dedicated backend for run-once code") ...@@ -149,7 +149,7 @@ DEFINE_bool(full_compiler, true, "enable dedicated backend for run-once code")
DEFINE_bool(fast_compiler, false, "enable speculative optimizing backend") DEFINE_bool(fast_compiler, false, "enable speculative optimizing backend")
DEFINE_bool(always_full_compiler, false, DEFINE_bool(always_full_compiler, false,
"try to use the dedicated run-once backend for all code") "try to use the dedicated run-once backend for all code")
#ifdef V8_TARGET_ARCH_IA32 #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
DEFINE_bool(force_full_compiler, false, DEFINE_bool(force_full_compiler, false,
"force use of the dedicated run-once backend for all code") "force use of the dedicated run-once backend for all code")
#endif #endif
......
...@@ -6165,11 +6165,11 @@ void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { ...@@ -6165,11 +6165,11 @@ void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
__ mov(map.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset)); __ mov(map.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
__ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset)); __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset));
__ cmp(map.reg(), FIRST_JS_OBJECT_TYPE); __ cmp(map.reg(), FIRST_JS_OBJECT_TYPE);
destination()->false_target()->Branch(less); destination()->false_target()->Branch(below);
__ cmp(map.reg(), LAST_JS_OBJECT_TYPE); __ cmp(map.reg(), LAST_JS_OBJECT_TYPE);
obj.Unuse(); obj.Unuse();
map.Unuse(); map.Unuse();
destination()->Split(less_equal); destination()->Split(below_equal);
} }
...@@ -6282,7 +6282,7 @@ void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) { ...@@ -6282,7 +6282,7 @@ void CodeGenerator::GenerateClassOf(ZoneList<Expression*>* args) {
__ mov(obj.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset)); __ mov(obj.reg(), FieldOperand(obj.reg(), HeapObject::kMapOffset));
__ movzx_b(tmp.reg(), FieldOperand(obj.reg(), Map::kInstanceTypeOffset)); __ movzx_b(tmp.reg(), FieldOperand(obj.reg(), Map::kInstanceTypeOffset));
__ cmp(tmp.reg(), FIRST_JS_OBJECT_TYPE); __ cmp(tmp.reg(), FIRST_JS_OBJECT_TYPE);
null.Branch(less); null.Branch(below);
// As long as JS_FUNCTION_TYPE is the last instance type and it is // As long as JS_FUNCTION_TYPE is the last instance type and it is
// right after LAST_JS_OBJECT_TYPE, we can avoid checking for // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
...@@ -6872,7 +6872,7 @@ void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) { ...@@ -6872,7 +6872,7 @@ void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
// Check that object doesn't require security checks and // Check that object doesn't require security checks and
// has no indexed interceptor. // has no indexed interceptor.
__ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg()); __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg());
deferred->Branch(less); deferred->Branch(below);
__ movzx_b(tmp1.reg(), FieldOperand(tmp1.reg(), Map::kBitFieldOffset)); __ movzx_b(tmp1.reg(), FieldOperand(tmp1.reg(), Map::kBitFieldOffset));
__ test(tmp1.reg(), Immediate(KeyedLoadIC::kSlowCaseBitFieldMask)); __ test(tmp1.reg(), Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
deferred->Branch(not_zero); deferred->Branch(not_zero);
...@@ -8192,11 +8192,11 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) { ...@@ -8192,11 +8192,11 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
__ mov(map.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset)); __ mov(map.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
__ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset)); __ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kInstanceTypeOffset));
__ cmp(map.reg(), FIRST_JS_OBJECT_TYPE); __ cmp(map.reg(), FIRST_JS_OBJECT_TYPE);
destination()->false_target()->Branch(less); destination()->false_target()->Branch(below);
__ cmp(map.reg(), LAST_JS_OBJECT_TYPE); __ cmp(map.reg(), LAST_JS_OBJECT_TYPE);
answer.Unuse(); answer.Unuse();
map.Unuse(); map.Unuse();
destination()->Split(less_equal); destination()->Split(below_equal);
} else { } else {
// Uncommon case: typeof testing against a string literal that is // Uncommon case: typeof testing against a string literal that is
// never returned from the typeof operator. // never returned from the typeof operator.
...@@ -11602,7 +11602,7 @@ void CompareStub::Generate(MacroAssembler* masm) { ...@@ -11602,7 +11602,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
ASSERT(LAST_TYPE == JS_FUNCTION_TYPE); ASSERT(LAST_TYPE == JS_FUNCTION_TYPE);
Label first_non_object; Label first_non_object;
__ cmp(ecx, FIRST_JS_OBJECT_TYPE); __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
__ j(less, &first_non_object); __ j(below, &first_non_object);
// Return non-zero (eax is not zero) // Return non-zero (eax is not zero)
Label return_not_equal; Label return_not_equal;
...@@ -11619,7 +11619,7 @@ void CompareStub::Generate(MacroAssembler* masm) { ...@@ -11619,7 +11619,7 @@ void CompareStub::Generate(MacroAssembler* masm) {
__ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
__ cmp(ecx, FIRST_JS_OBJECT_TYPE); __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
__ j(greater_equal, &return_not_equal); __ j(above_equal, &return_not_equal);
// Check for oddballs: true, false, null, undefined. // Check for oddballs: true, false, null, undefined.
__ cmp(ecx, ODDBALL_TYPE); __ cmp(ecx, ODDBALL_TYPE);
...@@ -12267,9 +12267,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) { ...@@ -12267,9 +12267,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); // eax - object map __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); // eax - object map
__ movzx_b(ecx, FieldOperand(eax, Map::kInstanceTypeOffset)); // ecx - type __ movzx_b(ecx, FieldOperand(eax, Map::kInstanceTypeOffset)); // ecx - type
__ cmp(ecx, FIRST_JS_OBJECT_TYPE); __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
__ j(less, &slow, not_taken); __ j(below, &slow, not_taken);
__ cmp(ecx, LAST_JS_OBJECT_TYPE); __ cmp(ecx, LAST_JS_OBJECT_TYPE);
__ j(greater, &slow, not_taken); __ j(above, &slow, not_taken);
// Get the prototype of the function. // Get the prototype of the function.
__ mov(edx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address __ mov(edx, Operand(esp, 1 * kPointerSize)); // 1 ~ return address
...@@ -12297,9 +12297,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) { ...@@ -12297,9 +12297,9 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
__ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset)); __ mov(ecx, FieldOperand(ebx, HeapObject::kMapOffset));
__ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset)); __ movzx_b(ecx, FieldOperand(ecx, Map::kInstanceTypeOffset));
__ cmp(ecx, FIRST_JS_OBJECT_TYPE); __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
__ j(less, &slow, not_taken); __ j(below, &slow, not_taken);
__ cmp(ecx, LAST_JS_OBJECT_TYPE); __ cmp(ecx, LAST_JS_OBJECT_TYPE);
__ j(greater, &slow, not_taken); __ j(above, &slow, not_taken);
// Register mapping: // Register mapping:
// eax is object map. // eax is object map.
......
...@@ -806,8 +806,8 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, ...@@ -806,8 +806,8 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ Check(equal, "Unexpected declaration in current context."); __ Check(equal, "Unexpected declaration in current context.");
} }
if (mode == Variable::CONST) { if (mode == Variable::CONST) {
__ mov(eax, Immediate(Factory::the_hole_value())); __ mov(CodeGenerator::ContextOperand(esi, slot->index()),
__ mov(CodeGenerator::ContextOperand(esi, slot->index()), eax); Immediate(Factory::the_hole_value()));
// No write barrier since the hole value is in old space. // No write barrier since the hole value is in old space.
} else if (function != NULL) { } else if (function != NULL) {
VisitForValue(function, kAccumulator); VisitForValue(function, kAccumulator);
...@@ -823,10 +823,8 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, ...@@ -823,10 +823,8 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
__ push(esi); __ push(esi);
__ push(Immediate(variable->name())); __ push(Immediate(variable->name()));
// Declaration nodes are always introduced in one of two modes. // Declaration nodes are always introduced in one of two modes.
ASSERT(mode == Variable::VAR || ASSERT(mode == Variable::VAR || mode == Variable::CONST);
mode == Variable::CONST); PropertyAttributes attr = (mode == Variable::VAR) ? NONE : READ_ONLY;
PropertyAttributes attr =
(mode == Variable::VAR) ? NONE : READ_ONLY;
__ push(Immediate(Smi::FromInt(attr))); __ push(Immediate(Smi::FromInt(attr)));
// Push initial value, if any. // Push initial value, if any.
// Note: For variables we must not push an initial value (such as // Note: For variables we must not push an initial value (such as
...@@ -1070,8 +1068,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) { ...@@ -1070,8 +1068,8 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ StackLimitCheck(&stack_limit_hit); __ StackLimitCheck(&stack_limit_hit);
__ bind(&stack_check_done); __ bind(&stack_check_done);
// Generate code for the going to the next element by incrementing // Generate code for going to the next element by incrementing the
// the index (smi) stored on top of the stack. // index (smi) stored on top of the stack.
__ bind(loop_statement.continue_target()); __ bind(loop_statement.continue_target());
__ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1))); __ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
__ jmp(&loop); __ jmp(&loop);
...@@ -2033,9 +2031,9 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { ...@@ -2033,9 +2031,9 @@ void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) {
__ j(not_zero, if_false); __ j(not_zero, if_false);
__ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset)); __ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceTypeOffset));
__ cmp(ecx, FIRST_JS_OBJECT_TYPE); __ cmp(ecx, FIRST_JS_OBJECT_TYPE);
__ j(less, if_false); __ j(below, if_false);
__ cmp(ecx, LAST_JS_OBJECT_TYPE); __ cmp(ecx, LAST_JS_OBJECT_TYPE);
__ j(less_equal, if_true); __ j(below_equal, if_true);
__ jmp(if_false); __ jmp(if_false);
Apply(context_, if_true, if_false); Apply(context_, if_true, if_false);
...@@ -2227,7 +2225,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) { ...@@ -2227,7 +2225,7 @@ void FullCodeGenerator::EmitClassOf(ZoneList<Expression*>* args) {
__ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
__ movzx_b(ebx, FieldOperand(eax, Map::kInstanceTypeOffset)); __ movzx_b(ebx, FieldOperand(eax, Map::kInstanceTypeOffset));
__ cmp(ebx, FIRST_JS_OBJECT_TYPE); __ cmp(ebx, FIRST_JS_OBJECT_TYPE);
__ j(less, &null); __ j(below, &null);
// As long as JS_FUNCTION_TYPE is the last instance type and it is // As long as JS_FUNCTION_TYPE is the last instance type and it is
// right after LAST_JS_OBJECT_TYPE, we can avoid checking for // right after LAST_JS_OBJECT_TYPE, we can avoid checking for
......
...@@ -3842,11 +3842,13 @@ void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) { ...@@ -3842,11 +3842,13 @@ void CodeGenerator::GenerateIsObject(ZoneList<Expression*>* args) {
__ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset), __ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable)); Immediate(1 << Map::kIsUndetectable));
destination()->false_target()->Branch(not_zero); destination()->false_target()->Branch(not_zero);
__ CmpInstanceType(kScratchRegister, FIRST_JS_OBJECT_TYPE); __ movzxbq(kScratchRegister,
destination()->false_target()->Branch(less); FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
__ CmpInstanceType(kScratchRegister, LAST_JS_OBJECT_TYPE); __ cmpq(kScratchRegister, Immediate(FIRST_JS_OBJECT_TYPE));
destination()->false_target()->Branch(below);
__ cmpq(kScratchRegister, Immediate(LAST_JS_OBJECT_TYPE));
obj.Unuse(); obj.Unuse();
destination()->Split(less_equal); destination()->Split(below_equal);
} }
...@@ -4338,7 +4340,7 @@ void CodeGenerator::GenerateRandomHeapNumber( ...@@ -4338,7 +4340,7 @@ void CodeGenerator::GenerateRandomHeapNumber(
__ PrepareCallCFunction(0); __ PrepareCallCFunction(0);
__ CallCFunction(ExternalReference::random_uint32_function(), 0); __ CallCFunction(ExternalReference::random_uint32_function(), 0);
// Convert 32 random bits in eax to 0.(32 random bits) in a double // Convert 32 random bits in rax to 0.(32 random bits) in a double
// by computing: // by computing:
// ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
__ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single. __ movl(rcx, Immediate(0x49800000)); // 1.0 x 2^20 as single.
......
This diff is collapsed.
...@@ -802,7 +802,7 @@ void MacroAssembler::SmiSub(Register dst, ...@@ -802,7 +802,7 @@ void MacroAssembler::SmiSub(Register dst,
void MacroAssembler::SmiSub(Register dst, void MacroAssembler::SmiSub(Register dst,
Register src1, Register src1,
Operand const& src2, const Operand& src2,
Label* on_not_smi_result) { Label* on_not_smi_result) {
if (on_not_smi_result == NULL) { if (on_not_smi_result == NULL) {
// No overflow checking. Use only when it's known that // No overflow checking. Use only when it's known that
...@@ -920,6 +920,14 @@ void MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) { ...@@ -920,6 +920,14 @@ void MacroAssembler::SmiAddConstant(Register dst, Register src, Smi* constant) {
} }
void MacroAssembler::SmiAddConstant(const Operand& dst, Smi* constant) {
if (constant->value() != 0) {
Move(kScratchRegister, constant);
addq(dst, kScratchRegister);
}
}
void MacroAssembler::SmiAddConstant(Register dst, void MacroAssembler::SmiAddConstant(Register dst,
Register src, Register src,
Smi* constant, Smi* constant,
......
...@@ -306,6 +306,10 @@ class MacroAssembler: public Assembler { ...@@ -306,6 +306,10 @@ class MacroAssembler: public Assembler {
// No overflow testing on the result is done. // No overflow testing on the result is done.
void SmiAddConstant(Register dst, Register src, Smi* constant); void SmiAddConstant(Register dst, Register src, Smi* constant);
// Add an integer constant to a tagged smi, giving a tagged smi as result.
// No overflow testing on the result is done.
void SmiAddConstant(const Operand& dst, Smi* constant);
// Add an integer constant to a tagged smi, giving a tagged smi as result, // Add an integer constant to a tagged smi, giving a tagged smi as result,
// or jumping to a label if the result cannot be represented by a smi. // or jumping to a label if the result cannot be represented by a smi.
void SmiAddConstant(Register dst, void SmiAddConstant(Register dst,
...@@ -349,7 +353,7 @@ class MacroAssembler: public Assembler { ...@@ -349,7 +353,7 @@ class MacroAssembler: public Assembler {
void SmiSub(Register dst, void SmiSub(Register dst,
Register src1, Register src1,
Operand const& src2, const Operand& src2,
Label* on_not_smi_result); Label* on_not_smi_result);
// Multiplies smi values and return the result as a smi, // Multiplies smi values and return the result as a smi,
......
...@@ -273,7 +273,7 @@ static void CreateTraceCallerFunction(const char* func_name, ...@@ -273,7 +273,7 @@ static void CreateTraceCallerFunction(const char* func_name,
// StackTracer uses Top::c_entry_fp as a starting point for stack // StackTracer uses Top::c_entry_fp as a starting point for stack
// walking. // walking.
TEST(CFromJSStackTrace) { TEST(CFromJSStackTrace) {
#ifdef V8_HOST_ARCH_IA32 #if defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_X64)
// TODO(711) The hack of replacing the inline runtime function // TODO(711) The hack of replacing the inline runtime function
// RandomHeapNumber with GetFrameNumber does not work with the way the full // RandomHeapNumber with GetFrameNumber does not work with the way the full
// compiler generates inline runtime calls. // compiler generates inline runtime calls.
...@@ -315,7 +315,7 @@ TEST(CFromJSStackTrace) { ...@@ -315,7 +315,7 @@ TEST(CFromJSStackTrace) {
// Top::c_entry_fp value. In this case, StackTracer uses passed frame // Top::c_entry_fp value. In this case, StackTracer uses passed frame
// pointer value as a starting point for stack walking. // pointer value as a starting point for stack walking.
TEST(PureJSStackTrace) { TEST(PureJSStackTrace) {
#ifdef V8_HOST_ARCH_IA32 #if defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_X64)
// TODO(711) The hack of replacing the inline runtime function // TODO(711) The hack of replacing the inline runtime function
// RandomHeapNumber with GetFrameNumber does not work with the way the full // RandomHeapNumber with GetFrameNumber does not work with the way the full
// compiler generates inline runtime calls. // compiler generates inline runtime calls.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment