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/profiler/cpu-profiler.h"
14
15 namespace v8 {
16 namespace internal {
17
RUNTIME_FUNCTION(Runtime_FunctionGetName)18 RUNTIME_FUNCTION(Runtime_FunctionGetName) {
19 SealHandleScope shs(isolate);
20 DCHECK(args.length() == 1);
21
22 CONVERT_ARG_CHECKED(JSFunction, f, 0);
23 return f->shared()->name();
24 }
25
26
RUNTIME_FUNCTION(Runtime_FunctionSetName)27 RUNTIME_FUNCTION(Runtime_FunctionSetName) {
28 HandleScope scope(isolate);
29 DCHECK(args.length() == 2);
30
31 CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
32 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
33
34 name = String::Flatten(name);
35 f->shared()->set_name(*name);
36 return isolate->heap()->undefined_value();
37 }
38
39
RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype)40 RUNTIME_FUNCTION(Runtime_FunctionRemovePrototype) {
41 SealHandleScope shs(isolate);
42 DCHECK(args.length() == 1);
43
44 CONVERT_ARG_CHECKED(JSFunction, f, 0);
45 RUNTIME_ASSERT(f->RemovePrototype());
46 f->shared()->set_construct_stub(
47 *isolate->builtins()->ConstructedNonConstructable());
48
49 return isolate->heap()->undefined_value();
50 }
51
52
RUNTIME_FUNCTION(Runtime_FunctionGetScript)53 RUNTIME_FUNCTION(Runtime_FunctionGetScript) {
54 HandleScope scope(isolate);
55 DCHECK_EQ(1, args.length());
56 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
57
58 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value();
59 Handle<Object> script(Handle<JSFunction>::cast(function)->shared()->script(),
60 isolate);
61 if (!script->IsScript()) return isolate->heap()->undefined_value();
62 return *Script::GetWrapper(Handle<Script>::cast(script));
63 }
64
65
RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode)66 RUNTIME_FUNCTION(Runtime_FunctionGetSourceCode) {
67 HandleScope scope(isolate);
68 DCHECK_EQ(1, args.length());
69 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
70 if (function->IsJSBoundFunction()) return isolate->heap()->undefined_value();
71 return *Handle<JSFunction>::cast(function)->shared()->GetSourceCode();
72 }
73
74
RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition)75 RUNTIME_FUNCTION(Runtime_FunctionGetScriptSourcePosition) {
76 SealHandleScope shs(isolate);
77 DCHECK(args.length() == 1);
78
79 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
80 int pos = fun->shared()->start_position();
81 return Smi::FromInt(pos);
82 }
83
84
RUNTIME_FUNCTION(Runtime_FunctionGetPositionForOffset)85 RUNTIME_FUNCTION(Runtime_FunctionGetPositionForOffset) {
86 SealHandleScope shs(isolate);
87 DCHECK(args.length() == 2);
88
89 CONVERT_ARG_CHECKED(Code, code, 0);
90 CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
91
92 RUNTIME_ASSERT(0 <= offset && offset < code->Size());
93
94 Address pc = code->address() + offset;
95 return Smi::FromInt(code->SourcePosition(pc));
96 }
97
98
RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName)99 RUNTIME_FUNCTION(Runtime_FunctionSetInstanceClassName) {
100 SealHandleScope shs(isolate);
101 DCHECK(args.length() == 2);
102
103 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
104 CONVERT_ARG_CHECKED(String, name, 1);
105 fun->shared()->set_instance_class_name(name);
106 return isolate->heap()->undefined_value();
107 }
108
109
RUNTIME_FUNCTION(Runtime_FunctionSetLength)110 RUNTIME_FUNCTION(Runtime_FunctionSetLength) {
111 SealHandleScope shs(isolate);
112 DCHECK(args.length() == 2);
113
114 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
115 CONVERT_SMI_ARG_CHECKED(length, 1);
116 RUNTIME_ASSERT((length & 0xC0000000) == 0xC0000000 ||
117 (length & 0xC0000000) == 0x0);
118 fun->shared()->set_length(length);
119 return isolate->heap()->undefined_value();
120 }
121
122
RUNTIME_FUNCTION(Runtime_FunctionSetPrototype)123 RUNTIME_FUNCTION(Runtime_FunctionSetPrototype) {
124 HandleScope scope(isolate);
125 DCHECK(args.length() == 2);
126
127 CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
128 CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
129 RUNTIME_ASSERT(fun->IsConstructor());
130 RETURN_FAILURE_ON_EXCEPTION(isolate,
131 Accessors::FunctionSetPrototype(fun, value));
132 return args[0]; // return TOS
133 }
134
135
RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction)136 RUNTIME_FUNCTION(Runtime_FunctionIsAPIFunction) {
137 SealHandleScope shs(isolate);
138 DCHECK(args.length() == 1);
139
140 CONVERT_ARG_CHECKED(JSFunction, f, 0);
141 return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
142 }
143
144
RUNTIME_FUNCTION(Runtime_SetCode)145 RUNTIME_FUNCTION(Runtime_SetCode) {
146 HandleScope scope(isolate);
147 DCHECK(args.length() == 2);
148
149 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
150 CONVERT_ARG_HANDLE_CHECKED(JSFunction, source, 1);
151
152 Handle<SharedFunctionInfo> target_shared(target->shared());
153 Handle<SharedFunctionInfo> source_shared(source->shared());
154
155 if (!Compiler::Compile(source, KEEP_EXCEPTION)) {
156 return isolate->heap()->exception();
157 }
158
159 // Mark both, the source and the target, as un-flushable because the
160 // shared unoptimized code makes them impossible to enqueue in a list.
161 DCHECK(target_shared->code()->gc_metadata() == NULL);
162 DCHECK(source_shared->code()->gc_metadata() == NULL);
163 target_shared->set_dont_flush(true);
164 source_shared->set_dont_flush(true);
165
166 // Set the code, scope info, formal parameter count, and the length
167 // of the target shared function info.
168 target_shared->ReplaceCode(source_shared->code());
169 target_shared->set_scope_info(source_shared->scope_info());
170 target_shared->set_length(source_shared->length());
171 target_shared->set_feedback_vector(source_shared->feedback_vector());
172 target_shared->set_internal_formal_parameter_count(
173 source_shared->internal_formal_parameter_count());
174 target_shared->set_start_position_and_type(
175 source_shared->start_position_and_type());
176 target_shared->set_end_position(source_shared->end_position());
177 bool was_native = target_shared->native();
178 target_shared->set_compiler_hints(source_shared->compiler_hints());
179 target_shared->set_opt_count_and_bailout_reason(
180 source_shared->opt_count_and_bailout_reason());
181 target_shared->set_native(was_native);
182 target_shared->set_profiler_ticks(source_shared->profiler_ticks());
183 SharedFunctionInfo::SetScript(
184 target_shared, Handle<Object>(source_shared->script(), isolate));
185
186 // Set the code of the target function.
187 target->ReplaceCode(source_shared->code());
188 DCHECK(target->next_function_link()->IsUndefined());
189
190 // Make sure we get a fresh copy of the literal vector to avoid cross
191 // context contamination.
192 Handle<Context> context(source->context());
193 target->set_context(*context);
194
195 int number_of_literals = source->NumberOfLiterals();
196 Handle<LiteralsArray> literals =
197 LiteralsArray::New(isolate, handle(target_shared->feedback_vector()),
198 number_of_literals, TENURED);
199 target->set_literals(*literals);
200
201 if (isolate->logger()->is_logging_code_events() ||
202 isolate->cpu_profiler()->is_profiling()) {
203 isolate->logger()->LogExistingFunction(source_shared,
204 Handle<Code>(source_shared->code()));
205 }
206
207 return *target;
208 }
209
210
211 // Set the native flag on the function.
212 // This is used to decide if we should transform null and undefined
213 // into the global object when doing call and apply.
RUNTIME_FUNCTION(Runtime_SetNativeFlag)214 RUNTIME_FUNCTION(Runtime_SetNativeFlag) {
215 SealHandleScope shs(isolate);
216 RUNTIME_ASSERT(args.length() == 1);
217
218 CONVERT_ARG_CHECKED(Object, object, 0);
219
220 if (object->IsJSFunction()) {
221 JSFunction* func = JSFunction::cast(object);
222 func->shared()->set_native(true);
223 }
224 return isolate->heap()->undefined_value();
225 }
226
227
RUNTIME_FUNCTION(Runtime_IsConstructor)228 RUNTIME_FUNCTION(Runtime_IsConstructor) {
229 SealHandleScope shs(isolate);
230 DCHECK_EQ(1, args.length());
231 CONVERT_ARG_CHECKED(Object, object, 0);
232 return isolate->heap()->ToBoolean(object->IsConstructor());
233 }
234
235
RUNTIME_FUNCTION(Runtime_SetForceInlineFlag)236 RUNTIME_FUNCTION(Runtime_SetForceInlineFlag) {
237 SealHandleScope shs(isolate);
238 RUNTIME_ASSERT(args.length() == 1);
239 CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
240
241 if (object->IsJSFunction()) {
242 JSFunction* func = JSFunction::cast(*object);
243 func->shared()->set_force_inline(true);
244 }
245 return isolate->heap()->undefined_value();
246 }
247
248
RUNTIME_FUNCTION(Runtime_Call)249 RUNTIME_FUNCTION(Runtime_Call) {
250 HandleScope scope(isolate);
251 DCHECK_LE(2, args.length());
252 int const argc = args.length() - 2;
253 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, target, 0);
254 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
255 ScopedVector<Handle<Object>> argv(argc);
256 for (int i = 0; i < argc; ++i) {
257 argv[i] = args.at<Object>(2 + i);
258 }
259 Handle<Object> result;
260 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
261 isolate, result,
262 Execution::Call(isolate, target, receiver, argc, argv.start()));
263 return *result;
264 }
265
266
RUNTIME_FUNCTION(Runtime_TailCall)267 RUNTIME_FUNCTION(Runtime_TailCall) {
268 HandleScope scope(isolate);
269 DCHECK_LE(2, args.length());
270 int const argc = args.length() - 2;
271 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, 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 Handle<Object> result;
278 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
279 isolate, result,
280 Execution::Call(isolate, target, receiver, argc, argv.start()));
281 return *result;
282 }
283
284
RUNTIME_FUNCTION(Runtime_Apply)285 RUNTIME_FUNCTION(Runtime_Apply) {
286 HandleScope scope(isolate);
287 DCHECK(args.length() == 5);
288 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
289 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 1);
290 CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
291 CONVERT_INT32_ARG_CHECKED(offset, 3);
292 CONVERT_INT32_ARG_CHECKED(argc, 4);
293 RUNTIME_ASSERT(offset >= 0);
294 // Loose upper bound to allow fuzzing. We'll most likely run out of
295 // stack space before hitting this limit.
296 static int kMaxArgc = 1000000;
297 RUNTIME_ASSERT(argc >= 0 && argc <= kMaxArgc);
298
299 // If there are too many arguments, allocate argv via malloc.
300 const int argv_small_size = 10;
301 Handle<Object> argv_small_buffer[argv_small_size];
302 base::SmartArrayPointer<Handle<Object> > argv_large_buffer;
303 Handle<Object>* argv = argv_small_buffer;
304 if (argc > argv_small_size) {
305 argv = new Handle<Object>[argc];
306 if (argv == NULL) return isolate->StackOverflow();
307 argv_large_buffer = base::SmartArrayPointer<Handle<Object> >(argv);
308 }
309
310 for (int i = 0; i < argc; ++i) {
311 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
312 isolate, argv[i], Object::GetElement(isolate, arguments, offset + i));
313 }
314
315 Handle<Object> result;
316 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
317 isolate, result, Execution::Call(isolate, fun, receiver, argc, argv));
318 return *result;
319 }
320
321
322 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
RUNTIME_FUNCTION(Runtime_ConvertReceiver)323 RUNTIME_FUNCTION(Runtime_ConvertReceiver) {
324 HandleScope scope(isolate);
325 DCHECK(args.length() == 1);
326 CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
327 if (receiver->IsNull() || receiver->IsUndefined()) {
328 return isolate->global_proxy();
329 }
330 return *Object::ToObject(isolate, receiver).ToHandleChecked();
331 }
332
333
RUNTIME_FUNCTION(Runtime_IsFunction)334 RUNTIME_FUNCTION(Runtime_IsFunction) {
335 SealHandleScope shs(isolate);
336 DCHECK_EQ(1, args.length());
337 CONVERT_ARG_CHECKED(Object, object, 0);
338 return isolate->heap()->ToBoolean(object->IsFunction());
339 }
340
341
RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments)342 RUNTIME_FUNCTION(Runtime_ThrowStrongModeTooFewArguments) {
343 HandleScope scope(isolate);
344 DCHECK(args.length() == 0);
345 THROW_NEW_ERROR_RETURN_FAILURE(isolate,
346 NewTypeError(MessageTemplate::kStrongArity));
347 }
348
349
RUNTIME_FUNCTION(Runtime_FunctionToString)350 RUNTIME_FUNCTION(Runtime_FunctionToString) {
351 HandleScope scope(isolate);
352 DCHECK_EQ(1, args.length());
353 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, function, 0);
354 return function->IsJSBoundFunction()
355 ? *JSBoundFunction::ToString(
356 Handle<JSBoundFunction>::cast(function))
357 : *JSFunction::ToString(Handle<JSFunction>::cast(function));
358 }
359
360 } // namespace internal
361 } // namespace v8
362