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