1 // Copyright 2014 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-utils.h"
6
7 #include "src/accessors.h"
8 #include "src/arguments.h"
9 #include "src/compiler.h"
10 #include "src/frames-inl.h"
11 #include "src/isolate-inl.h"
12 #include "src/messages.h"
13 #include "src/wasm/wasm-module.h"
14
15 namespace v8 {
16 namespace internal {
17
RUNTIME_FUNCTION(Runtime_FunctionGetName)18 RUNTIME_FUNCTION(Runtime_FunctionGetName) {
19 HandleScope scope(isolate);
20 DCHECK(args.length() == 1);
21
22 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
23 if (function->IsJSBoundFunction()) {
24 RETURN_RESULT_OR_FAILURE(
25 isolate, JSBoundFunction::GetName(
26 isolate, Handle<JSBoundFunction>::cast(function)));
27 } else {
28 return *JSFunction::GetName(isolate, Handle<JSFunction>::cast(function));
29 }
30 }
31
32
RUNTIME_FUNCTION(Runtime_FunctionSetName)33 RUNTIME_FUNCTION(Runtime_FunctionSetName) {
34 HandleScope scope(isolate);
35 DCHECK(args.length() == 2);
36
37 CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
38 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
39
40 name = String::Flatten(name);
41 f->shared()->set_name(*name);
42 return isolate->heap()->undefined_value();
43 }
44
45
RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype)46 RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
47 SealHandleScope shs(isolate);
48 DCHECK(args.length() == 1);
49
50 CONVERT_ARG_CHECKED(JSFunction, f, 0);
51 CHECK(f->RemovePrototype());
52 f->shared()->SetConstructStub(
53 *isolate->builtins()->ConstructedNonConstructable());
54
55 return isolate->heap()->undefined_value();
56 }
57
58 // TODO(5530): Remove once uses in debug.js are gone.
RUNTIME_FUNCTION(Runtime_FunctionGetScript)59 RUNTIME_FUNCTION(Runtime_FunctionGetScript) {
60 HandleScope scope(isolate);
61 DCHECK_EQ(1, args.length());
62 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
63
64 if (function->IsJSFunction()) {
65 Handle<Object> script(
66 Handle<JSFunction>::cast(function)->shared()->script(), isolate);
67 if (script->IsScript()) {
68 return *Script::GetWrapper(Handle<Script>::cast(script));
69 }
70 }
71 return isolate->heap()->undefined_value();
72 }
73
RUNTIME_FUNCTION(Runtime_FunctionGetScriptId)74 RUNTIME_FUNCTION(Runtime_FunctionGetScriptId) {
75 HandleScope scope(isolate);
76 DCHECK_EQ(1, args.length());
77 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
78
79 if (function->IsJSFunction()) {
80 Handle<Object> script(
81 Handle<JSFunction>::cast(function)->shared()->script(), isolate);
82 if (script->IsScript()) {
83 return Smi::FromInt(Handle<Script>::cast(script)->id());
84 }
85 }
86 return Smi::FromInt(-1);
87 }
88
RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode)89 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) {
90 HandleScope scope(isolate);
91 DCHECK_EQ(1, args.length());
92 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
93 if (function->IsJSFunction()) {
94 return *Handle<JSFunction>::cast(function)->shared()->GetSourceCode();
95 }
96 return isolate->heap()->undefined_value();
97 }
98
99
RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition)100 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) {
101 SealHandleScope shs(isolate);
102 DCHECK(args.length() == 1);
103
104 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
105 int pos = fun->shared()->start_position();
106 return Smi::FromInt(pos);
107 }
108
RUNTIME_FUNCTION(Runtime_FunctionGetContextData)109 RUNTIME_FUNCTION(Runtime_FunctionGetContextData) {
110 SealHandleScope shs(isolate);
111 DCHECK(args.length() == 1);
112
113 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
114 FixedArray* array = fun->native_context()->embedder_data();
115 return array->get(v8::Context::kDebugIdIndex);
116 }
117
RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName)118 RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName) {
119 SealHandleScope shs(isolate);
120 DCHECK(args.length() == 2);
121
122 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
123 CONVERT_ARG_CHECKED(String, name, 1);
124 fun->shared()->set_instance_class_name(name);
125 return isolate->heap()->undefined_value();
126 }
127
128
RUNTIME_FUNCTION(Runtime_FunctionSetLength)129 RUNTIME_FUNCTION(Runtime_FunctionSetLength) {
130 SealHandleScope shs(isolate);
131 DCHECK(args.length() == 2);
132
133 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
134 CONVERT_SMI_ARG_CHECKED(length, 1);
135 CHECK((length & 0xC0000000) == 0xC0000000 || (length & 0xC0000000) == 0x0);
136 fun->shared()->set_length(length);
137 return isolate->heap()->undefined_value();
138 }
139
140
RUNTIME_FUNCTION(Runtime_FunctionSetPrototype)141 RUNTIME_FUNCTION(Runtime_FunctionSetPrototype) {
142 HandleScope scope(isolate);
143 DCHECK(args.length() == 2);
144
145 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
146 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
147 CHECK(fun->IsConstructor());
148 RETURN_FAILURE_ON_EXCEPTION(isolate,
149 Accessors::FunctionSetPrototype(fun, value));
150 return args[0]; // return TOS
151 }
152
153
RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction)154 RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) {
155 SealHandleScope shs(isolate);
156 DCHECK(args.length() == 1);
157
158 CONVERT_ARG_CHECKED(JSFunction, f, 0);
159 return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
160 }
161
162
RUNTIME_FUNCTION(Runtime_SetCode)163 RUNTIME_FUNCTION(Runtime_SetCode) {
164 HandleScope scope(isolate);
165 DCHECK(args.length() == 2);
166
167 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
168 CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1);
169
170 Handle<SharedFunctionInfo> target_shared(target->shared());
171 Handle<SharedFunctionInfo> source_shared(source->shared());
172
173 if (!Compiler::Compile(source, Compiler::KEEP_EXCEPTION)) {
174 return isolate->heap()->exception();
175 }
176
177 // Mark both, the source and the target, as un-flushable because the
178 // shared unoptimized code makes them impossible to enqueue in a list.
179 DCHECK(target_shared->code()->gc_metadata() == NULL);
180 DCHECK(source_shared->code()->gc_metadata() == NULL);
181 target_shared->set_dont_flush(true);
182 source_shared->set_dont_flush(true);
183
184 // Set the code, scope info, formal parameter count, and the length
185 // of the target shared function info.
186 target_shared->ReplaceCode(source_shared->code());
187 if (source_shared->HasBytecodeArray()) {
188 target_shared->set_bytecode_array(source_shared->bytecode_array());
189 }
190 target_shared->set_scope_info(source_shared->scope_info());
191 target_shared->set_outer_scope_info(source_shared->outer_scope_info());
192 target_shared->set_length(source_shared->length());
193 target_shared->set_num_literals(source_shared->num_literals());
194 target_shared->set_feedback_metadata(source_shared->feedback_metadata());
195 target_shared->set_internal_formal_parameter_count(
196 source_shared->internal_formal_parameter_count());
197 target_shared->set_start_position_and_type(
198 source_shared->start_position_and_type());
199 target_shared->set_end_position(source_shared->end_position());
200 bool was_native = target_shared->native();
201 target_shared->set_compiler_hints(source_shared->compiler_hints());
202 target_shared->set_opt_count_and_bailout_reason(
203 source_shared->opt_count_and_bailout_reason());
204 target_shared->set_native(was_native);
205 target_shared->set_profiler_ticks(source_shared->profiler_ticks());
206 SharedFunctionInfo::SetScript(
207 target_shared, Handle<Object>(source_shared->script(), isolate));
208
209 // Set the code of the target function.
210 target->ReplaceCode(source_shared->code());
211 DCHECK(target->next_function_link()->IsUndefined(isolate));
212
213 Handle<Context> context(source->context());
214 target->set_context(*context);
215
216 // Make sure we get a fresh copy of the literal vector to avoid cross
217 // context contamination, and that the literal vector makes it's way into
218 // the target_shared optimized code map.
219 JSFunction::EnsureLiterals(target);
220
221 if (isolate->logger()->is_logging_code_events() || isolate->is_profiling()) {
222 isolate->logger()->LogExistingFunction(
223 source_shared, Handle<AbstractCode>(source_shared->abstract_code()));
224 }
225
226 return *target;
227 }
228
229
230 // Set the native flag on the function.
231 // This is used to decide if we should transform null and undefined
232 // into the global object when doing call and apply.
RUNTIME_FUNCTION(Runtime_SetNativeFlag)233 RUNTIME_FUNCTION(Runtime_SetNativeFlag) {
234 SealHandleScope shs(isolate);
235 DCHECK_EQ(1, args.length());
236
237 CONVERT_ARG_CHECKED(Object, object, 0);
238
239 if (object->IsJSFunction()) {
240 JSFunction* func = JSFunction::cast(object);
241 func->shared()->set_native(true);
242 }
243 return isolate->heap()->undefined_value();
244 }
245
246
RUNTIME_FUNCTION(Runtime_IsConstructor)247 RUNTIME_FUNCTION(Runtime_IsConstructor) {
248 SealHandleScope shs(isolate);
249 DCHECK_EQ(1, args.length());
250 CONVERT_ARG_CHECKED(Object, object, 0);
251 return isolate->heap()->ToBoolean(object->IsConstructor());
252 }
253
RUNTIME_FUNCTION(Runtime_SetForceInlineFlag)254 RUNTIME_FUNCTION(Runtime_SetForceInlineFlag) {
255 SealHandleScope shs(isolate);
256 DCHECK_EQ(1, args.length());
257 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
258
259 if (object->IsJSFunction()) {
260 JSFunction* func = JSFunction::cast(*object);
261 func->shared()->set_force_inline(true);
262 }
263 return isolate->heap()->undefined_value();
264 }
265
266
RUNTIME_FUNCTION(Runtime_Call)267 RUNTIME_FUNCTION(Runtime_Call) {
268 HandleScope scope(isolate);
269 DCHECK_LE(2, args.length());
270 int const argc = args.length() - 2;
271 CONVERT_ARG_HANDLE_CHECKED(Object, target, 0);
272 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
273 ScopedVector<Handle<Object>> argv(argc);
274 for (int i = 0; i < argc; ++i) {
275 argv[i] = args.at<Object>(2 + i);
276 }
277 RETURN_RESULT_OR_FAILURE(
278 isolate, Execution::Call(isolate, target, receiver, argc, argv.start()));
279 }
280
281
282 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
RUNTIME_FUNCTION(Runtime_ConvertReceiver)283 RUNTIME_FUNCTION(Runtime_ConvertReceiver) {
284 HandleScope scope(isolate);
285 DCHECK(args.length() == 1);
286 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
287 return *Object::ConvertReceiver(isolate, receiver).ToHandleChecked();
288 }
289
290
RUNTIME_FUNCTION(Runtime_IsFunction)291 RUNTIME_FUNCTION(Runtime_IsFunction) {
292 SealHandleScope shs(isolate);
293 DCHECK_EQ(1, args.length());
294 CONVERT_ARG_CHECKED(Object, object, 0);
295 return isolate->heap()->ToBoolean(object->IsFunction());
296 }
297
298
RUNTIME_FUNCTION(Runtime_FunctionToString)299 RUNTIME_FUNCTION(Runtime_FunctionToString) {
300 HandleScope scope(isolate);
301 DCHECK_EQ(1, args.length());
302 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
303 return function->IsJSBoundFunction()
304 ? *JSBoundFunction::ToString(
305 Handle<JSBoundFunction>::cast(function))
306 : *JSFunction::ToString(Handle<JSFunction>::cast(function));
307 }
308
309 } // namespace internal
310 } // namespace v8
311