OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 1969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1980 jmp(done, done_near); | 1980 jmp(done, done_near); |
1981 } | 1981 } |
1982 } else { | 1982 } else { |
1983 jmp(adaptor, RelocInfo::CODE_TARGET); | 1983 jmp(adaptor, RelocInfo::CODE_TARGET); |
1984 } | 1984 } |
1985 bind(&invoke); | 1985 bind(&invoke); |
1986 } | 1986 } |
1987 } | 1987 } |
1988 | 1988 |
1989 | 1989 |
1990 void MacroAssembler::InvokeCode(const Operand& code, | 1990 void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, |
1991 Register new_target, | 1991 const ParameterCount& expected, |
1992 const ParameterCount& expected, | 1992 const ParameterCount& actual) { |
1993 const ParameterCount& actual, | 1993 Label skip_flooding; |
1994 InvokeFlag flag, | 1994 ExternalReference debug_step_action = |
1995 const CallWrapper& call_wrapper) { | 1995 ExternalReference::debug_last_step_action_address(isolate()); |
| 1996 cmpb(Operand::StaticVariable(debug_step_action), StepIn); |
| 1997 j(not_equal, &skip_flooding); |
| 1998 { |
| 1999 FrameScope frame(this, |
| 2000 has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); |
| 2001 if (expected.is_reg()) { |
| 2002 SmiTag(expected.reg()); |
| 2003 Push(expected.reg()); |
| 2004 } |
| 2005 if (actual.is_reg()) { |
| 2006 SmiTag(actual.reg()); |
| 2007 Push(actual.reg()); |
| 2008 } |
| 2009 if (new_target.is_valid()) { |
| 2010 Push(new_target); |
| 2011 } |
| 2012 Push(fun); |
| 2013 Push(fun); |
| 2014 CallRuntime(Runtime::kDebugPrepareStepInIfStepping, 1); |
| 2015 Pop(fun); |
| 2016 if (new_target.is_valid()) { |
| 2017 Pop(new_target); |
| 2018 } |
| 2019 if (actual.is_reg()) { |
| 2020 Pop(actual.reg()); |
| 2021 SmiUntag(actual.reg()); |
| 2022 } |
| 2023 if (expected.is_reg()) { |
| 2024 Pop(expected.reg()); |
| 2025 SmiUntag(expected.reg()); |
| 2026 } |
| 2027 } |
| 2028 bind(&skip_flooding); |
| 2029 } |
| 2030 |
| 2031 |
| 2032 void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, |
| 2033 const ParameterCount& expected, |
| 2034 const ParameterCount& actual, |
| 2035 InvokeFlag flag, |
| 2036 const CallWrapper& call_wrapper) { |
1996 // You can't call a function without a valid frame. | 2037 // You can't call a function without a valid frame. |
1997 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2038 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
| 2039 DCHECK(function.is(edi)); |
| 2040 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx)); |
1998 | 2041 |
1999 // Ensure new target is passed in the correct register. Otherwise clear the | 2042 if (call_wrapper.NeedsDebugStepCheck()) { |
2000 // appropriate register in case new target is not given. | 2043 FloodFunctionIfStepping(function, new_target, expected, actual); |
2001 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx)); | 2044 } |
| 2045 |
| 2046 // Clear the new.target register if not given. |
2002 if (!new_target.is_valid()) { | 2047 if (!new_target.is_valid()) { |
2003 mov(edx, isolate()->factory()->undefined_value()); | 2048 mov(edx, isolate()->factory()->undefined_value()); |
2004 } | 2049 } |
2005 | 2050 |
2006 Label done; | 2051 Label done; |
2007 bool definitely_mismatches = false; | 2052 bool definitely_mismatches = false; |
2008 InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, | 2053 InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, |
2009 Label::kNear, call_wrapper); | 2054 Label::kNear, call_wrapper); |
2010 if (!definitely_mismatches) { | 2055 if (!definitely_mismatches) { |
| 2056 // We call indirectly through the code field in the function to |
| 2057 // allow recompilation to take effect without changing any of the |
| 2058 // call sites. |
| 2059 Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset); |
2011 if (flag == CALL_FUNCTION) { | 2060 if (flag == CALL_FUNCTION) { |
2012 call_wrapper.BeforeCall(CallSize(code)); | 2061 call_wrapper.BeforeCall(CallSize(code)); |
2013 call(code); | 2062 call(code); |
2014 call_wrapper.AfterCall(); | 2063 call_wrapper.AfterCall(); |
2015 } else { | 2064 } else { |
2016 DCHECK(flag == JUMP_FUNCTION); | 2065 DCHECK(flag == JUMP_FUNCTION); |
2017 jmp(code); | 2066 jmp(code); |
2018 } | 2067 } |
2019 bind(&done); | 2068 bind(&done); |
2020 } | 2069 } |
2021 } | 2070 } |
2022 | 2071 |
2023 | 2072 |
2024 void MacroAssembler::InvokeFunction(Register fun, | 2073 void MacroAssembler::InvokeFunction(Register fun, |
2025 Register new_target, | 2074 Register new_target, |
2026 const ParameterCount& actual, | 2075 const ParameterCount& actual, |
2027 InvokeFlag flag, | 2076 InvokeFlag flag, |
2028 const CallWrapper& call_wrapper) { | 2077 const CallWrapper& call_wrapper) { |
2029 // You can't call a function without a valid frame. | 2078 // You can't call a function without a valid frame. |
2030 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2079 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
2031 | 2080 |
2032 DCHECK(fun.is(edi)); | 2081 DCHECK(fun.is(edi)); |
2033 mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 2082 mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
2034 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2083 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
2035 mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset)); | 2084 mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset)); |
2036 SmiUntag(ebx); | 2085 SmiUntag(ebx); |
2037 | 2086 |
2038 ParameterCount expected(ebx); | 2087 ParameterCount expected(ebx); |
2039 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), new_target, | 2088 InvokeFunctionCode(edi, new_target, expected, actual, flag, call_wrapper); |
2040 expected, actual, flag, call_wrapper); | |
2041 } | 2089 } |
2042 | 2090 |
2043 | 2091 |
2044 void MacroAssembler::InvokeFunction(Register fun, | 2092 void MacroAssembler::InvokeFunction(Register fun, |
2045 const ParameterCount& expected, | 2093 const ParameterCount& expected, |
2046 const ParameterCount& actual, | 2094 const ParameterCount& actual, |
2047 InvokeFlag flag, | 2095 InvokeFlag flag, |
2048 const CallWrapper& call_wrapper) { | 2096 const CallWrapper& call_wrapper) { |
2049 // You can't call a function without a valid frame. | 2097 // You can't call a function without a valid frame. |
2050 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2098 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
2051 | 2099 |
2052 DCHECK(fun.is(edi)); | 2100 DCHECK(fun.is(edi)); |
2053 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2101 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
2054 | 2102 |
2055 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), no_reg, | 2103 InvokeFunctionCode(edi, no_reg, expected, actual, flag, call_wrapper); |
2056 expected, actual, flag, call_wrapper); | |
2057 } | 2104 } |
2058 | 2105 |
2059 | 2106 |
2060 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 2107 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
2061 const ParameterCount& expected, | 2108 const ParameterCount& expected, |
2062 const ParameterCount& actual, | 2109 const ParameterCount& actual, |
2063 InvokeFlag flag, | 2110 InvokeFlag flag, |
2064 const CallWrapper& call_wrapper) { | 2111 const CallWrapper& call_wrapper) { |
2065 LoadHeapObject(edi, function); | 2112 LoadHeapObject(edi, function); |
2066 InvokeFunction(edi, expected, actual, flag, call_wrapper); | 2113 InvokeFunction(edi, expected, actual, flag, call_wrapper); |
2067 } | 2114 } |
2068 | 2115 |
2069 | 2116 |
2070 void MacroAssembler::InvokeBuiltin(int native_context_index, InvokeFlag flag, | 2117 void MacroAssembler::InvokeBuiltin(int native_context_index, InvokeFlag flag, |
2071 const CallWrapper& call_wrapper) { | 2118 const CallWrapper& call_wrapper) { |
2072 // You can't call a builtin without a valid frame. | 2119 // You can't call a builtin without a valid frame. |
2073 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2120 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
2074 | 2121 |
2075 // Rely on the assertion to check that the number of provided | 2122 // Rely on the assertion to check that the number of provided |
2076 // arguments match the expected number of arguments. Fake a | 2123 // arguments match the expected number of arguments. Fake a |
2077 // parameter count to avoid emitting code to do the check. | 2124 // parameter count to avoid emitting code to do the check. |
2078 ParameterCount expected(0); | 2125 ParameterCount expected(0); |
2079 GetBuiltinFunction(edi, native_context_index); | 2126 GetBuiltinFunction(edi, native_context_index); |
2080 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), no_reg, | 2127 InvokeFunctionCode(edi, no_reg, expected, expected, flag, call_wrapper); |
2081 expected, expected, flag, call_wrapper); | |
2082 } | 2128 } |
2083 | 2129 |
2084 | 2130 |
2085 void MacroAssembler::GetBuiltinFunction(Register target, | 2131 void MacroAssembler::GetBuiltinFunction(Register target, |
2086 int native_context_index) { | 2132 int native_context_index) { |
2087 // Load the JavaScript builtin function from the builtins object. | 2133 // Load the JavaScript builtin function from the builtins object. |
2088 mov(target, GlobalObjectOperand()); | 2134 mov(target, GlobalObjectOperand()); |
2089 mov(target, FieldOperand(target, JSGlobalObject::kNativeContextOffset)); | 2135 mov(target, FieldOperand(target, JSGlobalObject::kNativeContextOffset)); |
2090 mov(target, ContextOperand(target, native_context_index)); | 2136 mov(target, ContextOperand(target, native_context_index)); |
2091 } | 2137 } |
2092 | 2138 |
2093 | 2139 |
2094 void MacroAssembler::GetBuiltinEntry(Register target, | |
2095 int native_context_index) { | |
2096 DCHECK(!target.is(edi)); | |
2097 // Load the JavaScript builtin function from the builtins object. | |
2098 GetBuiltinFunction(edi, native_context_index); | |
2099 // Load the code entry point from the function into the target register. | |
2100 mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset)); | |
2101 } | |
2102 | |
2103 | |
2104 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 2140 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
2105 if (context_chain_length > 0) { | 2141 if (context_chain_length > 0) { |
2106 // Move up the chain of contexts to the context containing the slot. | 2142 // Move up the chain of contexts to the context containing the slot. |
2107 mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 2143 mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
2108 for (int i = 1; i < context_chain_length; i++) { | 2144 for (int i = 1; i < context_chain_length; i++) { |
2109 mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 2145 mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
2110 } | 2146 } |
2111 } else { | 2147 } else { |
2112 // Slot is in the current function context. Move it into the | 2148 // Slot is in the current function context. Move it into the |
2113 // destination register in case we store into it (the write barrier | 2149 // destination register in case we store into it (the write barrier |
(...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3147 mov(eax, dividend); | 3183 mov(eax, dividend); |
3148 shr(eax, 31); | 3184 shr(eax, 31); |
3149 add(edx, eax); | 3185 add(edx, eax); |
3150 } | 3186 } |
3151 | 3187 |
3152 | 3188 |
3153 } // namespace internal | 3189 } // namespace internal |
3154 } // namespace v8 | 3190 } // namespace v8 |
3155 | 3191 |
3156 #endif // V8_TARGET_ARCH_IA32 | 3192 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |