| 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 |