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