deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / src / runtime / runtime-internal.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/bootstrapper.h"
9 #include "src/debug.h"
10 #include "src/messages.h"
11 #include "src/parser.h"
12 #include "src/prettyprinter.h"
13 #include "src/runtime/runtime-utils.h"
14
15 namespace v8 {
16 namespace internal {
17
18 RUNTIME_FUNCTION(Runtime_CheckIsBootstrapping) {
19   SealHandleScope shs(isolate);
20   DCHECK(args.length() == 0);
21   RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
22   return isolate->heap()->undefined_value();
23 }
24
25
26 RUNTIME_FUNCTION(Runtime_Throw) {
27   HandleScope scope(isolate);
28   DCHECK(args.length() == 1);
29   return isolate->Throw(args[0]);
30 }
31
32
33 RUNTIME_FUNCTION(Runtime_ReThrow) {
34   HandleScope scope(isolate);
35   DCHECK(args.length() == 1);
36   return isolate->ReThrow(args[0]);
37 }
38
39
40 RUNTIME_FUNCTION(Runtime_FindExceptionHandler) {
41   SealHandleScope shs(isolate);
42   DCHECK(args.length() == 0);
43   return isolate->FindHandler();
44 }
45
46
47 RUNTIME_FUNCTION(Runtime_PromoteScheduledException) {
48   SealHandleScope shs(isolate);
49   DCHECK(args.length() == 0);
50   return isolate->PromoteScheduledException();
51 }
52
53
54 RUNTIME_FUNCTION(Runtime_ThrowReferenceError) {
55   HandleScope scope(isolate);
56   DCHECK(args.length() == 1);
57   CONVERT_ARG_HANDLE_CHECKED(Object, name, 0);
58   THROW_NEW_ERROR_RETURN_FAILURE(
59       isolate, NewReferenceError("not_defined", HandleVector(&name, 1)));
60 }
61
62
63 RUNTIME_FUNCTION(Runtime_ThrowIteratorResultNotAnObject) {
64   HandleScope scope(isolate);
65   DCHECK(args.length() == 1);
66   CONVERT_ARG_HANDLE_CHECKED(Object, value, 0);
67   THROW_NEW_ERROR_RETURN_FAILURE(
68       isolate,
69       NewTypeError("iterator_result_not_an_object", HandleVector(&value, 1)));
70 }
71
72
73 RUNTIME_FUNCTION(Runtime_PromiseRejectEvent) {
74   DCHECK(args.length() == 3);
75   HandleScope scope(isolate);
76   CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
77   CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
78   CONVERT_BOOLEAN_ARG_CHECKED(debug_event, 2);
79   if (debug_event) isolate->debug()->OnPromiseReject(promise, value);
80   Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol();
81   // Do not report if we actually have a handler.
82   if (JSObject::GetDataProperty(promise, key)->IsUndefined()) {
83     isolate->ReportPromiseReject(promise, value,
84                                  v8::kPromiseRejectWithNoHandler);
85   }
86   return isolate->heap()->undefined_value();
87 }
88
89
90 RUNTIME_FUNCTION(Runtime_PromiseRevokeReject) {
91   DCHECK(args.length() == 1);
92   HandleScope scope(isolate);
93   CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0);
94   Handle<Symbol> key = isolate->factory()->promise_has_handler_symbol();
95   // At this point, no revocation has been issued before
96   RUNTIME_ASSERT(JSObject::GetDataProperty(promise, key)->IsUndefined());
97   isolate->ReportPromiseReject(promise, Handle<Object>(),
98                                v8::kPromiseHandlerAddedAfterReject);
99   return isolate->heap()->undefined_value();
100 }
101
102
103 RUNTIME_FUNCTION(Runtime_PromiseHasHandlerSymbol) {
104   DCHECK(args.length() == 0);
105   return isolate->heap()->promise_has_handler_symbol();
106 }
107
108
109 RUNTIME_FUNCTION(Runtime_StackGuard) {
110   SealHandleScope shs(isolate);
111   DCHECK(args.length() == 0);
112
113   // First check if this is a real stack overflow.
114   StackLimitCheck check(isolate);
115   if (check.JsHasOverflowed()) {
116     return isolate->StackOverflow();
117   }
118
119   return isolate->stack_guard()->HandleInterrupts();
120 }
121
122
123 RUNTIME_FUNCTION(Runtime_Interrupt) {
124   SealHandleScope shs(isolate);
125   DCHECK(args.length() == 0);
126   return isolate->stack_guard()->HandleInterrupts();
127 }
128
129
130 RUNTIME_FUNCTION(Runtime_AllocateInNewSpace) {
131   HandleScope scope(isolate);
132   DCHECK(args.length() == 1);
133   CONVERT_SMI_ARG_CHECKED(size, 0);
134   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
135   RUNTIME_ASSERT(size > 0);
136   RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
137   return *isolate->factory()->NewFillerObject(size, false, NEW_SPACE);
138 }
139
140
141 RUNTIME_FUNCTION(Runtime_AllocateInTargetSpace) {
142   HandleScope scope(isolate);
143   DCHECK(args.length() == 2);
144   CONVERT_SMI_ARG_CHECKED(size, 0);
145   CONVERT_SMI_ARG_CHECKED(flags, 1);
146   RUNTIME_ASSERT(IsAligned(size, kPointerSize));
147   RUNTIME_ASSERT(size > 0);
148   RUNTIME_ASSERT(size <= Page::kMaxRegularHeapObjectSize);
149   bool double_align = AllocateDoubleAlignFlag::decode(flags);
150   AllocationSpace space = AllocateTargetSpace::decode(flags);
151   return *isolate->factory()->NewFillerObject(size, double_align, space);
152 }
153
154
155 // Collect the raw data for a stack trace.  Returns an array of 4
156 // element segments each containing a receiver, function, code and
157 // native code offset.
158 RUNTIME_FUNCTION(Runtime_CollectStackTrace) {
159   HandleScope scope(isolate);
160   DCHECK(args.length() == 2);
161   CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
162   CONVERT_ARG_HANDLE_CHECKED(Object, caller, 1);
163
164   if (!isolate->bootstrapper()->IsActive()) {
165     // Optionally capture a more detailed stack trace for the message.
166     isolate->CaptureAndSetDetailedStackTrace(error_object);
167     // Capture a simple stack trace for the stack property.
168     isolate->CaptureAndSetSimpleStackTrace(error_object, caller);
169   }
170   return isolate->heap()->undefined_value();
171 }
172
173
174 RUNTIME_FUNCTION(Runtime_RenderCallSite) {
175   HandleScope scope(isolate);
176   DCHECK(args.length() == 0);
177   MessageLocation location;
178   isolate->ComputeLocation(&location);
179   if (location.start_pos() == -1) return isolate->heap()->empty_string();
180
181   Zone zone;
182   SmartPointer<ParseInfo> info(location.function()->shared()->is_function()
183                                    ? new ParseInfo(&zone, location.function())
184                                    : new ParseInfo(&zone, location.script()));
185
186   if (!Parser::ParseStatic(info.get())) {
187     isolate->clear_pending_exception();
188     return isolate->heap()->empty_string();
189   }
190   CallPrinter printer(isolate, &zone);
191   const char* string = printer.Print(info->function(), location.start_pos());
192   return *isolate->factory()->NewStringFromAsciiChecked(string);
193 }
194
195
196 RUNTIME_FUNCTION(Runtime_GetFromCacheRT) {
197   SealHandleScope shs(isolate);
198   // This is only called from codegen, so checks might be more lax.
199   CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
200   CONVERT_ARG_CHECKED(Object, key, 1);
201
202   {
203     DisallowHeapAllocation no_alloc;
204
205     int finger_index = cache->finger_index();
206     Object* o = cache->get(finger_index);
207     if (o == key) {
208       // The fastest case: hit the same place again.
209       return cache->get(finger_index + 1);
210     }
211
212     for (int i = finger_index - 2; i >= JSFunctionResultCache::kEntriesIndex;
213          i -= 2) {
214       o = cache->get(i);
215       if (o == key) {
216         cache->set_finger_index(i);
217         return cache->get(i + 1);
218       }
219     }
220
221     int size = cache->size();
222     DCHECK(size <= cache->length());
223
224     for (int i = size - 2; i > finger_index; i -= 2) {
225       o = cache->get(i);
226       if (o == key) {
227         cache->set_finger_index(i);
228         return cache->get(i + 1);
229       }
230     }
231   }
232
233   // There is no value in the cache.  Invoke the function and cache result.
234   HandleScope scope(isolate);
235
236   Handle<JSFunctionResultCache> cache_handle(cache);
237   Handle<Object> key_handle(key, isolate);
238   Handle<Object> value;
239   {
240     Handle<JSFunction> factory(JSFunction::cast(
241         cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
242     // TODO(antonm): consider passing a receiver when constructing a cache.
243     Handle<JSObject> receiver(isolate->global_proxy());
244     // This handle is nor shared, nor used later, so it's safe.
245     Handle<Object> argv[] = {key_handle};
246     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
247         isolate, value,
248         Execution::Call(isolate, factory, receiver, arraysize(argv), argv));
249   }
250
251 #ifdef VERIFY_HEAP
252   if (FLAG_verify_heap) {
253     cache_handle->JSFunctionResultCacheVerify();
254   }
255 #endif
256
257   // Function invocation may have cleared the cache.  Reread all the data.
258   int finger_index = cache_handle->finger_index();
259   int size = cache_handle->size();
260
261   // If we have spare room, put new data into it, otherwise evict post finger
262   // entry which is likely to be the least recently used.
263   int index = -1;
264   if (size < cache_handle->length()) {
265     cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
266     index = size;
267   } else {
268     index = finger_index + JSFunctionResultCache::kEntrySize;
269     if (index == cache_handle->length()) {
270       index = JSFunctionResultCache::kEntriesIndex;
271     }
272   }
273
274   DCHECK(index % 2 == 0);
275   DCHECK(index >= JSFunctionResultCache::kEntriesIndex);
276   DCHECK(index < cache_handle->length());
277
278   cache_handle->set(index, *key_handle);
279   cache_handle->set(index + 1, *value);
280   cache_handle->set_finger_index(index);
281
282 #ifdef VERIFY_HEAP
283   if (FLAG_verify_heap) {
284     cache_handle->JSFunctionResultCacheVerify();
285   }
286 #endif
287
288   return *value;
289 }
290
291
292 RUNTIME_FUNCTION(Runtime_MessageGetStartPosition) {
293   SealHandleScope shs(isolate);
294   DCHECK(args.length() == 1);
295   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
296   return Smi::FromInt(message->start_position());
297 }
298
299
300 RUNTIME_FUNCTION(Runtime_MessageGetScript) {
301   SealHandleScope shs(isolate);
302   DCHECK(args.length() == 1);
303   CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
304   return message->script();
305 }
306
307
308 RUNTIME_FUNCTION(Runtime_IS_VAR) {
309   UNREACHABLE();  // implemented as macro in the parser
310   return NULL;
311 }
312
313
314 RUNTIME_FUNCTION(Runtime_GetFromCache) {
315   HandleScope scope(isolate);
316   DCHECK(args.length() == 2);
317   CONVERT_SMI_ARG_CHECKED(id, 0);
318   args[0] = isolate->native_context()->jsfunction_result_caches()->get(id);
319   return __RT_impl_Runtime_GetFromCacheRT(args, isolate);
320 }
321
322
323 RUNTIME_FUNCTION(Runtime_IncrementStatsCounter) {
324   SealHandleScope shs(isolate);
325   DCHECK(args.length() == 1);
326   CONVERT_ARG_CHECKED(String, name, 0);
327
328   if (FLAG_native_code_counters) {
329     StatsCounter(isolate, name->ToCString().get()).Increment();
330   }
331   return isolate->heap()->undefined_value();
332 }
333 }
334 }  // namespace v8::internal