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