OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/debug/debug.h" | 9 #include "src/debug/debug.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 if (!Parser::ParseStatic(info.get())) { | 230 if (!Parser::ParseStatic(info.get())) { |
231 isolate->clear_pending_exception(); | 231 isolate->clear_pending_exception(); |
232 return isolate->heap()->empty_string(); | 232 return isolate->heap()->empty_string(); |
233 } | 233 } |
234 CallPrinter printer(isolate, &zone); | 234 CallPrinter printer(isolate, &zone); |
235 const char* string = printer.Print(info->function(), location.start_pos()); | 235 const char* string = printer.Print(info->function(), location.start_pos()); |
236 return *isolate->factory()->NewStringFromAsciiChecked(string); | 236 return *isolate->factory()->NewStringFromAsciiChecked(string); |
237 } | 237 } |
238 | 238 |
239 | 239 |
240 RUNTIME_FUNCTION(Runtime_GetFromCacheRT) { | |
241 SealHandleScope shs(isolate); | |
242 // This is only called from codegen, so checks might be more lax. | |
243 CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0); | |
244 CONVERT_ARG_CHECKED(Object, key, 1); | |
245 | |
246 { | |
247 DisallowHeapAllocation no_alloc; | |
248 | |
249 int finger_index = cache->finger_index(); | |
250 Object* o = cache->get(finger_index); | |
251 if (o == key) { | |
252 // The fastest case: hit the same place again. | |
253 return cache->get(finger_index + 1); | |
254 } | |
255 | |
256 for (int i = finger_index - 2; i >= JSFunctionResultCache::kEntriesIndex; | |
257 i -= 2) { | |
258 o = cache->get(i); | |
259 if (o == key) { | |
260 cache->set_finger_index(i); | |
261 return cache->get(i + 1); | |
262 } | |
263 } | |
264 | |
265 int size = cache->size(); | |
266 DCHECK(size <= cache->length()); | |
267 | |
268 for (int i = size - 2; i > finger_index; i -= 2) { | |
269 o = cache->get(i); | |
270 if (o == key) { | |
271 cache->set_finger_index(i); | |
272 return cache->get(i + 1); | |
273 } | |
274 } | |
275 } | |
276 | |
277 // There is no value in the cache. Invoke the function and cache result. | |
278 HandleScope scope(isolate); | |
279 | |
280 Handle<JSFunctionResultCache> cache_handle(cache); | |
281 Handle<Object> key_handle(key, isolate); | |
282 Handle<Object> value; | |
283 { | |
284 Handle<JSFunction> factory(JSFunction::cast( | |
285 cache_handle->get(JSFunctionResultCache::kFactoryIndex))); | |
286 // TODO(antonm): consider passing a receiver when constructing a cache. | |
287 Handle<JSObject> receiver(isolate->global_proxy()); | |
288 // This handle is nor shared, nor used later, so it's safe. | |
289 Handle<Object> argv[] = {key_handle}; | |
290 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
291 isolate, value, | |
292 Execution::Call(isolate, factory, receiver, arraysize(argv), argv)); | |
293 } | |
294 | |
295 #ifdef VERIFY_HEAP | |
296 if (FLAG_verify_heap) { | |
297 cache_handle->JSFunctionResultCacheVerify(); | |
298 } | |
299 #endif | |
300 | |
301 // Function invocation may have cleared the cache. Reread all the data. | |
302 int finger_index = cache_handle->finger_index(); | |
303 int size = cache_handle->size(); | |
304 | |
305 // If we have spare room, put new data into it, otherwise evict post finger | |
306 // entry which is likely to be the least recently used. | |
307 int index = -1; | |
308 if (size < cache_handle->length()) { | |
309 cache_handle->set_size(size + JSFunctionResultCache::kEntrySize); | |
310 index = size; | |
311 } else { | |
312 index = finger_index + JSFunctionResultCache::kEntrySize; | |
313 if (index == cache_handle->length()) { | |
314 index = JSFunctionResultCache::kEntriesIndex; | |
315 } | |
316 } | |
317 | |
318 DCHECK(index % 2 == 0); | |
319 DCHECK(index >= JSFunctionResultCache::kEntriesIndex); | |
320 DCHECK(index < cache_handle->length()); | |
321 | |
322 cache_handle->set(index, *key_handle); | |
323 cache_handle->set(index + 1, *value); | |
324 cache_handle->set_finger_index(index); | |
325 | |
326 #ifdef VERIFY_HEAP | |
327 if (FLAG_verify_heap) { | |
328 cache_handle->JSFunctionResultCacheVerify(); | |
329 } | |
330 #endif | |
331 | |
332 return *value; | |
333 } | |
334 | |
335 | |
336 RUNTIME_FUNCTION(Runtime_MessageGetStartPosition) { | 240 RUNTIME_FUNCTION(Runtime_MessageGetStartPosition) { |
337 SealHandleScope shs(isolate); | 241 SealHandleScope shs(isolate); |
338 DCHECK(args.length() == 1); | 242 DCHECK(args.length() == 1); |
339 CONVERT_ARG_CHECKED(JSMessageObject, message, 0); | 243 CONVERT_ARG_CHECKED(JSMessageObject, message, 0); |
340 return Smi::FromInt(message->start_position()); | 244 return Smi::FromInt(message->start_position()); |
341 } | 245 } |
342 | 246 |
343 | 247 |
344 RUNTIME_FUNCTION(Runtime_MessageGetScript) { | 248 RUNTIME_FUNCTION(Runtime_MessageGetScript) { |
345 SealHandleScope shs(isolate); | 249 SealHandleScope shs(isolate); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 | 310 |
407 #undef CALLSITE_GET | 311 #undef CALLSITE_GET |
408 | 312 |
409 | 313 |
410 RUNTIME_FUNCTION(Runtime_IS_VAR) { | 314 RUNTIME_FUNCTION(Runtime_IS_VAR) { |
411 UNREACHABLE(); // implemented as macro in the parser | 315 UNREACHABLE(); // implemented as macro in the parser |
412 return NULL; | 316 return NULL; |
413 } | 317 } |
414 | 318 |
415 | 319 |
416 RUNTIME_FUNCTION(Runtime_GetFromCache) { | |
417 HandleScope scope(isolate); | |
418 DCHECK(args.length() == 2); | |
419 CONVERT_SMI_ARG_CHECKED(id, 0); | |
420 args[0] = isolate->native_context()->jsfunction_result_caches()->get(id); | |
421 return __RT_impl_Runtime_GetFromCacheRT(args, isolate); | |
422 } | |
423 | |
424 | |
425 RUNTIME_FUNCTION(Runtime_IncrementStatsCounter) { | 320 RUNTIME_FUNCTION(Runtime_IncrementStatsCounter) { |
426 SealHandleScope shs(isolate); | 321 SealHandleScope shs(isolate); |
427 DCHECK(args.length() == 1); | 322 DCHECK(args.length() == 1); |
428 CONVERT_ARG_CHECKED(String, name, 0); | 323 CONVERT_ARG_CHECKED(String, name, 0); |
429 | 324 |
430 if (FLAG_native_code_counters) { | 325 if (FLAG_native_code_counters) { |
431 StatsCounter(isolate, name->ToCString().get()).Increment(); | 326 StatsCounter(isolate, name->ToCString().get()).Increment(); |
432 } | 327 } |
433 return isolate->heap()->undefined_value(); | 328 return isolate->heap()->undefined_value(); |
434 } | 329 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 } | 365 } |
471 | 366 |
472 | 367 |
473 RUNTIME_FUNCTION(Runtime_GetCodeStubExportsObject) { | 368 RUNTIME_FUNCTION(Runtime_GetCodeStubExportsObject) { |
474 HandleScope shs(isolate); | 369 HandleScope shs(isolate); |
475 return isolate->heap()->code_stub_exports_object(); | 370 return isolate->heap()->code_stub_exports_object(); |
476 } | 371 } |
477 | 372 |
478 } // namespace internal | 373 } // namespace internal |
479 } // namespace v8 | 374 } // namespace v8 |
OLD | NEW |