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_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
(...skipping 1931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1942 // method. | 1942 // method. |
1943 __ bind(&non_constructor); | 1943 __ bind(&non_constructor); |
1944 { | 1944 { |
1945 FrameScope scope(masm, StackFrame::INTERNAL); | 1945 FrameScope scope(masm, StackFrame::INTERNAL); |
1946 __ Push(rdi); | 1946 __ Push(rdi); |
1947 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); | 1947 __ CallRuntime(Runtime::kThrowCalledNonCallable, 1); |
1948 } | 1948 } |
1949 } | 1949 } |
1950 | 1950 |
1951 | 1951 |
| 1952 static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver, |
| 1953 Register function_template_info, |
| 1954 Register scratch0, Register scratch1, |
| 1955 Register scratch2, |
| 1956 Label* receiver_check_failed) { |
| 1957 Register signature = scratch0; |
| 1958 Register map = scratch1; |
| 1959 Register constructor = scratch2; |
| 1960 |
| 1961 // If receiver is not an object, jump to receiver_check_failed. |
| 1962 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister); |
| 1963 __ j(below, receiver_check_failed); |
| 1964 |
| 1965 // If there is no signature, return the holder. |
| 1966 __ movp(signature, FieldOperand(function_template_info, |
| 1967 FunctionTemplateInfo::kSignatureOffset)); |
| 1968 __ CompareRoot(signature, Heap::kUndefinedValueRootIndex); |
| 1969 Label receiver_check_passed; |
| 1970 __ j(equal, &receiver_check_passed, Label::kNear); |
| 1971 |
| 1972 // Walk the prototype chain. |
| 1973 Label prototype_loop_start; |
| 1974 __ bind(&prototype_loop_start); |
| 1975 |
| 1976 // End if receiver is null or if it's a hidden prototype. |
| 1977 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
| 1978 __ j(equal, receiver_check_failed, Label::kNear); |
| 1979 __ movp(map, FieldOperand(receiver, HeapObject::kMapOffset)); |
| 1980 __ testq(FieldOperand(map, Map::kBitField3Offset), |
| 1981 Immediate(Map::IsHiddenPrototype::kMask)); |
| 1982 __ j(not_zero, receiver_check_failed, Label::kNear); |
| 1983 |
| 1984 // Get the constructor, if any. |
| 1985 __ GetMapConstructor(constructor, map, kScratchRegister); |
| 1986 __ CmpInstanceType(kScratchRegister, JS_FUNCTION_TYPE); |
| 1987 Label next_prototype; |
| 1988 __ j(not_equal, &next_prototype, Label::kNear); |
| 1989 |
| 1990 // Get the constructor's signature. |
| 1991 Register type = constructor; |
| 1992 __ movp(type, |
| 1993 FieldOperand(constructor, JSFunction::kSharedFunctionInfoOffset)); |
| 1994 __ movp(type, FieldOperand(type, SharedFunctionInfo::kFunctionDataOffset)); |
| 1995 |
| 1996 // Loop through the chain of inheriting function templates. |
| 1997 Label function_template_loop; |
| 1998 __ bind(&function_template_loop); |
| 1999 |
| 2000 // If the signatures match, we have a compatible receiver. |
| 2001 __ cmpp(signature, type); |
| 2002 __ j(equal, &receiver_check_passed, Label::kNear); |
| 2003 |
| 2004 // If the current type is not a FunctionTemplateInfo, load the next prototype |
| 2005 // in the chain. |
| 2006 __ JumpIfSmi(type, &next_prototype, Label::kNear); |
| 2007 __ CmpObjectType(type, FUNCTION_TEMPLATE_INFO_TYPE, kScratchRegister); |
| 2008 __ j(not_equal, &next_prototype, Label::kNear); |
| 2009 |
| 2010 // Otherwise load the parent function template and iterate. |
| 2011 __ movp(type, |
| 2012 FieldOperand(type, FunctionTemplateInfo::kParentTemplateOffset)); |
| 2013 __ jmp(&function_template_loop, Label::kNear); |
| 2014 |
| 2015 // Load the next prototype and iterate. |
| 2016 __ bind(&next_prototype); |
| 2017 __ movp(receiver, FieldOperand(map, Map::kPrototypeOffset)); |
| 2018 __ jmp(&prototype_loop_start, Label::kNear); |
| 2019 |
| 2020 __ bind(&receiver_check_passed); |
| 2021 } |
| 2022 |
| 2023 |
| 2024 void Builtins::Generate_HandleFastApiCall(MacroAssembler* masm) { |
| 2025 // ----------- S t a t e ------------- |
| 2026 // -- rax : number of arguments (not including the receiver) |
| 2027 // -- rdi : callee |
| 2028 // -- rsi : context |
| 2029 // -- rsp[0] : return address |
| 2030 // -- rsp[8] : last argument |
| 2031 // -- ... |
| 2032 // -- rsp[rax * 8] : first argument |
| 2033 // -- rsp[(rax + 1) * 8] : receiver |
| 2034 // ----------------------------------- |
| 2035 |
| 2036 StackArgumentsAccessor args(rsp, rax); |
| 2037 __ movp(rcx, args.GetReceiverOperand()); |
| 2038 |
| 2039 // Update the receiver if this is a contextual call. |
| 2040 Label set_global_proxy, valid_receiver; |
| 2041 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); |
| 2042 __ j(equal, &set_global_proxy); |
| 2043 __ bind(&valid_receiver); |
| 2044 |
| 2045 // Load the FunctionTemplateInfo. |
| 2046 __ movp(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 2047 __ movp(rbx, FieldOperand(rbx, SharedFunctionInfo::kFunctionDataOffset)); |
| 2048 |
| 2049 // Do the compatible receiver check. |
| 2050 Label receiver_check_failed; |
| 2051 CompatibleReceiverCheck(masm, rcx, rbx, rdx, r8, r9, &receiver_check_failed); |
| 2052 |
| 2053 // Get the callback offset from the FunctionTemplateInfo, and jump to the |
| 2054 // beginning of the code. |
| 2055 __ movp(rdx, FieldOperand(rbx, FunctionTemplateInfo::kCallCodeOffset)); |
| 2056 __ movp(rdx, FieldOperand(rdx, CallHandlerInfo::kFastHandlerOffset)); |
| 2057 __ addp(rdx, Immediate(Code::kHeaderSize - kHeapObjectTag)); |
| 2058 __ jmp(rdx); |
| 2059 |
| 2060 __ bind(&set_global_proxy); |
| 2061 __ movp(rcx, GlobalObjectOperand()); |
| 2062 __ movp(rcx, FieldOperand(rcx, JSGlobalObject::kGlobalProxyOffset)); |
| 2063 __ movp(args.GetReceiverOperand(), rcx); |
| 2064 __ jmp(&valid_receiver, Label::kNear); |
| 2065 |
| 2066 // Compatible receiver check failed: pop return address, arguments and |
| 2067 // receiver and throw an Illegal Invocation exception. |
| 2068 __ bind(&receiver_check_failed); |
| 2069 __ PopReturnAddressTo(rbx); |
| 2070 __ leap(rax, Operand(rax, times_pointer_size, 1 * kPointerSize)); |
| 2071 __ addp(rsp, rax); |
| 2072 __ PushReturnAddressFrom(rbx); |
| 2073 { |
| 2074 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2075 __ TailCallRuntime(Runtime::kThrowIllegalInvocation, 0, 1); |
| 2076 } |
| 2077 } |
| 2078 |
| 2079 |
1952 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { | 2080 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { |
1953 // Lookup the function in the JavaScript frame. | 2081 // Lookup the function in the JavaScript frame. |
1954 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 2082 __ movp(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
1955 { | 2083 { |
1956 FrameScope scope(masm, StackFrame::INTERNAL); | 2084 FrameScope scope(masm, StackFrame::INTERNAL); |
1957 // Pass function as argument. | 2085 // Pass function as argument. |
1958 __ Push(rax); | 2086 __ Push(rax); |
1959 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); | 2087 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); |
1960 } | 2088 } |
1961 | 2089 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2001 __ ret(0); | 2129 __ ret(0); |
2002 } | 2130 } |
2003 | 2131 |
2004 | 2132 |
2005 #undef __ | 2133 #undef __ |
2006 | 2134 |
2007 } // namespace internal | 2135 } // namespace internal |
2008 } // namespace v8 | 2136 } // namespace v8 |
2009 | 2137 |
2010 #endif // V8_TARGET_ARCH_X64 | 2138 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |