• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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