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