89e1f2a69662fee8051345cdcc86e6047990c145
[platform/upstream/nodejs.git] / deps / v8 / src / runtime / runtime-test.cc
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/v8.h"
6
7 #include "src/arguments.h"
8 #include "src/deoptimizer.h"
9 #include "src/full-codegen.h"
10 #include "src/natives.h"
11 #include "src/runtime/runtime-utils.h"
12
13 namespace v8 {
14 namespace internal {
15
16 RUNTIME_FUNCTION(Runtime_DeoptimizeFunction) {
17   HandleScope scope(isolate);
18   DCHECK(args.length() == 1);
19   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
20   if (!function->IsOptimized()) return isolate->heap()->undefined_value();
21
22   // TODO(turbofan): Deoptimization is not supported yet.
23   if (function->code()->is_turbofanned() && !FLAG_turbo_deoptimization) {
24     return isolate->heap()->undefined_value();
25   }
26
27   Deoptimizer::DeoptimizeFunction(*function);
28
29   return isolate->heap()->undefined_value();
30 }
31
32
33 RUNTIME_FUNCTION(Runtime_RunningInSimulator) {
34   SealHandleScope shs(isolate);
35   DCHECK(args.length() == 0);
36 #if defined(USE_SIMULATOR)
37   return isolate->heap()->true_value();
38 #else
39   return isolate->heap()->false_value();
40 #endif
41 }
42
43
44 RUNTIME_FUNCTION(Runtime_IsConcurrentRecompilationSupported) {
45   SealHandleScope shs(isolate);
46   DCHECK(args.length() == 0);
47   return isolate->heap()->ToBoolean(
48       isolate->concurrent_recompilation_enabled());
49 }
50
51
52 RUNTIME_FUNCTION(Runtime_OptimizeFunctionOnNextCall) {
53   HandleScope scope(isolate);
54   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
55   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
56   // The following assertion was lifted from the DCHECK inside
57   // JSFunction::MarkForOptimization().
58   RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
59                  (function->code()->kind() == Code::FUNCTION &&
60                   function->code()->optimizable()));
61
62   if (!isolate->use_crankshaft()) return isolate->heap()->undefined_value();
63
64   // If the function is already optimized, just return.
65   if (function->IsOptimized()) return isolate->heap()->undefined_value();
66
67   function->MarkForOptimization();
68
69   Code* unoptimized = function->shared()->code();
70   if (args.length() == 2 && unoptimized->kind() == Code::FUNCTION) {
71     CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
72     if (type->IsOneByteEqualTo(STATIC_CHAR_VECTOR("concurrent")) &&
73         isolate->concurrent_recompilation_enabled()) {
74       function->AttemptConcurrentOptimization();
75     }
76   }
77
78   return isolate->heap()->undefined_value();
79 }
80
81
82 RUNTIME_FUNCTION(Runtime_OptimizeOsr) {
83   HandleScope scope(isolate);
84   RUNTIME_ASSERT(args.length() == 0);
85   Handle<JSFunction> function = Handle<JSFunction>::null();
86
87   {
88     // Find the JavaScript function on the top of the stack.
89     JavaScriptFrameIterator it(isolate);
90     while (!it.done()) {
91       if (it.frame()->is_java_script()) {
92         function = Handle<JSFunction>(it.frame()->function());
93         break;
94       }
95     }
96     if (function.is_null()) return isolate->heap()->undefined_value();
97   }
98
99   // The following assertion was lifted from the DCHECK inside
100   // JSFunction::MarkForOptimization().
101   RUNTIME_ASSERT(function->shared()->allows_lazy_compilation() ||
102                  (function->code()->kind() == Code::FUNCTION &&
103                   function->code()->optimizable()));
104
105   if (!isolate->use_crankshaft()) return isolate->heap()->undefined_value();
106
107   // If the function is already optimized, just return.
108   if (function->IsOptimized()) return isolate->heap()->undefined_value();
109
110   Code* unoptimized = function->shared()->code();
111   if (unoptimized->kind() == Code::FUNCTION) {
112     DCHECK(BackEdgeTable::Verify(isolate, unoptimized));
113     isolate->runtime_profiler()->AttemptOnStackReplacement(
114         *function, Code::kMaxLoopNestingMarker);
115   }
116
117   return isolate->heap()->undefined_value();
118 }
119
120
121 RUNTIME_FUNCTION(Runtime_NeverOptimizeFunction) {
122   HandleScope scope(isolate);
123   DCHECK(args.length() == 1);
124   CONVERT_ARG_CHECKED(JSFunction, function, 0);
125   function->shared()->set_disable_optimization_reason(kOptimizationDisabled);
126   function->shared()->set_optimization_disabled(true);
127   return isolate->heap()->undefined_value();
128 }
129
130
131 RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
132   HandleScope scope(isolate);
133   RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
134   if (!isolate->use_crankshaft()) {
135     return Smi::FromInt(4);  // 4 == "never".
136   }
137   bool sync_with_compiler_thread = true;
138   if (args.length() == 2) {
139     CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
140     if (sync->IsOneByteEqualTo(STATIC_CHAR_VECTOR("no sync"))) {
141       sync_with_compiler_thread = false;
142     }
143   }
144   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
145   if (isolate->concurrent_recompilation_enabled() &&
146       sync_with_compiler_thread) {
147     while (function->IsInOptimizationQueue()) {
148       isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
149       base::OS::Sleep(50);
150     }
151   }
152   if (FLAG_always_opt) {
153     // We may have always opt, but that is more best-effort than a real
154     // promise, so we still say "no" if it is not optimized.
155     return function->IsOptimized() ? Smi::FromInt(3)   // 3 == "always".
156                                    : Smi::FromInt(2);  // 2 == "no".
157   }
158   if (FLAG_deopt_every_n_times) {
159     return Smi::FromInt(6);  // 6 == "maybe deopted".
160   }
161   if (function->IsOptimized() && function->code()->is_turbofanned()) {
162     return Smi::FromInt(7);  // 7 == "TurboFan compiler".
163   }
164   return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
165                                  : Smi::FromInt(2);  // 2 == "no".
166 }
167
168
169 RUNTIME_FUNCTION(Runtime_UnblockConcurrentRecompilation) {
170   DCHECK(args.length() == 0);
171   RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
172   RUNTIME_ASSERT(isolate->concurrent_recompilation_enabled());
173   isolate->optimizing_compiler_thread()->Unblock();
174   return isolate->heap()->undefined_value();
175 }
176
177
178 RUNTIME_FUNCTION(Runtime_GetOptimizationCount) {
179   HandleScope scope(isolate);
180   DCHECK(args.length() == 1);
181   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
182   return Smi::FromInt(function->shared()->opt_count());
183 }
184
185
186 RUNTIME_FUNCTION(Runtime_ClearFunctionTypeFeedback) {
187   HandleScope scope(isolate);
188   DCHECK(args.length() == 1);
189   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
190   function->shared()->ClearTypeFeedbackInfo();
191   Code* unoptimized = function->shared()->code();
192   if (unoptimized->kind() == Code::FUNCTION) {
193     unoptimized->ClearInlineCaches();
194   }
195   return isolate->heap()->undefined_value();
196 }
197
198
199 RUNTIME_FUNCTION(Runtime_NotifyContextDisposed) {
200   HandleScope scope(isolate);
201   DCHECK(args.length() == 0);
202   isolate->heap()->NotifyContextDisposed(true);
203   return isolate->heap()->undefined_value();
204 }
205
206
207 RUNTIME_FUNCTION(Runtime_SetAllocationTimeout) {
208   SealHandleScope shs(isolate);
209   DCHECK(args.length() == 2 || args.length() == 3);
210 #ifdef DEBUG
211   CONVERT_SMI_ARG_CHECKED(interval, 0);
212   CONVERT_SMI_ARG_CHECKED(timeout, 1);
213   isolate->heap()->set_allocation_timeout(timeout);
214   FLAG_gc_interval = interval;
215   if (args.length() == 3) {
216     // Enable/disable inline allocation if requested.
217     CONVERT_BOOLEAN_ARG_CHECKED(inline_allocation, 2);
218     if (inline_allocation) {
219       isolate->heap()->EnableInlineAllocation();
220     } else {
221       isolate->heap()->DisableInlineAllocation();
222     }
223   }
224 #endif
225   return isolate->heap()->undefined_value();
226 }
227
228
229 RUNTIME_FUNCTION(Runtime_DebugPrint) {
230   SealHandleScope shs(isolate);
231   DCHECK(args.length() == 1);
232
233   OFStream os(stdout);
234 #ifdef DEBUG
235   if (args[0]->IsString()) {
236     // If we have a string, assume it's a code "marker"
237     // and print some interesting cpu debugging info.
238     JavaScriptFrameIterator it(isolate);
239     JavaScriptFrame* frame = it.frame();
240     os << "fp = " << frame->fp() << ", sp = " << frame->sp()
241        << ", caller_sp = " << frame->caller_sp() << ": ";
242   } else {
243     os << "DebugPrint: ";
244   }
245   args[0]->Print(os);
246   if (args[0]->IsHeapObject()) {
247     os << "\n";
248     HeapObject::cast(args[0])->map()->Print(os);
249   }
250 #else
251   // ShortPrint is available in release mode. Print is not.
252   os << Brief(args[0]);
253 #endif
254   os << std::endl;
255
256   return args[0];  // return TOS
257 }
258
259
260 RUNTIME_FUNCTION(Runtime_DebugTrace) {
261   SealHandleScope shs(isolate);
262   DCHECK(args.length() == 0);
263   isolate->PrintStack(stdout);
264   return isolate->heap()->undefined_value();
265 }
266
267
268 // This will not allocate (flatten the string), but it may run
269 // very slowly for very deeply nested ConsStrings.  For debugging use only.
270 RUNTIME_FUNCTION(Runtime_GlobalPrint) {
271   SealHandleScope shs(isolate);
272   DCHECK(args.length() == 1);
273
274   CONVERT_ARG_CHECKED(String, string, 0);
275   StringCharacterStream stream(string);
276   while (stream.HasMore()) {
277     uint16_t character = stream.GetNext();
278     PrintF("%c", character);
279   }
280   return string;
281 }
282
283
284 RUNTIME_FUNCTION(Runtime_SystemBreak) {
285   // The code below doesn't create handles, but when breaking here in GDB
286   // having a handle scope might be useful.
287   HandleScope scope(isolate);
288   DCHECK(args.length() == 0);
289   base::OS::DebugBreak();
290   return isolate->heap()->undefined_value();
291 }
292
293
294 // Sets a v8 flag.
295 RUNTIME_FUNCTION(Runtime_SetFlags) {
296   SealHandleScope shs(isolate);
297   DCHECK(args.length() == 1);
298   CONVERT_ARG_CHECKED(String, arg, 0);
299   SmartArrayPointer<char> flags =
300       arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
301   FlagList::SetFlagsFromString(flags.get(), StrLength(flags.get()));
302   return isolate->heap()->undefined_value();
303 }
304
305
306 RUNTIME_FUNCTION(Runtime_Abort) {
307   SealHandleScope shs(isolate);
308   DCHECK(args.length() == 1);
309   CONVERT_SMI_ARG_CHECKED(message_id, 0);
310   const char* message =
311       GetBailoutReason(static_cast<BailoutReason>(message_id));
312   base::OS::PrintError("abort: %s\n", message);
313   isolate->PrintStack(stderr);
314   base::OS::Abort();
315   UNREACHABLE();
316   return NULL;
317 }
318
319
320 RUNTIME_FUNCTION(Runtime_AbortJS) {
321   HandleScope scope(isolate);
322   DCHECK(args.length() == 1);
323   CONVERT_ARG_HANDLE_CHECKED(String, message, 0);
324   base::OS::PrintError("abort: %s\n", message->ToCString().get());
325   isolate->PrintStack(stderr);
326   base::OS::Abort();
327   UNREACHABLE();
328   return NULL;
329 }
330
331
332 RUNTIME_FUNCTION(Runtime_NativeScriptsCount) {
333   DCHECK(args.length() == 0);
334   return Smi::FromInt(Natives::GetBuiltinsCount());
335 }
336
337
338 // Returns V8 version as a string.
339 RUNTIME_FUNCTION(Runtime_GetV8Version) {
340   HandleScope scope(isolate);
341   DCHECK(args.length() == 0);
342
343   const char* version_string = v8::V8::GetVersion();
344
345   return *isolate->factory()->NewStringFromAsciiChecked(version_string);
346 }
347
348
349 static int StackSize(Isolate* isolate) {
350   int n = 0;
351   for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
352   return n;
353 }
354
355
356 static void PrintTransition(Isolate* isolate, Object* result) {
357   // indentation
358   {
359     const int nmax = 80;
360     int n = StackSize(isolate);
361     if (n <= nmax)
362       PrintF("%4d:%*s", n, n, "");
363     else
364       PrintF("%4d:%*s", n, nmax, "...");
365   }
366
367   if (result == NULL) {
368     JavaScriptFrame::PrintTop(isolate, stdout, true, false);
369     PrintF(" {\n");
370   } else {
371     // function result
372     PrintF("} -> ");
373     result->ShortPrint();
374     PrintF("\n");
375   }
376 }
377
378
379 RUNTIME_FUNCTION(Runtime_TraceEnter) {
380   SealHandleScope shs(isolate);
381   DCHECK(args.length() == 0);
382   PrintTransition(isolate, NULL);
383   return isolate->heap()->undefined_value();
384 }
385
386
387 RUNTIME_FUNCTION(Runtime_TraceExit) {
388   SealHandleScope shs(isolate);
389   DCHECK(args.length() == 1);
390   CONVERT_ARG_CHECKED(Object, obj, 0);
391   PrintTransition(isolate, obj);
392   return obj;  // return TOS
393 }
394
395
396 RUNTIME_FUNCTION(Runtime_HaveSameMap) {
397   SealHandleScope shs(isolate);
398   DCHECK(args.length() == 2);
399   CONVERT_ARG_CHECKED(JSObject, obj1, 0);
400   CONVERT_ARG_CHECKED(JSObject, obj2, 1);
401   return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
402 }
403
404
405 #define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)       \
406   RUNTIME_FUNCTION(Runtime_Has##Name) {                  \
407     CONVERT_ARG_CHECKED(JSObject, obj, 0);               \
408     return isolate->heap()->ToBoolean(obj->Has##Name()); \
409   }
410
411 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
412 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
413 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
414 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
415 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
416 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
417 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(SloppyArgumentsElements)
418 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
419 // Properties test sitting with elements tests - not fooling anyone.
420 ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
421
422 #undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
423
424
425 #define TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, size) \
426   RUNTIME_FUNCTION(Runtime_HasExternal##Type##Elements) {                  \
427     CONVERT_ARG_CHECKED(JSObject, obj, 0);                                 \
428     return isolate->heap()->ToBoolean(obj->HasExternal##Type##Elements()); \
429   }
430
431 TYPED_ARRAYS(TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
432
433 #undef TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
434
435
436 #define FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION(Type, type, TYPE, ctype, s) \
437   RUNTIME_FUNCTION(Runtime_HasFixed##Type##Elements) {                        \
438     CONVERT_ARG_CHECKED(JSObject, obj, 0);                                    \
439     return isolate->heap()->ToBoolean(obj->HasFixed##Type##Elements());       \
440   }
441
442 TYPED_ARRAYS(FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION)
443
444 #undef FIXED_TYPED_ARRAYS_CHECK_RUNTIME_FUNCTION
445 }
446 }  // namespace v8::internal