diff options
Diffstat (limited to 'deps/v8/src/runtime.cc')
-rw-r--r-- | deps/v8/src/runtime.cc | 833 |
1 files changed, 572 insertions, 261 deletions
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index 5b96d1fd46..c09fb1d499 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -80,6 +80,7 @@ #include "unicode/locid.h" #include "unicode/numfmt.h" #include "unicode/numsys.h" +#include "unicode/rbbi.h" #include "unicode/smpdtfmt.h" #include "unicode/timezone.h" #include "unicode/uchar.h" @@ -289,9 +290,7 @@ static Handle<Object> CreateObjectLiteralBoilerplate( } Handle<Object> result; uint32_t element_index = 0; - JSReceiver::StoreMode mode = value->IsJSObject() - ? JSReceiver::FORCE_FIELD - : JSReceiver::ALLOW_AS_CONSTANT; + StoreMode mode = value->IsJSObject() ? FORCE_FIELD : ALLOW_AS_CONSTANT; if (key->IsInternalizedString()) { if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { // Array index as string (uint32). @@ -686,10 +685,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) { RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 1); - CONVERT_ARG_CHECKED(JSProxy, proxy, 0); - proxy->Fix(); + CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0); + JSProxy::Fix(proxy); return isolate->heap()->undefined_value(); } @@ -995,7 +994,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) { JSArrayBuffer::cast(typed_array->buffer())->backing_store()); size_t source_byte_offset = NumberToSize(isolate, typed_array->byte_offset()); - OS::MemCopy( + memcpy( buffer->backing_store(), backing_store + source_byte_offset, byte_length); @@ -1663,6 +1662,14 @@ static bool CheckAccessException(Object* callback, (access_type == v8::ACCESS_GET && info->all_can_read()) || (access_type == v8::ACCESS_SET && info->all_can_write()); } + if (callback->IsAccessorPair()) { + AccessorPair* info = AccessorPair::cast(callback); + return + (access_type == v8::ACCESS_HAS && + (info->all_can_read() || info->all_can_write())) || + (access_type == v8::ACCESS_GET && info->all_can_read()) || + (access_type == v8::ACCESS_SET && info->all_can_write()); + } return false; } @@ -1944,6 +1951,35 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) { } +// Transform getter or setter into something DefineAccessor can handle. +static Handle<Object> InstantiateAccessorComponent(Isolate* isolate, + Handle<Object> component) { + if (component->IsUndefined()) return isolate->factory()->null_value(); + Handle<FunctionTemplateInfo> info = + Handle<FunctionTemplateInfo>::cast(component); + return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction()); +} + + +RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) { + HandleScope scope(isolate); + ASSERT(args.length() == 6); + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); + CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2); + CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3); + CONVERT_SMI_ARG_CHECKED(attribute, 4); + CONVERT_SMI_ARG_CHECKED(access_control, 5); + JSObject::DefineAccessor(object, + name, + InstantiateAccessorComponent(isolate, getter), + InstantiateAccessorComponent(isolate, setter), + static_cast<PropertyAttributes>(attribute), + static_cast<v8::AccessControl>(access_control)); + return isolate->heap()->undefined_value(); +} + + static Failure* ThrowRedeclarationError(Isolate* isolate, const char* type, Handle<String> name) { @@ -2240,9 +2276,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { LookupResult lookup(isolate); global->LocalLookup(*name, &lookup); if (!lookup.IsFound()) { - return global->SetLocalPropertyIgnoreAttributes(*name, - *value, - attributes); + HandleScope handle_scope(isolate); + Handle<GlobalObject> global(isolate->context()->global_object()); + RETURN_IF_EMPTY_HANDLE( + isolate, + JSObject::SetLocalPropertyIgnoreAttributes(global, name, value, + attributes)); + return *value; } if (!lookup.IsReadOnly()) { @@ -2459,41 +2499,41 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) { RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); DisallowHeapAllocation no_allocation; ASSERT(args.length() == 5); - CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); - CONVERT_ARG_CHECKED(String, source, 1); + CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); + CONVERT_ARG_HANDLE_CHECKED(String, source, 1); // If source is the empty string we set it to "(?:)" instead as // suggested by ECMA-262, 5th, section 15.10.4.1. - if (source->length() == 0) source = isolate->heap()->query_colon_string(); + if (source->length() == 0) source = isolate->factory()->query_colon_string(); - Object* global = args[2]; - if (!global->IsTrue()) global = isolate->heap()->false_value(); + CONVERT_ARG_HANDLE_CHECKED(Object, global, 2); + if (!global->IsTrue()) global = isolate->factory()->false_value(); - Object* ignoreCase = args[3]; - if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value(); + CONVERT_ARG_HANDLE_CHECKED(Object, ignoreCase, 3); + if (!ignoreCase->IsTrue()) ignoreCase = isolate->factory()->false_value(); - Object* multiline = args[4]; - if (!multiline->IsTrue()) multiline = isolate->heap()->false_value(); + CONVERT_ARG_HANDLE_CHECKED(Object, multiline, 4); + if (!multiline->IsTrue()) multiline = isolate->factory()->false_value(); Map* map = regexp->map(); Object* constructor = map->constructor(); if (constructor->IsJSFunction() && JSFunction::cast(constructor)->initial_map() == map) { // If we still have the original map, set in-object properties directly. - regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source); + regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, *source); // Both true and false are immovable immortal objects so no need for write // barrier. regexp->InObjectPropertyAtPut( - JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER); + JSRegExp::kGlobalFieldIndex, *global, SKIP_WRITE_BARRIER); regexp->InObjectPropertyAtPut( - JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER); + JSRegExp::kIgnoreCaseFieldIndex, *ignoreCase, SKIP_WRITE_BARRIER); regexp->InObjectPropertyAtPut( - JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER); + JSRegExp::kMultilineFieldIndex, *multiline, SKIP_WRITE_BARRIER); regexp->InObjectPropertyAtPut( JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER); - return regexp; + return *regexp; } // Map has changed, so use generic, but slower, method. @@ -2501,34 +2541,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) { static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE); PropertyAttributes writable = static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); - Heap* heap = isolate->heap(); - MaybeObject* result; - result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_string(), - source, - final); - // TODO(jkummerow): Turn these back into ASSERTs when we can be certain - // that it never fires in Release mode in the wild. - CHECK(!result->IsFailure()); - result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_string(), - global, - final); - CHECK(!result->IsFailure()); - result = - regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_string(), - ignoreCase, - final); - CHECK(!result->IsFailure()); - result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_string(), - multiline, - final); - CHECK(!result->IsFailure()); - result = - regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_string(), - Smi::FromInt(0), - writable); - CHECK(!result->IsFailure()); - USE(result); - return regexp; + Handle<Object> zero(Smi::FromInt(0), isolate); + Factory* factory = isolate->factory(); + CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes( + regexp, factory->source_string(), source, final)); + CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes( + regexp, factory->global_string(), global, final)); + CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes( + regexp, factory->ignore_case_string(), ignoreCase, final)); + CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes( + regexp, factory->multiline_string(), multiline, final)); + CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes( + regexp, factory->last_index_string(), zero, writable)); + return *regexp; } @@ -2585,8 +2610,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsClassicModeFunction) { if (!callable->IsJSFunction()) { HandleScope scope(isolate); bool threw = false; - Handle<Object> delegate = - Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw); + Handle<Object> delegate = Execution::TryGetFunctionDelegate( + isolate, Handle<JSReceiver>(callable), &threw); if (threw) return Failure::Exception(); callable = JSFunction::cast(*delegate); } @@ -2604,8 +2629,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) { if (!callable->IsJSFunction()) { HandleScope scope(isolate); bool threw = false; - Handle<Object> delegate = - Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw); + Handle<Object> delegate = Execution::TryGetFunctionDelegate( + isolate, Handle<JSReceiver>(callable), &threw); if (threw) return Failure::Exception(); callable = JSFunction::cast(*delegate); } @@ -2780,16 +2805,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) { RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 2); - CONVERT_ARG_CHECKED(JSFunction, fun, 0); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 1); ASSERT(fun->should_have_prototype()); - Object* obj; - { MaybeObject* maybe_obj = - Accessors::FunctionSetPrototype(fun, args[1], NULL); - if (!maybe_obj->ToObject(&obj)) return maybe_obj; - } + Accessors::FunctionSetPrototype(fun, value); return args[0]; // return TOS } @@ -4689,6 +4711,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) { } +RUNTIME_FUNCTION(MaybeObject*, Runtime_IsValidSmi) { + HandleScope shs(isolate); + ASSERT(args.length() == 1); + + CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]); + if (Smi::IsValid(number)) { + return isolate->heap()->true_value(); + } else { + return isolate->heap()->false_value(); + } +} + + // Returns a single character string where first character equals // string->Get(index). static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { @@ -4728,10 +4763,10 @@ MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate, } if (object->IsString() || object->IsNumber() || object->IsBoolean()) { - return object->GetPrototype(isolate)->GetElement(index); + return object->GetPrototype(isolate)->GetElement(isolate, index); } - return object->GetElement(index); + return object->GetElement(isolate, index); } @@ -4753,7 +4788,7 @@ MaybeObject* Runtime::HasObjectProperty(Isolate* isolate, } else { bool has_pending_exception = false; Handle<Object> converted = - Execution::ToString(key, &has_pending_exception); + Execution::ToString(isolate, key, &has_pending_exception); if (has_pending_exception) return Failure::Exception(); name = Handle<Name>::cast(converted); } @@ -4795,7 +4830,7 @@ MaybeObject* Runtime::GetObjectProperty(Isolate* isolate, } else { bool has_pending_exception = false; Handle<Object> converted = - Execution::ToString(key, &has_pending_exception); + Execution::ToString(isolate, key, &has_pending_exception); if (has_pending_exception) return Failure::Exception(); name = Handle<Name>::cast(converted); } @@ -5018,9 +5053,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); // Use IgnoreAttributes version since a readonly property may be // overridden and SetProperty does not allow this. - return js_object->SetLocalPropertyIgnoreAttributes(*name, - *obj_value, - attr); + Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( + js_object, name, obj_value, attr); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; } return Runtime::ForceSetObjectProperty(isolate, @@ -5093,7 +5129,7 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, if (object->IsJSProxy()) { bool has_pending_exception = false; Handle<Object> name = key->IsSymbol() - ? key : Execution::ToString(key, &has_pending_exception); + ? key : Execution::ToString(isolate, key, &has_pending_exception); if (has_pending_exception) return Failure::Exception(); return JSProxy::cast(*object)->SetProperty( Name::cast(*name), *value, attr, strict_mode); @@ -5122,7 +5158,8 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, if (js_object->HasExternalArrayElements()) { if (!value->IsNumber() && !value->IsUndefined()) { bool has_exception; - Handle<Object> number = Execution::ToNumber(value, &has_exception); + Handle<Object> number = + Execution::ToNumber(isolate, value, &has_exception); if (has_exception) return Failure::Exception(); value = number; } @@ -5141,7 +5178,8 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, if (js_object->HasExternalArrayElements()) { if (!value->IsNumber() && !value->IsUndefined()) { bool has_exception; - Handle<Object> number = Execution::ToNumber(value, &has_exception); + Handle<Object> number = + Execution::ToNumber(isolate, value, &has_exception); if (has_exception) return Failure::Exception(); value = number; } @@ -5158,7 +5196,8 @@ MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, // Call-back into JavaScript to convert the key to a string. bool has_pending_exception = false; - Handle<Object> converted = Execution::ToString(key, &has_pending_exception); + Handle<Object> converted = + Execution::ToString(isolate, key, &has_pending_exception); if (has_pending_exception) return Failure::Exception(); Handle<String> name = Handle<String>::cast(converted); @@ -5203,13 +5242,17 @@ MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); } else { if (name->IsString()) Handle<String>::cast(name)->TryFlatten(); - return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); + Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( + js_object, name, value, attr); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; } } // Call-back into JavaScript to convert the key to a string. bool has_pending_exception = false; - Handle<Object> converted = Execution::ToString(key, &has_pending_exception); + Handle<Object> converted = + Execution::ToString(isolate, key, &has_pending_exception); if (has_pending_exception) return Failure::Exception(); Handle<String> name = Handle<String>::cast(converted); @@ -5217,7 +5260,10 @@ MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, return js_object->SetElement( index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); } else { - return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); + Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( + js_object, name, value, attr); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; } } @@ -5252,7 +5298,8 @@ MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate, } else { // Call-back into JavaScript to convert the key to a string. bool has_pending_exception = false; - Handle<Object> converted = Execution::ToString(key, &has_pending_exception); + Handle<Object> converted = Execution::ToString( + isolate, key, &has_pending_exception); if (has_pending_exception) return Failure::Exception(); name = Handle<String>::cast(converted); } @@ -5419,10 +5466,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) { // Set a local property, even if it is READ_ONLY. If the property does not // exist, it will be added with attributes NONE. RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); - CONVERT_ARG_CHECKED(JSObject, object, 0); - CONVERT_ARG_CHECKED(Name, name, 1); + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); + CONVERT_ARG_HANDLE_CHECKED(Name, name, 1); + CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); // Compute attributes. PropertyAttributes attributes = NONE; if (args.length() == 4) { @@ -5432,9 +5480,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) { (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); attributes = static_cast<PropertyAttributes>(unchecked_value); } - - return object-> - SetLocalPropertyIgnoreAttributes(name, args[2], attributes); + Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes( + object, name, value, attributes); + RETURN_IF_EMPTY_HANDLE(isolate, result); + return *result; } @@ -5844,7 +5893,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) { HandleScope scope(isolate); bool exception = false; Handle<Object> converted = - Execution::ToString(args.at<Object>(0), &exception); + Execution::ToString(isolate, args.at<Object>(0), &exception); if (exception) return Failure::Exception(); Handle<String> key = Handle<String>::cast(converted); @@ -5853,7 +5902,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) { if (index < n) { return frame->GetParameter(index); } else { - return isolate->initial_object_prototype()->GetElement(index); + return isolate->initial_object_prototype()->GetElement(isolate, index); } } @@ -6500,8 +6549,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) { int part_count = indices.length(); Handle<JSArray> result = isolate->factory()->NewJSArray(part_count); - MaybeObject* maybe_result = result->EnsureCanContainHeapObjectElements(); - if (maybe_result->IsFailure()) return maybe_result; + JSObject::EnsureCanContainHeapObjectElements(result); result->set_length(Smi::FromInt(part_count)); ASSERT(result->HasFastObjectElements()); @@ -6628,7 +6676,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) { SealHandleScope shs(isolate); ASSERT(args.length() == 1); CONVERT_ARG_CHECKED(String, value, 0); - return value->ToObject(); + return value->ToObject(isolate); } @@ -6894,21 +6942,20 @@ static inline void StringBuilderConcatHelper(String* special, RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { - SealHandleScope shs(isolate); + HandleScope scope(isolate); ASSERT(args.length() == 3); - CONVERT_ARG_CHECKED(JSArray, array, 0); + CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0); if (!args[1]->IsSmi()) { isolate->context()->mark_out_of_memory(); return Failure::OutOfMemoryException(0x14); } int array_length = args.smi_at(1); - CONVERT_ARG_CHECKED(String, special, 2); + CONVERT_ARG_HANDLE_CHECKED(String, special, 2); // This assumption is used by the slice encoding in one or two smis. ASSERT(Smi::kMaxValue >= String::kMaxLength); - MaybeObject* maybe_result = array->EnsureCanContainHeapObjectElements(); - if (maybe_result->IsFailure()) return maybe_result; + JSObject::EnsureCanContainHeapObjectElements(array); int special_length = special->length(); if (!array->HasFastObjectElements()) { @@ -6990,7 +7037,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { if (!maybe_object->ToObject(&object)) return maybe_object; } SeqOneByteString* answer = SeqOneByteString::cast(object); - StringBuilderConcatHelper(special, + StringBuilderConcatHelper(*special, answer->GetChars(), fixed_array, array_length); @@ -7001,7 +7048,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { if (!maybe_object->ToObject(&object)) return maybe_object; } SeqTwoByteString* answer = SeqTwoByteString::cast(object); - StringBuilderConcatHelper(special, + StringBuilderConcatHelper(*special, answer->GetChars(), fixed_array, array_length); @@ -7477,7 +7524,7 @@ static Object* FlatStringCompare(String* x, String* y) { result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER); } ASSERT(result == - StringCharacterStreamCompare(Isolate::Current()->runtime_state(), x, y)); + StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y)); return result; } @@ -7918,6 +7965,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) { } +RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosureFromStubFailure) { + HandleScope scope(isolate); + ASSERT(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0); + Handle<Context> context(isolate->context()); + PretenureFlag pretenure_flag = NOT_TENURED; + Handle<JSFunction> result = + isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, + context, + pretenure_flag); + return *result; +} + + RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) { HandleScope scope(isolate); ASSERT(args.length() == 3); @@ -8091,7 +8152,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) { if (!bound_function->IsJSFunction()) { bool exception_thrown; - bound_function = Execution::TryGetConstructorDelegate(bound_function, + bound_function = Execution::TryGetConstructorDelegate(isolate, + bound_function, &exception_thrown); if (exception_thrown) return Failure::Exception(); } @@ -8252,9 +8314,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) { return function->code(); } function->shared()->code()->set_profiler_ticks(0); - if (JSFunction::CompileOptimized(function, - BailoutId::None(), - CLEAR_EXCEPTION)) { + if (JSFunction::CompileOptimized(function, CLEAR_EXCEPTION)) { return function->code(); } if (FLAG_trace_opt) { @@ -8267,7 +8327,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) { } -RUNTIME_FUNCTION(MaybeObject*, Runtime_ParallelRecompile) { +RUNTIME_FUNCTION(MaybeObject*, Runtime_ConcurrentRecompile) { HandleScope handle_scope(isolate); ASSERT(args.length() == 1); CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); @@ -8276,22 +8336,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ParallelRecompile) { return isolate->heap()->undefined_value(); } function->shared()->code()->set_profiler_ticks(0); - ASSERT(FLAG_parallel_recompilation); - Compiler::RecompileParallel(function); + ASSERT(FLAG_concurrent_recompilation); + if (!Compiler::RecompileConcurrent(function)) { + function->ReplaceCode(function->shared()->code()); + } return isolate->heap()->undefined_value(); } -RUNTIME_FUNCTION(MaybeObject*, Runtime_InstallRecompiledCode) { - HandleScope handle_scope(isolate); - ASSERT(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); - ASSERT(V8::UseCrankshaft() && FLAG_parallel_recompilation); - isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); - return function->code(); -} - - class ActivationsFinder : public ThreadVisitor { public: Code* code_; @@ -8347,6 +8399,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) { JavaScriptFrame* frame = it.frame(); RUNTIME_ASSERT(frame->function()->IsJSFunction()); + ASSERT(frame->function() == *function); // Avoid doing too much work when running with --always-opt and keep // the optimized code around. @@ -8426,9 +8479,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) { } -RUNTIME_FUNCTION(MaybeObject*, Runtime_IsParallelRecompilationSupported) { +RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConcurrentRecompilationSupported) { HandleScope scope(isolate); - return FLAG_parallel_recompilation + return FLAG_concurrent_recompilation ? isolate->heap()->true_value() : isolate->heap()->false_value(); } @@ -8446,12 +8499,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) { unoptimized->kind() == Code::FUNCTION) { CONVERT_ARG_HANDLE_CHECKED(String, type, 1); if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) { - for (int i = 0; i <= Code::kMaxLoopNestingMarker; i++) { + // Start patching from the currently patched loop nesting level. + int current_level = unoptimized->allow_osr_at_loop_nesting_level(); + ASSERT(Deoptimizer::VerifyInterruptCode( + isolate, unoptimized, current_level)); + for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) { unoptimized->set_allow_osr_at_loop_nesting_level(i); isolate->runtime_profiler()->AttemptOnStackReplacement(*function); } - } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("parallel"))) { - function->MarkForParallelRecompilation(); + } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent"))) { + function->MarkForConcurrentRecompilation(); } } @@ -8472,7 +8529,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) { RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) { HandleScope scope(isolate); RUNTIME_ASSERT(args.length() == 1 || args.length() == 2); - if (!V8::UseCrankshaft()) { + if (!isolate->use_crankshaft()) { return Smi::FromInt(4); // 4 == "never". } bool sync_with_compiler_thread = true; @@ -8483,9 +8540,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) { } } CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); - if (FLAG_parallel_recompilation && sync_with_compiler_thread) { - while (function->IsInRecompileQueue() || - function->IsMarkedForInstallingRecompiledCode()) { + if (FLAG_concurrent_recompilation && sync_with_compiler_thread) { + while (function->IsInRecompileQueue()) { isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); OS::Sleep(50); } @@ -8512,115 +8568,125 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) { } +static bool IsSuitableForOnStackReplacement(Isolate* isolate, + Handle<JSFunction> function, + Handle<Code> unoptimized) { + // Keep track of whether we've succeeded in optimizing. + if (!unoptimized->optimizable()) return false; + // If we are trying to do OSR when there are already optimized + // activations of the function, it means (a) the function is directly or + // indirectly recursive and (b) an optimized invocation has been + // deoptimized so that we are currently in an unoptimized activation. + // Check for optimized activations of this function. + for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) { + JavaScriptFrame* frame = it.frame(); + if (frame->is_optimized() && frame->function() == *function) return false; + } + + return true; +} + + RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) { HandleScope scope(isolate); - ASSERT(args.length() == 1); + ASSERT(args.length() == 2); CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); + CONVERT_NUMBER_CHECKED(uint32_t, pc_offset, Uint32, args[1]); + Handle<Code> unoptimized(function->shared()->code(), isolate); + +#ifdef DEBUG + JavaScriptFrameIterator it(isolate); + JavaScriptFrame* frame = it.frame(); + ASSERT_EQ(frame->function(), *function); + ASSERT_EQ(frame->LookupCode(), *unoptimized); + ASSERT(unoptimized->contains(frame->pc())); + + ASSERT(pc_offset == + static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start())); +#endif // DEBUG // We're not prepared to handle a function with arguments object. ASSERT(!function->shared()->uses_arguments()); - // We have hit a back edge in an unoptimized frame for a function that was - // selected for on-stack replacement. Find the unoptimized code object. - Handle<Code> unoptimized(function->shared()->code(), isolate); - // Keep track of whether we've succeeded in optimizing. - bool succeeded = unoptimized->optimizable(); - if (succeeded) { - // If we are trying to do OSR when there are already optimized - // activations of the function, it means (a) the function is directly or - // indirectly recursive and (b) an optimized invocation has been - // deoptimized so that we are currently in an unoptimized activation. - // Check for optimized activations of this function. - JavaScriptFrameIterator it(isolate); - while (succeeded && !it.done()) { - JavaScriptFrame* frame = it.frame(); - succeeded = !frame->is_optimized() || frame->function() != *function; - it.Advance(); + Handle<Code> result = Handle<Code>::null(); + BailoutId ast_id = BailoutId::None(); + + if (FLAG_concurrent_recompilation && FLAG_concurrent_osr) { + if (isolate->optimizing_compiler_thread()-> + IsQueuedForOSR(function, pc_offset)) { + // Still waiting for the optimizing compiler thread to finish. Carry on. + if (FLAG_trace_osr) { + PrintF("[COSR - polling recompile tasks for "); + function->PrintName(); + PrintF("]\n"); + } + return NULL; } - } - BailoutId ast_id = BailoutId::None(); - if (succeeded) { - // The top JS function is this one, the PC is somewhere in the - // unoptimized code. - JavaScriptFrameIterator it(isolate); - JavaScriptFrame* frame = it.frame(); - ASSERT(frame->function() == *function); - ASSERT(frame->LookupCode() == *unoptimized); - ASSERT(unoptimized->contains(frame->pc())); - - // Use linear search of the unoptimized code's back edge table to find - // the AST id matching the PC. - uint32_t target_pc_offset = - static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start()); - uint32_t loop_depth = 0; - - for (FullCodeGenerator::BackEdgeTableIterator back_edges(*unoptimized); - !back_edges.Done(); - back_edges.Next()) { - if (back_edges.pc_offset() == target_pc_offset) { - ast_id = back_edges.ast_id(); - loop_depth = back_edges.loop_depth(); - break; + OptimizingCompiler* compiler = isolate->optimizing_compiler_thread()-> + FindReadyOSRCandidate(function, pc_offset); + + if (compiler == NULL) { + if (IsSuitableForOnStackReplacement(isolate, function, unoptimized) && + Compiler::RecompileConcurrent(function, pc_offset)) { + if (function->IsMarkedForLazyRecompilation() || + function->IsMarkedForConcurrentRecompilation()) { + // Prevent regular recompilation if we queue this for OSR. + // TODO(yangguo): remove this as soon as OSR becomes one-shot. + function->ReplaceCode(function->shared()->code()); + } + return NULL; } + // Fall through to the end in case of failure. + } else { + // TODO(titzer): don't install the OSR code into the function. + ast_id = compiler->info()->osr_ast_id(); + result = Compiler::InstallOptimizedCode(compiler); } + } else if (IsSuitableForOnStackReplacement(isolate, function, unoptimized)) { + ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset); ASSERT(!ast_id.IsNone()); - if (FLAG_trace_osr) { - PrintF("[replacing on-stack at AST id %d, loop depth %d in ", - ast_id.ToInt(), loop_depth); + PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt()); function->PrintName(); PrintF("]\n"); } + // Attempt OSR compilation. + result = JSFunction::CompileOsr(function, ast_id, CLEAR_EXCEPTION); + } - // Try to compile the optimized code. A true return value from - // CompileOptimized means that compilation succeeded, not necessarily - // that optimization succeeded. - if (JSFunction::CompileOptimized(function, ast_id, CLEAR_EXCEPTION) && - function->IsOptimized()) { - DeoptimizationInputData* data = DeoptimizationInputData::cast( - function->code()->deoptimization_data()); - if (data->OsrPcOffset()->value() >= 0) { - if (FLAG_trace_osr) { - PrintF("[on-stack replacement offset %d in optimized code]\n", - data->OsrPcOffset()->value()); - } - ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); - } else { - // We may never generate the desired OSR entry if we emit an - // early deoptimize. - succeeded = false; + // Revert the patched interrupt now, regardless of whether OSR succeeds. + Deoptimizer::RevertInterruptCode(isolate, *unoptimized); + + // Check whether we ended up with usable optimized code. + if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) { + DeoptimizationInputData* data = + DeoptimizationInputData::cast(result->deoptimization_data()); + + if (data->OsrPcOffset()->value() >= 0) { + ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id); + if (FLAG_trace_osr) { + PrintF("[OSR - entry at AST id %d, offset %d in optimized code]\n", + ast_id.ToInt(), data->OsrPcOffset()->value()); } - } else { - succeeded = false; + // TODO(titzer): this is a massive hack to make the deopt counts + // match. Fix heuristics for reenabling optimizations! + function->shared()->increment_deopt_count(); + return *result; } } - // Revert to the original interrupt calls in the original unoptimized code. if (FLAG_trace_osr) { - PrintF("[restoring original interrupt calls in "); + PrintF("[OSR - optimization failed for "); function->PrintName(); PrintF("]\n"); } - InterruptStub interrupt_stub; - Handle<Code> interrupt_code = interrupt_stub.GetCode(isolate); - Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement(); - Deoptimizer::RevertInterruptCode(*unoptimized, - *interrupt_code, - *replacement_code); - - // If the optimization attempt succeeded, return the AST id tagged as a - // smi. This tells the builtin that we need to translate the unoptimized - // frame to an optimized one. - if (succeeded) { - ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); - return Smi::FromInt(ast_id.ToInt()); - } else { - if (function->IsMarkedForLazyRecompilation()) { - function->ReplaceCode(function->shared()->code()); - } - return Smi::FromInt(-1); + + if (function->IsMarkedForLazyRecompilation() || + function->IsMarkedForConcurrentRecompilation()) { + function->ReplaceCode(function->shared()->code()); } + return NULL; } @@ -8679,8 +8745,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) { bool threw; Handle<JSReceiver> hfun(fun); Handle<Object> hreceiver(receiver, isolate); - Handle<Object> result = - Execution::Call(hfun, hreceiver, argc, argv, &threw, true); + Handle<Object> result = Execution::Call( + isolate, hfun, hreceiver, argc, argv, &threw, true); if (threw) return Failure::Exception(); return *result; @@ -8710,12 +8776,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) { } for (int i = 0; i < argc; ++i) { - argv[i] = Object::GetElement(arguments, offset + i); + argv[i] = Object::GetElement(isolate, arguments, offset + i); } bool threw; - Handle<Object> result = - Execution::Call(fun, receiver, argc, argv, &threw, true); + Handle<Object> result = Execution::Call( + isolate, fun, receiver, argc, argv, &threw, true); if (threw) return Failure::Exception(); return *result; @@ -8726,7 +8792,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) { HandleScope scope(isolate); ASSERT(args.length() == 1); RUNTIME_ASSERT(!args[0]->IsJSFunction()); - return *Execution::GetFunctionDelegate(args.at<Object>(0)); + return *Execution::GetFunctionDelegate(isolate, args.at<Object>(0)); } @@ -8734,7 +8800,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) { HandleScope scope(isolate); ASSERT(args.length() == 1); RUNTIME_ASSERT(!args[0]->IsJSFunction()); - return *Execution::GetConstructorDelegate(args.at<Object>(0)); + return *Execution::GetConstructorDelegate(isolate, args.at<Object>(0)); } @@ -8783,7 +8849,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) { extension_object = JSReceiver::cast(args[0]); } else { // Convert the object to a proper JavaScript object. - MaybeObject* maybe_js_object = args[0]->ToObject(); + MaybeObject* maybe_js_object = args[0]->ToObject(isolate); if (!maybe_js_object->To(&extension_object)) { if (Failure::cast(maybe_js_object)->IsInternalError()) { HandleScope scope(isolate); @@ -8937,7 +9003,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) { IsImmutableVariableMode(mode) ? FROZEN : SEALED; Handle<AccessorInfo> info = Accessors::MakeModuleExport(name, index, attr); - Handle<Object> result = SetAccessor(module, info); + Handle<Object> result = JSObject::SetAccessor(module, info); ASSERT(!(result.is_null() || result->IsUndefined())); USE(result); break; @@ -9303,7 +9369,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) { // First check if this is a real stack overflow. if (isolate->stack_guard()->IsStackOverflow()) { - SealHandleScope shs(isolate); return isolate->StackOverflow(); } @@ -9311,6 +9376,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) { } +RUNTIME_FUNCTION(MaybeObject*, Runtime_TryInstallRecompiledCode) { + HandleScope scope(isolate); + ASSERT(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); + + // First check if this is a real stack overflow. + if (isolate->stack_guard()->IsStackOverflow()) { + SealHandleScope shs(isolate); + return isolate->StackOverflow(); + } + + isolate->optimizing_compiler_thread()->InstallOptimizedFunctions(); + return (function->IsOptimized()) ? function->code() + : function->shared()->code(); +} + + RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) { SealHandleScope shs(isolate); ASSERT(args.length() == 0); @@ -9423,9 +9505,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) { CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1); - MaybeObject* maybe_result_array = - output->EnsureCanContainHeapObjectElements(); - if (maybe_result_array->IsFailure()) return maybe_result_array; + JSObject::EnsureCanContainHeapObjectElements(output); RUNTIME_ASSERT(output->HasFastObjectElements()); DisallowHeapAllocation no_gc; @@ -10097,7 +10177,7 @@ static bool IterateElements(Isolate* isolate, } else if (receiver->HasElement(j)) { // Call GetElement on receiver, not its prototype, or getters won't // have the correct receiver. - element_value = Object::GetElement(receiver, j); + element_value = Object::GetElement(isolate, receiver, j); RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false); visitor->visit(j, element_value); } @@ -10122,7 +10202,8 @@ static bool IterateElements(Isolate* isolate, } else if (receiver->HasElement(j)) { // Call GetElement on receiver, not its prototype, or getters won't // have the correct receiver. - Handle<Object> element_value = Object::GetElement(receiver, j); + Handle<Object> element_value = + Object::GetElement(isolate, receiver, j); RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false); visitor->visit(j, element_value); } @@ -10141,7 +10222,7 @@ static bool IterateElements(Isolate* isolate, while (j < n) { HandleScope loop_scope(isolate); uint32_t index = indices[j]; - Handle<Object> element = Object::GetElement(receiver, index); + Handle<Object> element = Object::GetElement(isolate, receiver, index); RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false); visitor->visit(index, element); // Skip to next different index (i.e., omit duplicates). @@ -10521,7 +10602,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) { RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) { SealHandleScope shs(isolate); ASSERT(args.length() == 0); - return Execution::DebugBreakHelper(); + return Execution::DebugBreakHelper(isolate); } @@ -12021,6 +12102,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) { // Get the frame where the debugging is performed. StackFrame::Id id = UnwrapFrameId(wrapped_id); JavaScriptFrameIterator frame_it(isolate, id); + RUNTIME_ASSERT(!frame_it.done()); + JavaScriptFrame* frame = frame_it.frame(); Handle<JSFunction> fun = @@ -12040,11 +12123,28 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) { BreakLocationIterator break_location_iterator(debug_info, ALL_BREAK_LOCATIONS); - break_location_iterator.FindBreakLocationFromAddress(frame->pc()); + break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1); int current_statement_pos = break_location_iterator.statement_position(); while (!break_location_iterator.Done()) { + bool accept; if (break_location_iterator.pc() > frame->pc()) { + accept = true; + } else { + StackFrame::Id break_frame_id = isolate->debug()->break_frame_id(); + // The break point is near our pc. Could be a step-in possibility, + // that is currently taken by active debugger call. + if (break_frame_id == StackFrame::NO_ID) { + // We are not stepping. + accept = false; + } else { + JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id); + // If our frame is a top frame and we are stepping, we can do step-in + // at this place. + accept = additional_frame_it.frame()->id() == id; + } + } + if (accept) { if (break_location_iterator.IsStepInLocation(isolate)) { Smi* position_value = Smi::FromInt(break_location_iterator.position()); JSObject::SetElement(array, len, @@ -12476,7 +12576,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) { // of frames to step down. RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) { HandleScope scope(isolate); - ASSERT(args.length() == 3); + ASSERT(args.length() == 4); // Check arguments. Object* check; { MaybeObject* maybe_check = Runtime_CheckExecutionState( @@ -12487,6 +12587,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) { return isolate->Throw(isolate->heap()->illegal_argument_string()); } + CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]); + + StackFrame::Id frame_id; + if (wrapped_frame_id == 0) { + frame_id = StackFrame::NO_ID; + } else { + frame_id = UnwrapFrameId(wrapped_frame_id); + } + // Get the step action and check validity. StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1])); if (step_action != StepIn && @@ -12497,6 +12606,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) { return isolate->Throw(isolate->heap()->illegal_argument_string()); } + if (frame_id != StackFrame::NO_ID && step_action != StepNext && + step_action != StepMin && step_action != StepOut) { + return isolate->ThrowIllegalOperation(); + } + // Get the number of steps. int step_count = NumberToInt32(args[2]); if (step_count < 1) { @@ -12508,7 +12622,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) { // Prepare step. isolate->debug()->PrepareStep(static_cast<StepAction>(step_action), - step_count); + step_count, + frame_id); return isolate->heap()->undefined_value(); } @@ -12574,7 +12689,7 @@ static MaybeObject* DebugEvaluate(Isolate* isolate, shared, context, NOT_TENURED); bool pending_exception; Handle<Object> result = Execution::Call( - eval_fun, receiver, 0, NULL, &pending_exception); + isolate, eval_fun, receiver, 0, NULL, &pending_exception); if (pending_exception) return Failure::Exception(); @@ -12613,7 +12728,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { Handle<Object> context_extension(args[5], isolate); // Handle the processing of break. - DisableBreak disable_break_save(disable_break); + DisableBreak disable_break_save(isolate, disable_break); // Get the frame where the debugging is performed. StackFrame::Id id = UnwrapFrameId(wrapped_id); @@ -12680,7 +12795,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) { Handle<Object> context_extension(args[3], isolate); // Handle the processing of break. - DisableBreak disable_break_save(disable_break); + DisableBreak disable_break_save(isolate, disable_break); // Enter the top context from before the debugger was invoked. SaveContext save(isolate); @@ -12925,7 +13040,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) { } FixedArray* instances = FixedArray::cast(object); - ASSERT(HEAP->IsHeapIterable()); + ASSERT(isolate->heap()->IsHeapIterable()); // Fill the referencing objects. HeapIterator heap_iterator2(heap); count = DebugConstructedBy(&heap_iterator2, @@ -12976,7 +13091,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) { RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) { SealHandleScope shs(isolate); ASSERT(args.length() == 0); - CPU::DebugBreak(); + OS::DebugBreak(); return isolate->heap()->undefined_value(); } @@ -13345,11 +13460,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) { bool pending_exception; { if (without_debugger) { - result = Execution::Call(function, isolate->global_object(), 0, NULL, + result = Execution::Call(isolate, + function, + isolate->global_object(), + 0, + NULL, &pending_exception); } else { - EnterDebugger enter_debugger; - result = Execution::Call(function, isolate->global_object(), 0, NULL, + EnterDebugger enter_debugger(isolate); + result = Execution::Call(isolate, + function, + isolate->global_object(), + 0, + NULL, &pending_exception); } } @@ -13510,7 +13633,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) { Handle<Name> base = isolate->factory()->NewStringFromAscii(CStrVector("base")); for (unsigned int i = 0; i < length; ++i) { - MaybeObject* maybe_string = input->GetElement(i); + MaybeObject* maybe_string = input->GetElement(isolate, i); Object* locale_id; if (!maybe_string->ToObject(&locale_id) || !locale_id->IsString()) { return isolate->Throw(isolate->heap()->illegal_argument_string()); @@ -13623,11 +13746,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) { isolate->factory()->NewStringFromAscii(CStrVector("valid")), NONE)); - Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate), - v8::Utils::ToLocal(local_object)); // Make object handle weak so we can delete the data format once GC kicks in. - wrapper.MakeWeak<void>(NULL, &DateFormat::DeleteDateFormat); - wrapper.ClearAndLeak(); + Handle<Object> wrapper = isolate->global_handles()->Create(*local_object); + GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()), + NULL, + DateFormat::DeleteDateFormat); return *local_object; } @@ -13641,7 +13764,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) { CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1); bool has_pending_exception = false; - Handle<Object> value = Execution::ToNumber(date, &has_pending_exception); + Handle<Object> value = + Execution::ToNumber(isolate, date, &has_pending_exception); if (has_pending_exception) { ASSERT(isolate->has_pending_exception()); return Failure::Exception(); @@ -13681,7 +13805,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) { bool has_pending_exception = false; Handle<JSDate> result = Handle<JSDate>::cast( - Execution::NewDate(static_cast<double>(date), &has_pending_exception)); + Execution::NewDate( + isolate, static_cast<double>(date), &has_pending_exception)); if (has_pending_exception) { ASSERT(isolate->has_pending_exception()); return Failure::Exception(); @@ -13726,12 +13851,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) { isolate->factory()->NewStringFromAscii(CStrVector("valid")), NONE)); - Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate), - v8::Utils::ToLocal(local_object)); - // Make object handle weak so we can delete the number format once GC kicks - // in. - wrapper.MakeWeak<void>(NULL, &NumberFormat::DeleteNumberFormat); - wrapper.ClearAndLeak(); + Handle<Object> wrapper = isolate->global_handles()->Create(*local_object); + GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()), + NULL, + NumberFormat::DeleteNumberFormat); return *local_object; } @@ -13745,7 +13868,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) { CONVERT_ARG_HANDLE_CHECKED(Object, number, 1); bool has_pending_exception = false; - Handle<Object> value = Execution::ToNumber(number, &has_pending_exception); + Handle<Object> value = Execution::ToNumber( + isolate, number, &has_pending_exception); if (has_pending_exception) { ASSERT(isolate->has_pending_exception()); return Failure::Exception(); @@ -13839,11 +13963,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) { isolate->factory()->NewStringFromAscii(CStrVector("valid")), NONE)); - Persistent<v8::Object> wrapper(reinterpret_cast<v8::Isolate*>(isolate), - v8::Utils::ToLocal(local_object)); - // Make object handle weak so we can delete the collator once GC kicks in. - wrapper.MakeWeak<void>(NULL, &Collator::DeleteCollator); - wrapper.ClearAndLeak(); + Handle<Object> wrapper = isolate->global_handles()->Create(*local_object); + GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()), + NULL, + Collator::DeleteCollator); return *local_object; } @@ -13874,6 +13997,158 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) { return *isolate->factory()->NewNumberFromInt(result); } + + +RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) { + HandleScope scope(isolate); + + ASSERT(args.length() == 3); + + CONVERT_ARG_HANDLE_CHECKED(String, locale, 0); + CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1); + CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2); + + Handle<ObjectTemplateInfo> break_iterator_template = + I18N::GetTemplate2(isolate); + + // Create an empty object wrapper. + bool has_pending_exception = false; + Handle<JSObject> local_object = Execution::InstantiateObject( + break_iterator_template, &has_pending_exception); + if (has_pending_exception) { + ASSERT(isolate->has_pending_exception()); + return Failure::Exception(); + } + + // Set break iterator as internal field of the resulting JS object. + icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator( + isolate, locale, options, resolved); + + if (!break_iterator) return isolate->ThrowIllegalOperation(); + + local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator)); + // Make sure that the pointer to adopted text is NULL. + local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL)); + + RETURN_IF_EMPTY_HANDLE(isolate, + JSObject::SetLocalPropertyIgnoreAttributes( + local_object, + isolate->factory()->NewStringFromAscii(CStrVector("breakIterator")), + isolate->factory()->NewStringFromAscii(CStrVector("valid")), + NONE)); + + // Make object handle weak so we can delete the break iterator once GC kicks + // in. + Handle<Object> wrapper = isolate->global_handles()->Create(*local_object); + GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()), + NULL, + BreakIterator::DeleteBreakIterator); + return *local_object; +} + + +RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorAdoptText) { + HandleScope scope(isolate); + + ASSERT(args.length() == 2); + + CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0); + CONVERT_ARG_HANDLE_CHECKED(String, text, 1); + + icu::BreakIterator* break_iterator = + BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder); + if (!break_iterator) return isolate->ThrowIllegalOperation(); + + icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>( + break_iterator_holder->GetInternalField(1)); + delete u_text; + + v8::String::Value text_value(v8::Utils::ToLocal(text)); + u_text = new icu::UnicodeString( + reinterpret_cast<const UChar*>(*text_value), text_value.length()); + break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text)); + + break_iterator->setText(*u_text); + + return isolate->heap()->undefined_value(); +} + + +RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorFirst) { + HandleScope scope(isolate); + + ASSERT(args.length() == 1); + + CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0); + + icu::BreakIterator* break_iterator = + BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder); + if (!break_iterator) return isolate->ThrowIllegalOperation(); + + return *isolate->factory()->NewNumberFromInt(break_iterator->first()); +} + + +RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorNext) { + HandleScope scope(isolate); + + ASSERT(args.length() == 1); + + CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0); + + icu::BreakIterator* break_iterator = + BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder); + if (!break_iterator) return isolate->ThrowIllegalOperation(); + + return *isolate->factory()->NewNumberFromInt(break_iterator->next()); +} + + +RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorCurrent) { + HandleScope scope(isolate); + + ASSERT(args.length() == 1); + + CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0); + + icu::BreakIterator* break_iterator = + BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder); + if (!break_iterator) return isolate->ThrowIllegalOperation(); + + return *isolate->factory()->NewNumberFromInt(break_iterator->current()); +} + + +RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorBreakType) { + HandleScope scope(isolate); + + ASSERT(args.length() == 1); + + CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0); + + icu::BreakIterator* break_iterator = + BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder); + if (!break_iterator) return isolate->ThrowIllegalOperation(); + + // TODO(cira): Remove cast once ICU fixes base BreakIterator class. + icu::RuleBasedBreakIterator* rule_based_iterator = + static_cast<icu::RuleBasedBreakIterator*>(break_iterator); + int32_t status = rule_based_iterator->getRuleStatus(); + // Keep return values in sync with JavaScript BreakType enum. + if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) { + return *isolate->factory()->NewStringFromAscii(CStrVector("none")); + } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) { + return *isolate->factory()->NewStringFromAscii(CStrVector("number")); + } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) { + return *isolate->factory()->NewStringFromAscii(CStrVector("letter")); + } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) { + return *isolate->factory()->NewStringFromAscii(CStrVector("kana")); + } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) { + return *isolate->factory()->NewStringFromAscii(CStrVector("ideo")); + } else { + return *isolate->factory()->NewStringFromAscii(CStrVector("unknown")); + } +} #endif // V8_I18N_SUPPORT @@ -13952,13 +14227,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) { RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) { HandleScope scope(isolate); ASSERT_EQ(args.length(), 1); - CONVERT_ARG_CHECKED(JSObject, error_object, 0); - String* key = isolate->heap()->hidden_stack_trace_string(); - Object* result = error_object->GetHiddenProperty(key); + CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0); + Handle<String> key = isolate->factory()->hidden_stack_trace_string(); + Handle<Object> result(error_object->GetHiddenProperty(*key), isolate); if (result->IsTheHole()) return isolate->heap()->undefined_value(); RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined()); - error_object->DeleteHiddenProperty(key); - return result; + JSObject::DeleteHiddenProperty(error_object, key); + return *result; } @@ -14064,7 +14339,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) { // This handle is nor shared, nor used later, so it's safe. Handle<Object> argv[] = { key_handle }; bool pending_exception; - value = Execution::Call(factory, + value = Execution::Call(isolate, + factory, receiver, ARRAY_SIZE(argv), argv, @@ -14232,6 +14508,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) { } +RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessCheckNeeded) { + SealHandleScope shs(isolate); + ASSERT(args.length() == 1); + CONVERT_ARG_CHECKED(HeapObject, obj, 0); + return isolate->heap()->ToBoolean(obj->IsAccessCheckNeeded()); +} + + RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) { SealHandleScope shs(isolate); ASSERT(args.length() == 1); @@ -14309,6 +14593,34 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_UnwrapGlobalProxy) { } +RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) { + HandleScope scope(isolate); + ASSERT(args.length() == 3); + CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0); + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1); + ASSERT(object->IsAccessCheckNeeded()); + Handle<Object> key = args.at<Object>(2); + SaveContext save(isolate); + isolate->set_context(observer->context()); + if (!isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(), + v8::ACCESS_KEYS)) { + return isolate->heap()->false_value(); + } + bool access_allowed = false; + uint32_t index = 0; + if (key->ToArrayIndex(&index) || + (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) { + access_allowed = + isolate->MayIndexedAccess(*object, index, v8::ACCESS_GET) && + isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS); + } else { + access_allowed = isolate->MayNamedAccess(*object, *key, v8::ACCESS_GET) && + isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS); + } + return isolate->heap()->ToBoolean(access_allowed); +} + + static MaybeObject* ArrayConstructorCommon(Isolate* isolate, Handle<JSFunction> constructor, Handle<Object> type_info, @@ -14433,7 +14745,6 @@ static const Runtime::Function kIntrinsicFunctions[] = { MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap, Object* dictionary) { - ASSERT(Isolate::Current()->heap() == heap); ASSERT(dictionary != NULL); ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0); for (int i = 0; i < kNumFunctions; ++i) { |