| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 8563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8574 | 8574 |
| 8575 | 8575 |
| 8576 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) { | 8576 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) { |
| 8577 HandleScope scope(isolate); | 8577 HandleScope scope(isolate); |
| 8578 ASSERT(args.length() == 1); | 8578 ASSERT(args.length() == 1); |
| 8579 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | 8579 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); |
| 8580 return Smi::FromInt(function->shared()->opt_count()); | 8580 return Smi::FromInt(function->shared()->opt_count()); |
| 8581 } | 8581 } |
| 8582 | 8582 |
| 8583 | 8583 |
| 8584 static bool IsSuitableForOnStackReplacement(Isolate* isolate, |
| 8585 Handle<JSFunction> function, |
| 8586 Handle<Code> unoptimized) { |
| 8587 // Keep track of whether we've succeeded in optimizing. |
| 8588 if (!unoptimized->optimizable()) return false; |
| 8589 // If we are trying to do OSR when there are already optimized |
| 8590 // activations of the function, it means (a) the function is directly or |
| 8591 // indirectly recursive and (b) an optimized invocation has been |
| 8592 // deoptimized so that we are currently in an unoptimized activation. |
| 8593 // Check for optimized activations of this function. |
| 8594 for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { |
| 8595 JavaScriptFrame* frame = it.frame(); |
| 8596 if (frame->is_optimized() && frame->function() == *function) return false; |
| 8597 } |
| 8598 |
| 8599 return true; |
| 8600 } |
| 8601 |
| 8602 |
| 8584 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) { | 8603 RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) { |
| 8585 HandleScope scope(isolate); | 8604 HandleScope scope(isolate); |
| 8586 ASSERT(args.length() == 1); | 8605 ASSERT(args.length() == 2); |
| 8587 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); | 8606 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); |
| 8607 CONVERT_NUMBER_CHECKED(uint32_t, pc_offset, Uint32, args[1]); |
| 8608 Handle<Code> unoptimized(function->shared()->code(), isolate); |
| 8609 |
| 8610 #ifdef DEBUG |
| 8611 JavaScriptFrameIterator it(isolate); |
| 8612 JavaScriptFrame* frame = it.frame(); |
| 8613 ASSERT_EQ(frame->function(), *function); |
| 8614 ASSERT_EQ(frame->LookupCode(), *unoptimized); |
| 8615 ASSERT(unoptimized->contains(frame->pc())); |
| 8616 |
| 8617 ASSERT(pc_offset == |
| 8618 static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start())); |
| 8619 #endif // DEBUG |
| 8588 | 8620 |
| 8589 // We're not prepared to handle a function with arguments object. | 8621 // We're not prepared to handle a function with arguments object. |
| 8590 ASSERT(!function->shared()->uses_arguments()); | 8622 ASSERT(!function->shared()->uses_arguments()); |
| 8591 | 8623 |
| 8592 // If the optimization attempt succeeds, return the code object which | 8624 Handle<Code> result = Handle<Code>::null(); |
| 8593 // the unoptimized code can jump into. | 8625 BailoutId ast_id = BailoutId::None(); |
| 8594 Handle<Code> code = | 8626 |
| 8595 (FLAG_concurrent_recompilation && FLAG_concurrent_osr) | 8627 if (FLAG_concurrent_recompilation && FLAG_concurrent_osr) { |
| 8596 ? Compiler::CompileForConcurrentOSR(function) | 8628 if (isolate->optimizing_compiler_thread()-> |
| 8597 : Compiler::CompileForOnStackReplacement(function); | 8629 IsQueuedForOSR(function, pc_offset)) { |
| 8598 if (!code.is_null()) { | 8630 // Still waiting for the optimizing compiler thread to finish. Carry on. |
| 8599 #if DEBUG | 8631 if (FLAG_trace_osr) { |
| 8600 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 8632 PrintF("[COSR - polling recompile tasks for "); |
| 8633 function->PrintName(); |
| 8634 PrintF("]\n"); |
| 8635 } |
| 8636 return NULL; |
| 8637 } |
| 8638 |
| 8639 OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()-> |
| 8640 FindReadyOSRCandidate(function, pc_offset); |
| 8641 |
| 8642 if (compiler == NULL) { |
| 8643 if (IsSuitableForOnStackReplacement(isolate, function, unoptimized) && |
| 8644 Compiler::RecompileConcurrent(function, pc_offset)) { |
| 8645 if (function->IsMarkedForLazyRecompilation() || |
| 8646 function->IsMarkedForConcurrentRecompilation()) { |
| 8647 // Prevent regular recompilation if we queue this for OSR. |
| 8648 // TODO(yangguo): remove this as soon as OSR becomes one-shot. |
| 8649 function->ReplaceCode(function->shared()->code()); |
| 8650 } |
| 8651 return NULL; |
| 8652 } |
| 8653 // Fall through to the end in case of failure. |
| 8654 } else { |
| 8655 // TODO(titzer): don't install the OSR code into the function. |
| 8656 ast_id = compiler->info()->osr_ast_id(); |
| 8657 result = Compiler::InstallOptimizedCode(compiler); |
| 8658 } |
| 8659 } else if (IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { |
| 8660 ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset); |
| 8661 ASSERT(!ast_id.IsNone()); |
| 8662 if (FLAG_trace_osr) { |
| 8663 PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt()); |
| 8664 function->PrintName(); |
| 8665 PrintF("]\n"); |
| 8666 } |
| 8667 // Attempt OSR compilation. |
| 8668 result = JSFunction::CompileOsr(function, ast_id, CLEAR_EXCEPTION); |
| 8669 } |
| 8670 |
| 8671 // Revert the patched interrupt now, regardless of whether OSR succeeds. |
| 8672 Deoptimizer::RevertInterruptCode(isolate, *unoptimized); |
| 8673 |
| 8674 // Check whether we ended up with usable optimized code. |
| 8675 if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) { |
| 8601 DeoptimizationInputData* data = | 8676 DeoptimizationInputData* data = |
| 8602 DeoptimizationInputData::cast(code->deoptimization_data()); | 8677 DeoptimizationInputData::cast(result->deoptimization_data()); |
| 8603 ASSERT(!BailoutId(data->OsrAstId()->value()).IsNone()); | 8678 |
| 8604 #endif | 8679 if (data->OsrPcOffset()->value() >= 0) { |
| 8605 // TODO(titzer): this is a massive hack to make the deopt counts | 8680 ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); |
| 8606 // match. Fix heuristics for reenabling optimizations! | 8681 if (FLAG_trace_osr) { |
| 8607 function->shared()->increment_deopt_count(); | 8682 PrintF("[OSR - entry at AST id %d, offset %d in optimized code]\n", |
| 8608 return *code; | 8683 ast_id.ToInt(), data->OsrPcOffset()->value()); |
| 8609 } else { | 8684 } |
| 8610 if (function->IsMarkedForLazyRecompilation() || | 8685 // TODO(titzer): this is a massive hack to make the deopt counts |
| 8611 function->IsMarkedForConcurrentRecompilation()) { | 8686 // match. Fix heuristics for reenabling optimizations! |
| 8612 function->ReplaceCode(function->shared()->code()); | 8687 function->shared()->increment_deopt_count(); |
| 8688 return *result; |
| 8613 } | 8689 } |
| 8614 return NULL; | |
| 8615 } | 8690 } |
| 8691 |
| 8692 if (FLAG_trace_osr) { |
| 8693 PrintF("[OSR - optimization failed for "); |
| 8694 function->PrintName(); |
| 8695 PrintF("]\n"); |
| 8696 } |
| 8697 |
| 8698 if (function->IsMarkedForLazyRecompilation() || |
| 8699 function->IsMarkedForConcurrentRecompilation()) { |
| 8700 function->ReplaceCode(function->shared()->code()); |
| 8701 } |
| 8702 return NULL; |
| 8616 } | 8703 } |
| 8617 | 8704 |
| 8618 | 8705 |
| 8619 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) { | 8706 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) { |
| 8620 SealHandleScope shs(isolate); | 8707 SealHandleScope shs(isolate); |
| 8621 ASSERT(args.length() == 2); | 8708 ASSERT(args.length() == 2); |
| 8622 #ifdef DEBUG | 8709 #ifdef DEBUG |
| 8623 CONVERT_SMI_ARG_CHECKED(interval, 0); | 8710 CONVERT_SMI_ARG_CHECKED(interval, 0); |
| 8624 CONVERT_SMI_ARG_CHECKED(timeout, 1); | 8711 CONVERT_SMI_ARG_CHECKED(timeout, 1); |
| 8625 isolate->heap()->set_allocation_timeout(timeout); | 8712 isolate->heap()->set_allocation_timeout(timeout); |
| (...skipping 4317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12943 NULL, | 13030 NULL, |
| 12944 0); | 13031 0); |
| 12945 | 13032 |
| 12946 // Allocate an array to hold the result. | 13033 // Allocate an array to hold the result. |
| 12947 Object* object; | 13034 Object* object; |
| 12948 { MaybeObject* maybe_object = heap->AllocateFixedArray(count); | 13035 { MaybeObject* maybe_object = heap->AllocateFixedArray(count); |
| 12949 if (!maybe_object->ToObject(&object)) return maybe_object; | 13036 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 12950 } | 13037 } |
| 12951 FixedArray* instances = FixedArray::cast(object); | 13038 FixedArray* instances = FixedArray::cast(object); |
| 12952 | 13039 |
| 12953 ASSERT(HEAP->IsHeapIterable()); | 13040 ASSERT(isolate->heap()->IsHeapIterable()); |
| 12954 // Fill the referencing objects. | 13041 // Fill the referencing objects. |
| 12955 HeapIterator heap_iterator2(heap); | 13042 HeapIterator heap_iterator2(heap); |
| 12956 count = DebugConstructedBy(&heap_iterator2, | 13043 count = DebugConstructedBy(&heap_iterator2, |
| 12957 constructor, | 13044 constructor, |
| 12958 max_references, | 13045 max_references, |
| 12959 instances, | 13046 instances, |
| 12960 count); | 13047 count); |
| 12961 | 13048 |
| 12962 // Return result as JS array. | 13049 // Return result as JS array. |
| 12963 Object* result; | 13050 Object* result; |
| (...skipping 1447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14411 | 14498 |
| 14412 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) { | 14499 RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) { |
| 14413 SealHandleScope shs(isolate); | 14500 SealHandleScope shs(isolate); |
| 14414 ASSERT(args.length() == 2); | 14501 ASSERT(args.length() == 2); |
| 14415 CONVERT_ARG_CHECKED(JSObject, obj1, 0); | 14502 CONVERT_ARG_CHECKED(JSObject, obj1, 0); |
| 14416 CONVERT_ARG_CHECKED(JSObject, obj2, 1); | 14503 CONVERT_ARG_CHECKED(JSObject, obj2, 1); |
| 14417 return isolate->heap()->ToBoolean(obj1->map() == obj2->map()); | 14504 return isolate->heap()->ToBoolean(obj1->map() == obj2->map()); |
| 14418 } | 14505 } |
| 14419 | 14506 |
| 14420 | 14507 |
| 14508 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessCheckNeeded) { |
| 14509 SealHandleScope shs(isolate); |
| 14510 ASSERT(args.length() == 1); |
| 14511 CONVERT_ARG_CHECKED(HeapObject, obj, 0); |
| 14512 return isolate->heap()->ToBoolean(obj->IsAccessCheckNeeded()); |
| 14513 } |
| 14514 |
| 14515 |
| 14421 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) { | 14516 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) { |
| 14422 SealHandleScope shs(isolate); | 14517 SealHandleScope shs(isolate); |
| 14423 ASSERT(args.length() == 1); | 14518 ASSERT(args.length() == 1); |
| 14424 | 14519 |
| 14425 if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value(); | 14520 if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value(); |
| 14426 JSReceiver* obj = JSReceiver::cast(args[0]); | 14521 JSReceiver* obj = JSReceiver::cast(args[0]); |
| 14427 if (obj->IsJSGlobalProxy()) { | 14522 if (obj->IsJSGlobalProxy()) { |
| 14428 Object* proto = obj->GetPrototype(); | 14523 Object* proto = obj->GetPrototype(); |
| 14429 if (proto->IsNull()) return isolate->heap()->false_value(); | 14524 if (proto->IsNull()) return isolate->heap()->false_value(); |
| 14430 ASSERT(proto->IsJSGlobalObject()); | 14525 ASSERT(proto->IsJSGlobalObject()); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14488 ASSERT(args.length() == 1); | 14583 ASSERT(args.length() == 1); |
| 14489 Object* object = args[0]; | 14584 Object* object = args[0]; |
| 14490 if (object->IsJSGlobalProxy()) { | 14585 if (object->IsJSGlobalProxy()) { |
| 14491 object = object->GetPrototype(isolate); | 14586 object = object->GetPrototype(isolate); |
| 14492 if (object->IsNull()) return isolate->heap()->undefined_value(); | 14587 if (object->IsNull()) return isolate->heap()->undefined_value(); |
| 14493 } | 14588 } |
| 14494 return object; | 14589 return object; |
| 14495 } | 14590 } |
| 14496 | 14591 |
| 14497 | 14592 |
| 14593 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) { |
| 14594 HandleScope scope(isolate); |
| 14595 ASSERT(args.length() == 3); |
| 14596 CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0); |
| 14597 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1); |
| 14598 ASSERT(object->IsAccessCheckNeeded()); |
| 14599 Handle<Object> key = args.at<Object>(2); |
| 14600 SaveContext save(isolate); |
| 14601 isolate->set_context(observer->context()); |
| 14602 if (!isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(), |
| 14603 v8::ACCESS_KEYS)) { |
| 14604 return isolate->heap()->false_value(); |
| 14605 } |
| 14606 bool access_allowed = false; |
| 14607 uint32_t index = 0; |
| 14608 if (key->ToArrayIndex(&index) || |
| 14609 (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) { |
| 14610 access_allowed = |
| 14611 isolate->MayIndexedAccess(*object, index, v8::ACCESS_GET) && |
| 14612 isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS); |
| 14613 } else { |
| 14614 access_allowed = isolate->MayNamedAccess(*object, *key, v8::ACCESS_GET) && |
| 14615 isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS); |
| 14616 } |
| 14617 return isolate->heap()->ToBoolean(access_allowed); |
| 14618 } |
| 14619 |
| 14620 |
| 14498 static MaybeObject* ArrayConstructorCommon(Isolate* isolate, | 14621 static MaybeObject* ArrayConstructorCommon(Isolate* isolate, |
| 14499 Handle<JSFunction> constructor, | 14622 Handle<JSFunction> constructor, |
| 14500 Handle<Object> type_info, | 14623 Handle<Object> type_info, |
| 14501 Arguments* caller_args) { | 14624 Arguments* caller_args) { |
| 14502 bool holey = false; | 14625 bool holey = false; |
| 14503 bool can_use_type_feedback = true; | 14626 bool can_use_type_feedback = true; |
| 14504 if (caller_args->length() == 1) { | 14627 if (caller_args->length() == 1) { |
| 14505 Object* argument_one = (*caller_args)[0]; | 14628 Object* argument_one = (*caller_args)[0]; |
| 14506 if (argument_one->IsSmi()) { | 14629 if (argument_one->IsSmi()) { |
| 14507 int value = Smi::cast(argument_one)->value(); | 14630 int value = Smi::cast(argument_one)->value(); |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14676 // Handle last resort GC and make sure to allow future allocations | 14799 // Handle last resort GC and make sure to allow future allocations |
| 14677 // to grow the heap without causing GCs (if possible). | 14800 // to grow the heap without causing GCs (if possible). |
| 14678 isolate->counters()->gc_last_resort_from_js()->Increment(); | 14801 isolate->counters()->gc_last_resort_from_js()->Increment(); |
| 14679 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 14802 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
| 14680 "Runtime::PerformGC"); | 14803 "Runtime::PerformGC"); |
| 14681 } | 14804 } |
| 14682 } | 14805 } |
| 14683 | 14806 |
| 14684 | 14807 |
| 14685 } } // namespace v8::internal | 14808 } } // namespace v8::internal |
| OLD | NEW |