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_X87 | 5 #if V8_TARGET_ARCH_X87 |
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 1934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1945 jmp(done, done_near); | 1945 jmp(done, done_near); |
1946 } | 1946 } |
1947 } else { | 1947 } else { |
1948 jmp(adaptor, RelocInfo::CODE_TARGET); | 1948 jmp(adaptor, RelocInfo::CODE_TARGET); |
1949 } | 1949 } |
1950 bind(&invoke); | 1950 bind(&invoke); |
1951 } | 1951 } |
1952 } | 1952 } |
1953 | 1953 |
1954 | 1954 |
1955 void MacroAssembler::InvokeCode(const Operand& code, Register new_target, | 1955 void MacroAssembler::FloodFunctionIfStepping(Register fun, Register new_target, |
1956 const ParameterCount& expected, | 1956 const ParameterCount& expected, |
1957 const ParameterCount& actual, InvokeFlag flag, | 1957 const ParameterCount& actual) { |
1958 const CallWrapper& call_wrapper) { | 1958 Label skip_flooding; |
| 1959 ExternalReference debug_step_action = |
| 1960 ExternalReference::debug_last_step_action_address(isolate()); |
| 1961 cmpb(Operand::StaticVariable(debug_step_action), StepIn); |
| 1962 j(not_equal, &skip_flooding); |
| 1963 { |
| 1964 FrameScope frame(this, |
| 1965 has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); |
| 1966 if (expected.is_reg()) { |
| 1967 SmiTag(expected.reg()); |
| 1968 Push(expected.reg()); |
| 1969 } |
| 1970 if (actual.is_reg()) { |
| 1971 SmiTag(actual.reg()); |
| 1972 Push(actual.reg()); |
| 1973 } |
| 1974 if (new_target.is_valid()) { |
| 1975 Push(new_target); |
| 1976 } |
| 1977 Push(fun); |
| 1978 Push(fun); |
| 1979 CallRuntime(Runtime::kDebugPrepareStepInIfStepping, 1); |
| 1980 Pop(fun); |
| 1981 if (new_target.is_valid()) { |
| 1982 Pop(new_target); |
| 1983 } |
| 1984 if (actual.is_reg()) { |
| 1985 Pop(actual.reg()); |
| 1986 SmiUntag(actual.reg()); |
| 1987 } |
| 1988 if (expected.is_reg()) { |
| 1989 Pop(expected.reg()); |
| 1990 SmiUntag(expected.reg()); |
| 1991 } |
| 1992 } |
| 1993 bind(&skip_flooding); |
| 1994 } |
| 1995 |
| 1996 |
| 1997 void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, |
| 1998 const ParameterCount& expected, |
| 1999 const ParameterCount& actual, |
| 2000 InvokeFlag flag, |
| 2001 const CallWrapper& call_wrapper) { |
1959 // You can't call a function without a valid frame. | 2002 // You can't call a function without a valid frame. |
1960 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2003 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
| 2004 DCHECK(function.is(edi)); |
| 2005 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx)); |
1961 | 2006 |
1962 // Ensure new target is passed in the correct register. Otherwise clear the | 2007 if (call_wrapper.NeedsDebugStepCheck()) { |
1963 // appropriate register in case new target is not given. | 2008 FloodFunctionIfStepping(function, new_target, expected, actual); |
1964 DCHECK_IMPLIES(new_target.is_valid(), new_target.is(edx)); | 2009 } |
| 2010 |
| 2011 // Clear the new.target register if not given. |
1965 if (!new_target.is_valid()) { | 2012 if (!new_target.is_valid()) { |
1966 mov(edx, isolate()->factory()->undefined_value()); | 2013 mov(edx, isolate()->factory()->undefined_value()); |
1967 } | 2014 } |
1968 | 2015 |
1969 Label done; | 2016 Label done; |
1970 bool definitely_mismatches = false; | 2017 bool definitely_mismatches = false; |
1971 InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, | 2018 InvokePrologue(expected, actual, &done, &definitely_mismatches, flag, |
1972 Label::kNear, call_wrapper); | 2019 Label::kNear, call_wrapper); |
1973 if (!definitely_mismatches) { | 2020 if (!definitely_mismatches) { |
| 2021 // We call indirectly through the code field in the function to |
| 2022 // allow recompilation to take effect without changing any of the |
| 2023 // call sites. |
| 2024 Operand code = FieldOperand(function, JSFunction::kCodeEntryOffset); |
1974 if (flag == CALL_FUNCTION) { | 2025 if (flag == CALL_FUNCTION) { |
1975 call_wrapper.BeforeCall(CallSize(code)); | 2026 call_wrapper.BeforeCall(CallSize(code)); |
1976 call(code); | 2027 call(code); |
1977 call_wrapper.AfterCall(); | 2028 call_wrapper.AfterCall(); |
1978 } else { | 2029 } else { |
1979 DCHECK(flag == JUMP_FUNCTION); | 2030 DCHECK(flag == JUMP_FUNCTION); |
1980 jmp(code); | 2031 jmp(code); |
1981 } | 2032 } |
1982 bind(&done); | 2033 bind(&done); |
1983 } | 2034 } |
1984 } | 2035 } |
1985 | 2036 |
1986 | 2037 |
1987 void MacroAssembler::InvokeFunction(Register fun, Register new_target, | 2038 void MacroAssembler::InvokeFunction(Register fun, Register new_target, |
1988 const ParameterCount& actual, | 2039 const ParameterCount& actual, |
1989 InvokeFlag flag, | 2040 InvokeFlag flag, |
1990 const CallWrapper& call_wrapper) { | 2041 const CallWrapper& call_wrapper) { |
1991 // You can't call a function without a valid frame. | 2042 // You can't call a function without a valid frame. |
1992 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2043 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
1993 | 2044 |
1994 DCHECK(fun.is(edi)); | 2045 DCHECK(fun.is(edi)); |
1995 mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 2046 mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
1996 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2047 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
1997 mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset)); | 2048 mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kFormalParameterCountOffset)); |
1998 SmiUntag(ebx); | 2049 SmiUntag(ebx); |
1999 | 2050 |
2000 ParameterCount expected(ebx); | 2051 ParameterCount expected(ebx); |
2001 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), new_target, | 2052 InvokeFunctionCode(edi, new_target, expected, actual, flag, call_wrapper); |
2002 expected, actual, flag, call_wrapper); | |
2003 } | 2053 } |
2004 | 2054 |
2005 | 2055 |
2006 void MacroAssembler::InvokeFunction(Register fun, | 2056 void MacroAssembler::InvokeFunction(Register fun, |
2007 const ParameterCount& expected, | 2057 const ParameterCount& expected, |
2008 const ParameterCount& actual, | 2058 const ParameterCount& actual, |
2009 InvokeFlag flag, | 2059 InvokeFlag flag, |
2010 const CallWrapper& call_wrapper) { | 2060 const CallWrapper& call_wrapper) { |
2011 // You can't call a function without a valid frame. | 2061 // You can't call a function without a valid frame. |
2012 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2062 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
2013 | 2063 |
2014 DCHECK(fun.is(edi)); | 2064 DCHECK(fun.is(edi)); |
2015 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2065 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
2016 | 2066 |
2017 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), no_reg, expected, | 2067 InvokeFunctionCode(edi, no_reg, expected, actual, flag, call_wrapper); |
2018 actual, flag, call_wrapper); | |
2019 } | 2068 } |
2020 | 2069 |
2021 | 2070 |
2022 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 2071 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
2023 const ParameterCount& expected, | 2072 const ParameterCount& expected, |
2024 const ParameterCount& actual, | 2073 const ParameterCount& actual, |
2025 InvokeFlag flag, | 2074 InvokeFlag flag, |
2026 const CallWrapper& call_wrapper) { | 2075 const CallWrapper& call_wrapper) { |
2027 LoadHeapObject(edi, function); | 2076 LoadHeapObject(edi, function); |
2028 InvokeFunction(edi, expected, actual, flag, call_wrapper); | 2077 InvokeFunction(edi, expected, actual, flag, call_wrapper); |
2029 } | 2078 } |
2030 | 2079 |
2031 | 2080 |
2032 void MacroAssembler::InvokeBuiltin(int native_context_index, InvokeFlag flag, | 2081 void MacroAssembler::InvokeBuiltin(int native_context_index, InvokeFlag flag, |
2033 const CallWrapper& call_wrapper) { | 2082 const CallWrapper& call_wrapper) { |
2034 // You can't call a builtin without a valid frame. | 2083 // You can't call a builtin without a valid frame. |
2035 DCHECK(flag == JUMP_FUNCTION || has_frame()); | 2084 DCHECK(flag == JUMP_FUNCTION || has_frame()); |
2036 | 2085 |
2037 // Rely on the assertion to check that the number of provided | 2086 // Rely on the assertion to check that the number of provided |
2038 // arguments match the expected number of arguments. Fake a | 2087 // arguments match the expected number of arguments. Fake a |
2039 // parameter count to avoid emitting code to do the check. | 2088 // parameter count to avoid emitting code to do the check. |
2040 ParameterCount expected(0); | 2089 ParameterCount expected(0); |
2041 GetBuiltinFunction(edi, native_context_index); | 2090 GetBuiltinFunction(edi, native_context_index); |
2042 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), no_reg, expected, | 2091 InvokeFunctionCode(edi, no_reg, expected, expected, flag, call_wrapper); |
2043 expected, flag, call_wrapper); | |
2044 } | 2092 } |
2045 | 2093 |
2046 | 2094 |
2047 void MacroAssembler::GetBuiltinFunction(Register target, | 2095 void MacroAssembler::GetBuiltinFunction(Register target, |
2048 int native_context_index) { | 2096 int native_context_index) { |
2049 // Load the JavaScript builtin function from the builtins object. | 2097 // Load the JavaScript builtin function from the builtins object. |
2050 mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 2098 mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
2051 mov(target, FieldOperand(target, JSGlobalObject::kNativeContextOffset)); | 2099 mov(target, FieldOperand(target, JSGlobalObject::kNativeContextOffset)); |
2052 mov(target, ContextOperand(target, native_context_index)); | 2100 mov(target, ContextOperand(target, native_context_index)); |
2053 } | 2101 } |
2054 | 2102 |
2055 | 2103 |
2056 void MacroAssembler::GetBuiltinEntry(Register target, | |
2057 int native_context_index) { | |
2058 DCHECK(!target.is(edi)); | |
2059 // Load the JavaScript builtin function from the builtins object. | |
2060 GetBuiltinFunction(edi, native_context_index); | |
2061 // Load the code entry point from the function into the target register. | |
2062 mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset)); | |
2063 } | |
2064 | |
2065 | |
2066 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 2104 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
2067 if (context_chain_length > 0) { | 2105 if (context_chain_length > 0) { |
2068 // Move up the chain of contexts to the context containing the slot. | 2106 // Move up the chain of contexts to the context containing the slot. |
2069 mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 2107 mov(dst, Operand(esi, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
2070 for (int i = 1; i < context_chain_length; i++) { | 2108 for (int i = 1; i < context_chain_length; i++) { |
2071 mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 2109 mov(dst, Operand(dst, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
2072 } | 2110 } |
2073 } else { | 2111 } else { |
2074 // Slot is in the current function context. Move it into the | 2112 // Slot is in the current function context. Move it into the |
2075 // destination register in case we store into it (the write barrier | 2113 // destination register in case we store into it (the write barrier |
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3017 mov(eax, dividend); | 3055 mov(eax, dividend); |
3018 shr(eax, 31); | 3056 shr(eax, 31); |
3019 add(edx, eax); | 3057 add(edx, eax); |
3020 } | 3058 } |
3021 | 3059 |
3022 | 3060 |
3023 } // namespace internal | 3061 } // namespace internal |
3024 } // namespace v8 | 3062 } // namespace v8 |
3025 | 3063 |
3026 #endif // V8_TARGET_ARCH_X87 | 3064 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |