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