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