| 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 |