Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #include "src/runtime/runtime.h"
6 :
7 : #include "src/base/hashmap.h"
8 : #include "src/contexts.h"
9 : #include "src/handles-inl.h"
10 : #include "src/heap/heap.h"
11 : #include "src/isolate.h"
12 : #include "src/objects-inl.h"
13 : #include "src/reloc-info.h"
14 : #include "src/runtime/runtime-utils.h"
15 :
16 : namespace v8 {
17 : namespace internal {
18 :
19 : // Header of runtime functions.
20 : #define F(name, number_of_args, result_size) \
21 : Address Runtime_##name(int args_length, Address* args_object, \
22 : Isolate* isolate);
23 : FOR_EACH_INTRINSIC_RETURN_OBJECT(F)
24 : #undef F
25 :
26 : #define P(name, number_of_args, result_size) \
27 : ObjectPair Runtime_##name(int args_length, Address* args_object, \
28 : Isolate* isolate);
29 : FOR_EACH_INTRINSIC_RETURN_PAIR(P)
30 : #undef P
31 :
32 : #define F(name, number_of_args, result_size) \
33 : { \
34 : Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \
35 : number_of_args, result_size \
36 : } \
37 : ,
38 :
39 :
40 : #define I(name, number_of_args, result_size) \
41 : { \
42 : Runtime::kInline##name, Runtime::INLINE, "_" #name, \
43 : FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \
44 : } \
45 : ,
46 :
47 : static const Runtime::Function kIntrinsicFunctions[] = {
48 : FOR_EACH_INTRINSIC(F) FOR_EACH_INLINE_INTRINSIC(I)};
49 :
50 : #undef I
51 : #undef F
52 :
53 : namespace {
54 :
55 : V8_DECLARE_ONCE(initialize_function_name_map_once);
56 : static const base::CustomMatcherHashMap* kRuntimeFunctionNameMap;
57 :
58 : struct IntrinsicFunctionIdentifier {
59 : IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
60 5668770 : : data_(data), length_(length) {}
61 :
62 146851 : static bool Match(void* key1, void* key2) {
63 : const IntrinsicFunctionIdentifier* lhs =
64 : static_cast<IntrinsicFunctionIdentifier*>(key1);
65 : const IntrinsicFunctionIdentifier* rhs =
66 : static_cast<IntrinsicFunctionIdentifier*>(key2);
67 146851 : if (lhs->length_ != rhs->length_) return false;
68 293700 : return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs->data_),
69 146850 : reinterpret_cast<const uint8_t*>(rhs->data_),
70 146850 : rhs->length_) == 0;
71 : }
72 :
73 : uint32_t Hash() {
74 : return StringHasher::HashSequentialString<uint8_t>(
75 5668770 : data_, length_, v8::internal::kZeroHashSeed);
76 : }
77 :
78 : const unsigned char* data_;
79 : const int length_;
80 : };
81 :
82 11480 : void InitializeIntrinsicFunctionNames() {
83 : base::CustomMatcherHashMap* function_name_map =
84 11480 : new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match);
85 11215960 : for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
86 5602240 : const Runtime::Function* function = &kIntrinsicFunctions[i];
87 : IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier(
88 : reinterpret_cast<const unsigned char*>(function->name),
89 5602240 : static_cast<int>(strlen(function->name)));
90 : base::HashMap::Entry* entry =
91 5602240 : function_name_map->InsertNew(identifier, identifier->Hash());
92 5602240 : entry->value = const_cast<Runtime::Function*>(function);
93 : }
94 11480 : kRuntimeFunctionNameMap = function_name_map;
95 11480 : }
96 :
97 : } // namespace
98 :
99 376432 : bool Runtime::NeedsExactContext(FunctionId id) {
100 376432 : switch (id) {
101 : case Runtime::kInlineAsyncFunctionReject:
102 : case Runtime::kInlineAsyncFunctionResolve:
103 : // For %_AsyncFunctionReject and %_AsyncFunctionResolve we don't
104 : // really need the current context, which in particular allows
105 : // us to usually eliminate the catch context for the implicit
106 : // try-catch in async function.
107 : return false;
108 : case Runtime::kAddPrivateField:
109 : case Runtime::kCopyDataProperties:
110 : case Runtime::kCreateDataProperty:
111 : case Runtime::kCreatePrivateNameSymbol:
112 : case Runtime::kReThrow:
113 : case Runtime::kThrow:
114 : case Runtime::kThrowApplyNonFunction:
115 : case Runtime::kThrowCalledNonCallable:
116 : case Runtime::kThrowConstAssignError:
117 : case Runtime::kThrowConstructorNonCallableError:
118 : case Runtime::kThrowConstructedNonConstructable:
119 : case Runtime::kThrowConstructorReturnedNonObject:
120 : case Runtime::kThrowInvalidStringLength:
121 : case Runtime::kThrowInvalidTypedArrayAlignment:
122 : case Runtime::kThrowIteratorError:
123 : case Runtime::kThrowIteratorResultNotAnObject:
124 : case Runtime::kThrowNotConstructor:
125 : case Runtime::kThrowRangeError:
126 : case Runtime::kThrowReferenceError:
127 : case Runtime::kThrowAccessedUninitializedVariable:
128 : case Runtime::kThrowStackOverflow:
129 : case Runtime::kThrowStaticPrototypeError:
130 : case Runtime::kThrowSuperAlreadyCalledError:
131 : case Runtime::kThrowSuperNotCalled:
132 : case Runtime::kThrowSymbolAsyncIteratorInvalid:
133 : case Runtime::kThrowSymbolIteratorInvalid:
134 : case Runtime::kThrowThrowMethodMissing:
135 : case Runtime::kThrowTypeError:
136 : case Runtime::kThrowUnsupportedSuperError:
137 : case Runtime::kThrowWasmError:
138 : case Runtime::kThrowWasmStackOverflow:
139 : return false;
140 : default:
141 225987 : return true;
142 : }
143 : }
144 :
145 165086 : bool Runtime::IsNonReturning(FunctionId id) {
146 165086 : switch (id) {
147 : case Runtime::kThrowUnsupportedSuperError:
148 : case Runtime::kThrowConstructorNonCallableError:
149 : case Runtime::kThrowStaticPrototypeError:
150 : case Runtime::kThrowSuperAlreadyCalledError:
151 : case Runtime::kThrowSuperNotCalled:
152 : case Runtime::kReThrow:
153 : case Runtime::kThrow:
154 : case Runtime::kThrowApplyNonFunction:
155 : case Runtime::kThrowCalledNonCallable:
156 : case Runtime::kThrowConstructedNonConstructable:
157 : case Runtime::kThrowConstructorReturnedNonObject:
158 : case Runtime::kThrowInvalidStringLength:
159 : case Runtime::kThrowInvalidTypedArrayAlignment:
160 : case Runtime::kThrowIteratorError:
161 : case Runtime::kThrowIteratorResultNotAnObject:
162 : case Runtime::kThrowThrowMethodMissing:
163 : case Runtime::kThrowSymbolIteratorInvalid:
164 : case Runtime::kThrowNotConstructor:
165 : case Runtime::kThrowRangeError:
166 : case Runtime::kThrowReferenceError:
167 : case Runtime::kThrowAccessedUninitializedVariable:
168 : case Runtime::kThrowStackOverflow:
169 : case Runtime::kThrowSymbolAsyncIteratorInvalid:
170 : case Runtime::kThrowTypeError:
171 : case Runtime::kThrowConstAssignError:
172 : case Runtime::kThrowWasmError:
173 : case Runtime::kThrowWasmStackOverflow:
174 : return true;
175 : default:
176 140548 : return false;
177 : }
178 : }
179 :
180 66532 : const Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
181 : int length) {
182 66530 : base::CallOnce(&initialize_function_name_map_once,
183 66532 : &InitializeIntrinsicFunctionNames);
184 : IntrinsicFunctionIdentifier identifier(name, length);
185 : base::HashMap::Entry* entry =
186 133065 : kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash());
187 66536 : if (entry) {
188 66491 : return reinterpret_cast<Function*>(entry->value);
189 : }
190 : return nullptr;
191 : }
192 :
193 :
194 64 : const Runtime::Function* Runtime::FunctionForEntry(Address entry) {
195 41856 : for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
196 20928 : if (entry == kIntrinsicFunctions[i].entry) {
197 32 : return &(kIntrinsicFunctions[i]);
198 : }
199 : }
200 : return nullptr;
201 : }
202 :
203 :
204 33722766 : const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
205 33722766 : return &(kIntrinsicFunctions[static_cast<int>(id)]);
206 : }
207 :
208 62770 : const Runtime::Function* Runtime::RuntimeFunctionTable(Isolate* isolate) {
209 : #ifdef USE_SIMULATOR
210 : // When running with the simulator we need to provide a table which has
211 : // redirected runtime entry addresses.
212 : if (!isolate->runtime_state()->redirected_intrinsic_functions()) {
213 : size_t function_count = arraysize(kIntrinsicFunctions);
214 : Function* redirected_functions = new Function[function_count];
215 : memcpy(redirected_functions, kIntrinsicFunctions,
216 : sizeof(kIntrinsicFunctions));
217 : for (size_t i = 0; i < function_count; i++) {
218 : ExternalReference redirected_entry =
219 : ExternalReference::Create(static_cast<Runtime::FunctionId>(i));
220 : redirected_functions[i].entry = redirected_entry.address();
221 : }
222 : isolate->runtime_state()->set_redirected_intrinsic_functions(
223 : redirected_functions);
224 : }
225 :
226 : return isolate->runtime_state()->redirected_intrinsic_functions();
227 : #else
228 62770 : return kIntrinsicFunctions;
229 : #endif
230 : }
231 :
232 0 : std::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) {
233 0 : return os << Runtime::FunctionForId(id)->name;
234 : }
235 :
236 :
237 : } // namespace internal
238 121996 : } // namespace v8
|