diff options
Diffstat (limited to 'deps/v8/src/runtime.cc')
-rw-r--r-- | deps/v8/src/runtime.cc | 1381 |
1 files changed, 585 insertions, 796 deletions
diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index 09ca04706d..19d9a3f0be 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -46,7 +46,6 @@ #include "isolate-inl.h" #include "jsregexp.h" #include "json-parser.h" -#include "json-stringifier.h" #include "liveedit.h" #include "liveobjectlist-inl.h" #include "misc-intrinsics.h" @@ -783,15 +782,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) { } -RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) { - HandleScope scope(isolate); - ASSERT(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); - Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table())); - return Smi::FromInt(table->NumberOfElements()); -} - - RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) { HandleScope scope(isolate); ASSERT(args.length() == 1); @@ -851,15 +841,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) { } -RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) { - HandleScope scope(isolate); - ASSERT(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); - Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table())); - return Smi::FromInt(table->NumberOfElements()); -} - - RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) { HandleScope scope(isolate); ASSERT(args.length() == 1); @@ -967,107 +948,104 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) { } -static bool CheckAccessException(Object* callback, - v8::AccessType access_type) { - if (callback->IsAccessorInfo()) { - AccessorInfo* info = AccessorInfo::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; -} +// Recursively traverses hidden prototypes if property is not found +static void GetOwnPropertyImplementation(JSObject* obj, + String* name, + LookupResult* result) { + obj->LocalLookupRealNamedProperty(name, result); + if (result->IsFound()) return; -template<class Key> -static bool CheckGenericAccess( - JSObject* receiver, - JSObject* holder, - Key key, - v8::AccessType access_type, - bool (Isolate::*mayAccess)(JSObject*, Key, v8::AccessType)) { - Isolate* isolate = receiver->GetIsolate(); - for (JSObject* current = receiver; - true; - current = JSObject::cast(current->GetPrototype())) { - if (current->IsAccessCheckNeeded() && - !(isolate->*mayAccess)(current, key, access_type)) { - return false; - } - if (current == holder) break; - } - return true; + Object* proto = obj->GetPrototype(); + if (proto->IsJSObject() && + JSObject::cast(proto)->map()->is_hidden_prototype()) + GetOwnPropertyImplementation(JSObject::cast(proto), + name, result); } -enum AccessCheckResult { - ACCESS_FORBIDDEN, - ACCESS_ALLOWED, - ACCESS_ABSENT -}; - - -static AccessCheckResult CheckElementAccess( - JSObject* obj, - uint32_t index, - v8::AccessType access_type) { - // TODO(1095): we should traverse hidden prototype hierachy as well. - if (CheckGenericAccess( - obj, obj, index, access_type, &Isolate::MayIndexedAccess)) { - return ACCESS_ALLOWED; +static bool CheckAccessException(LookupResult* result, + v8::AccessType access_type) { + if (result->type() == CALLBACKS) { + Object* callback = result->GetCallbackObject(); + if (callback->IsAccessorInfo()) { + AccessorInfo* info = AccessorInfo::cast(callback); + bool can_access = + (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 can_access; + } } - obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type); - return ACCESS_FORBIDDEN; + return false; } -static AccessCheckResult CheckPropertyAccess( - JSObject* obj, - String* name, - v8::AccessType access_type) { - uint32_t index; - if (name->AsArrayIndex(&index)) { - return CheckElementAccess(obj, index, access_type); - } +static bool CheckAccess(JSObject* obj, + String* name, + LookupResult* result, + v8::AccessType access_type) { + ASSERT(result->IsProperty()); - LookupResult lookup(obj->GetIsolate()); - obj->LocalLookup(name, &lookup, true); + JSObject* holder = result->holder(); + JSObject* current = obj; + Isolate* isolate = obj->GetIsolate(); + while (true) { + if (current->IsAccessCheckNeeded() && + !isolate->MayNamedAccess(current, name, access_type)) { + // Access check callback denied the access, but some properties + // can have a special permissions which override callbacks descision + // (currently see v8::AccessControl). + break; + } + + if (current == holder) { + return true; + } - if (!lookup.IsProperty()) return ACCESS_ABSENT; - if (CheckGenericAccess<Object*>( - obj, lookup.holder(), name, access_type, &Isolate::MayNamedAccess)) { - return ACCESS_ALLOWED; + current = JSObject::cast(current->GetPrototype()); } - // Access check callback denied the access, but some properties - // can have a special permissions which override callbacks descision - // (currently see v8::AccessControl). // API callbacks can have per callback access exceptions. - switch (lookup.type()) { - case CALLBACKS: - if (CheckAccessException(lookup.GetCallbackObject(), access_type)) { - return ACCESS_ALLOWED; + switch (result->type()) { + case CALLBACKS: { + if (CheckAccessException(result, access_type)) { + return true; } break; - case INTERCEPTOR: + } + case INTERCEPTOR: { // If the object has an interceptor, try real named properties. // Overwrite the result to fetch the correct property later. - lookup.holder()->LookupRealNamedProperty(name, &lookup); - if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) { - if (CheckAccessException(lookup.GetCallbackObject(), access_type)) { - return ACCESS_ALLOWED; + holder->LookupRealNamedProperty(name, result); + if (result->IsProperty()) { + if (CheckAccessException(result, access_type)) { + return true; } } break; + } default: break; } - obj->GetIsolate()->ReportFailedAccessCheck(obj, access_type); - return ACCESS_FORBIDDEN; + isolate->ReportFailedAccessCheck(current, access_type); + return false; +} + + +// TODO(1095): we should traverse hidden prototype hierachy as well. +static bool CheckElementAccess(JSObject* obj, + uint32_t index, + v8::AccessType access_type) { + if (obj->IsAccessCheckNeeded() && + !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) { + return false; + } + + return true; } @@ -1088,44 +1066,141 @@ static MaybeObject* GetOwnProperty(Isolate* isolate, Handle<JSObject> obj, Handle<String> name) { Heap* heap = isolate->heap(); - // Due to some WebKit tests, we want to make sure that we do not log - // more than one access failure here. - switch (CheckPropertyAccess(*obj, *name, v8::ACCESS_HAS)) { - case ACCESS_FORBIDDEN: return heap->false_value(); - case ACCESS_ALLOWED: break; - case ACCESS_ABSENT: return heap->undefined_value(); + Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE); + Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms); + LookupResult result(isolate); + // This could be an element. + uint32_t index; + if (name->AsArrayIndex(&index)) { + switch (obj->HasLocalElement(index)) { + case JSObject::UNDEFINED_ELEMENT: + return heap->undefined_value(); + + case JSObject::STRING_CHARACTER_ELEMENT: { + // Special handling of string objects according to ECMAScript 5 + // 15.5.5.2. Note that this might be a string object with elements + // other than the actual string value. This is covered by the + // subsequent cases. + Handle<JSValue> js_value = Handle<JSValue>::cast(obj); + Handle<String> str(String::cast(js_value->value())); + Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED); + + elms->set(IS_ACCESSOR_INDEX, heap->false_value()); + elms->set(VALUE_INDEX, *substr); + elms->set(WRITABLE_INDEX, heap->false_value()); + elms->set(ENUMERABLE_INDEX, heap->true_value()); + elms->set(CONFIGURABLE_INDEX, heap->false_value()); + return *desc; + } + + case JSObject::INTERCEPTED_ELEMENT: + case JSObject::FAST_ELEMENT: { + elms->set(IS_ACCESSOR_INDEX, heap->false_value()); + Handle<Object> value = Object::GetElement(obj, index); + RETURN_IF_EMPTY_HANDLE(isolate, value); + elms->set(VALUE_INDEX, *value); + elms->set(WRITABLE_INDEX, heap->true_value()); + elms->set(ENUMERABLE_INDEX, heap->true_value()); + elms->set(CONFIGURABLE_INDEX, heap->true_value()); + return *desc; + } + + case JSObject::DICTIONARY_ELEMENT: { + Handle<JSObject> holder = obj; + if (obj->IsJSGlobalProxy()) { + Object* proto = obj->GetPrototype(); + if (proto->IsNull()) return heap->undefined_value(); + ASSERT(proto->IsJSGlobalObject()); + holder = Handle<JSObject>(JSObject::cast(proto)); + } + FixedArray* elements = FixedArray::cast(holder->elements()); + SeededNumberDictionary* dictionary = NULL; + if (elements->map() == heap->non_strict_arguments_elements_map()) { + dictionary = SeededNumberDictionary::cast(elements->get(1)); + } else { + dictionary = SeededNumberDictionary::cast(elements); + } + int entry = dictionary->FindEntry(index); + ASSERT(entry != SeededNumberDictionary::kNotFound); + PropertyDetails details = dictionary->DetailsAt(entry); + switch (details.type()) { + case CALLBACKS: { + // This is an accessor property with getter and/or setter. + AccessorPair* accessors = + AccessorPair::cast(dictionary->ValueAt(entry)); + elms->set(IS_ACCESSOR_INDEX, heap->true_value()); + if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { + elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER)); + } + if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) { + elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER)); + } + break; + } + case NORMAL: { + // This is a data property. + elms->set(IS_ACCESSOR_INDEX, heap->false_value()); + Handle<Object> value = Object::GetElement(obj, index); + ASSERT(!value.is_null()); + elms->set(VALUE_INDEX, *value); + elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly())); + break; + } + default: + UNREACHABLE(); + break; + } + elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum())); + elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete())); + return *desc; + } + } } - PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name); - if (attrs == ABSENT) return heap->undefined_value(); - AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name); - Handle<AccessorPair> accessors(raw_accessors, isolate); + // Use recursive implementation to also traverse hidden prototypes + GetOwnPropertyImplementation(*obj, *name, &result); - Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE); - elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0)); - elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0)); - elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL)); - - if (raw_accessors == NULL) { - elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0)); - // GetProperty does access check. - Handle<Object> value = GetProperty(obj, name); - if (value.is_null()) return Failure::Exception(); - elms->set(VALUE_INDEX, *value); - } else { - // Access checks are performed for both accessors separately. - // When they fail, the respective field is not set in the descriptor. + if (!result.IsProperty()) { + return heap->undefined_value(); + } + + if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) { + return heap->false_value(); + } + + elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum())); + elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete())); + + bool is_js_accessor = result.IsPropertyCallbacks() && + (result.GetCallbackObject()->IsAccessorPair()); + + if (is_js_accessor) { + // __defineGetter__/__defineSetter__ callback. + elms->set(IS_ACCESSOR_INDEX, heap->true_value()); + + AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject()); Object* getter = accessors->GetComponent(ACCESSOR_GETTER); - Object* setter = accessors->GetComponent(ACCESSOR_SETTER); - if (!getter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_GET)) { + if (!getter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) { elms->set(GETTER_INDEX, getter); } - if (!setter->IsMap() && CheckPropertyAccess(*obj, *name, v8::ACCESS_SET)) { + Object* setter = accessors->GetComponent(ACCESSOR_SETTER); + if (!setter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) { elms->set(SETTER_INDEX, setter); } + } else { + elms->set(IS_ACCESSOR_INDEX, heap->false_value()); + elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly())); + + PropertyAttributes attrs; + Object* value; + // GetProperty will check access and report any violations. + { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs); + if (!maybe_value->ToObject(&value)) return maybe_value; + } + elms->set(VALUE_INDEX, value); } - return *isolate->factory()->NewJSArrayWithElements(elms); + return *desc; } @@ -1283,7 +1358,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { bool is_var = value->IsUndefined(); bool is_const = value->IsTheHole(); bool is_function = value->IsSharedFunctionInfo(); - ASSERT(is_var + is_const + is_function == 1); + bool is_module = value->IsJSModule(); + ASSERT(is_var + is_const + is_function + is_module == 1); if (is_var || is_const) { // Lookup the property in the global object, and don't set the @@ -1291,7 +1367,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { // Do the lookup locally only, see ES5 erratum. LookupResult lookup(isolate); if (FLAG_es52_globals) { - global->LocalLookup(*name, &lookup, true); + Object* obj = *global; + do { + JSObject::cast(obj)->LocalLookup(*name, &lookup); + if (lookup.IsFound()) break; + obj = obj->GetPrototype(); + } while (obj->IsJSObject() && + JSObject::cast(obj)->map()->is_hidden_prototype()); } else { global->Lookup(*name, &lookup); } @@ -1315,29 +1397,30 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { } LookupResult lookup(isolate); - global->LocalLookup(*name, &lookup, true); + global->LocalLookup(*name, &lookup); // Compute the property attributes. According to ECMA-262, // the property must be non-configurable except in eval. int attr = NONE; bool is_eval = DeclareGlobalsEvalFlag::decode(flags); - if (!is_eval) { + if (!is_eval || is_module) { attr |= DONT_DELETE; } bool is_native = DeclareGlobalsNativeFlag::decode(flags); - if (is_const || (is_native && is_function)) { + if (is_const || is_module || (is_native && is_function)) { attr |= READ_ONLY; } LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags); - if (!lookup.IsFound() || is_function) { + if (!lookup.IsFound() || is_function || is_module) { // If the local property exists, check that we can reconfigure it // as required for function declarations. if (lookup.IsFound() && lookup.IsDontDelete()) { if (lookup.IsReadOnly() || lookup.IsDontEnum() || lookup.IsPropertyCallbacks()) { - return ThrowRedeclarationError(isolate, "function", name); + return ThrowRedeclarationError( + isolate, is_function ? "function" : "module", name); } // If the existing property is not configurable, keep its attributes. attr = lookup.GetAttributes(); @@ -1493,20 +1576,27 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { // the whole chain of hidden prototypes to do a 'local' lookup. Object* object = global; LookupResult lookup(isolate); - JSObject::cast(object)->LocalLookup(*name, &lookup, true); - if (lookup.IsInterceptor()) { - HandleScope handle_scope(isolate); - PropertyAttributes intercepted = - lookup.holder()->GetPropertyAttribute(*name); - if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { - // Found an interceptor that's not read only. - if (assign) { - return lookup.holder()->SetProperty( - &lookup, *name, args[2], attributes, strict_mode_flag); - } else { - return isolate->heap()->undefined_value(); + while (object->IsJSObject() && + JSObject::cast(object)->map()->is_hidden_prototype()) { + JSObject* raw_holder = JSObject::cast(object); + raw_holder->LocalLookup(*name, &lookup); + if (lookup.IsInterceptor()) { + HandleScope handle_scope(isolate); + Handle<JSObject> holder(raw_holder); + PropertyAttributes intercepted = holder->GetPropertyAttribute(*name); + // Update the raw pointer in case it's changed due to GC. + raw_holder = *holder; + if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { + // Found an interceptor that's not read only. + if (assign) { + return raw_holder->SetProperty( + &lookup, *name, args[2], attributes, strict_mode_flag); + } else { + return isolate->heap()->undefined_value(); + } } } + object = raw_holder->GetPrototype(); } // Reload global in case the loop above performed a GC. @@ -1570,7 +1660,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { // Strict mode handling not needed (const is disallowed in strict mode). if (lookup.IsField()) { FixedArray* properties = global->properties(); - int index = lookup.GetFieldIndex().field_index(); + int index = lookup.GetFieldIndex(); if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) { properties->set(index, *value); } @@ -1660,7 +1750,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { if (lookup.IsField()) { FixedArray* properties = object->properties(); - int index = lookup.GetFieldIndex().field_index(); + int index = lookup.GetFieldIndex(); if (properties->get(index)->IsTheHole()) { properties->set(index, *value); } @@ -1791,8 +1881,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) { JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER); regexp->InObjectPropertyAtPut( JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER); - regexp->InObjectPropertyAtPut( - JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER); + regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, + Smi::FromInt(0), + SKIP_WRITE_BARRIER); // It's a Smi. return regexp; } @@ -2147,7 +2238,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) { // target function to undefined. SetCode is only used for built-in // constructors like String, Array, and Object, and some web code // doesn't like seeing source code for constructors. - target_shared->ReplaceCode(source_shared->code()); + target_shared->set_code(source_shared->code()); target_shared->set_scope_info(source_shared->scope_info()); target_shared->set_length(source_shared->length()); target_shared->set_formal_parameter_count( @@ -2351,7 +2442,7 @@ class ReplacementStringBuilder { array_builder_(heap->isolate(), estimated_part_count), subject_(subject), character_count_(0), - is_ascii_(subject->IsOneByteRepresentation()) { + is_ascii_(subject->IsAsciiRepresentation()) { // Require a non-zero initial size. Ensures that doubling the size to // extend the array will work. ASSERT(estimated_part_count > 0); @@ -2391,7 +2482,7 @@ class ReplacementStringBuilder { int length = string->length(); ASSERT(length > 0); AddElement(*string); - if (!string->IsOneByteRepresentation()) { + if (!string->IsAsciiRepresentation()) { is_ascii_ = false; } IncrementCharacterCount(length); @@ -2405,7 +2496,7 @@ class ReplacementStringBuilder { Handle<String> joined_string; if (is_ascii_) { - Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_); + Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_); AssertNoAllocation no_alloc; char* char_buffer = seq->GetChars(); StringBuilderConcatHelper(*subject_, @@ -2436,8 +2527,8 @@ class ReplacementStringBuilder { } private: - Handle<SeqOneByteString> NewRawOneByteString(int length) { - return heap_->isolate()->factory()->NewRawOneByteString(length); + Handle<SeqAsciiString> NewRawAsciiString(int length) { + return heap_->isolate()->factory()->NewRawAsciiString(length); } @@ -2762,23 +2853,6 @@ void FindAsciiStringIndices(Vector<const char> subject, } -void FindTwoByteStringIndices(const Vector<const uc16> subject, - uc16 pattern, - ZoneList<int>* indices, - unsigned int limit, - Zone* zone) { - ASSERT(limit > 0); - const uc16* subject_start = subject.start(); - const uc16* subject_end = subject_start + subject.length(); - for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) { - if (*pos == pattern) { - indices->Add(static_cast<int>(pos - subject_start), zone); - limit--; - } - } -} - - template <typename SubjectChar, typename PatternChar> void FindStringIndices(Isolate* isolate, Vector<const SubjectChar> subject, @@ -2843,37 +2917,19 @@ void FindStringIndicesDispatch(Isolate* isolate, } else { Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); if (pattern_content.IsAscii()) { - Vector<const char> pattern_vector = pattern_content.ToAsciiVector(); - if (pattern_vector.length() == 1) { - FindTwoByteStringIndices(subject_vector, - pattern_vector[0], - indices, - limit, - zone); - } else { - FindStringIndices(isolate, - subject_vector, - pattern_vector, - indices, - limit, - zone); - } + FindStringIndices(isolate, + subject_vector, + pattern_content.ToAsciiVector(), + indices, + limit, + zone); } else { - Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector(); - if (pattern_vector.length() == 1) { - FindTwoByteStringIndices(subject_vector, - pattern_vector[0], - indices, - limit, - zone); - } else { - FindStringIndices(isolate, - subject_vector, - pattern_vector, - indices, - limit, - zone); - } + FindStringIndices(isolate, + subject_vector, + pattern_content.ToUC16Vector(), + indices, + limit, + zone); } } } @@ -2904,9 +2960,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString( isolate, *subject, pattern, &indices, 0xffffffff, zone); int matches = indices.length(); - if (matches == 0) { - return isolate->heap()->undefined_value(); - } + if (matches == 0) return *subject; // Detect integer overflow. int64_t result_len_64 = @@ -2923,7 +2977,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString( Handle<ResultSeqString> result; if (ResultSeqString::kHasAsciiEncoding) { result = Handle<ResultSeqString>::cast( - isolate->factory()->NewRawOneByteString(result_len)); + isolate->factory()->NewRawAsciiString(result_len)); } else { result = Handle<ResultSeqString>::cast( isolate->factory()->NewRawTwoByteString(result_len)); @@ -2992,7 +3046,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString( regexp->TypeTag() == JSRegExp::ATOM && simple_replace) { if (subject->HasOnlyAsciiChars() && replacement->HasOnlyAsciiChars()) { - return StringReplaceAtomRegExpWithString<SeqOneByteString>( + return StringReplaceAtomRegExpWithString<SeqAsciiString>( isolate, subject, regexp, replacement, last_match_info); } else { return StringReplaceAtomRegExpWithString<SeqTwoByteString>( @@ -3006,7 +3060,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString( int32_t* current_match = global_cache.FetchNext(); if (current_match == NULL) { if (global_cache.HasException()) return Failure::Exception(); - return isolate->heap()->undefined_value(); + return *subject; } // Guessing the number of parts that the final result string is built @@ -3080,9 +3134,9 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString( // Shortcut for simple non-regexp global replacements if (is_global && regexp->TypeTag() == JSRegExp::ATOM) { - Handle<String> empty_string = isolate->factory()->empty_string(); + Handle<String> empty_string(HEAP->empty_string()); if (subject->HasOnlyAsciiChars()) { - return StringReplaceAtomRegExpWithString<SeqOneByteString>( + return StringReplaceAtomRegExpWithString<SeqAsciiString>( isolate, subject, regexp, @@ -3104,7 +3158,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString( int32_t* current_match = global_cache.FetchNext(); if (current_match == NULL) { if (global_cache.HasException()) return Failure::Exception(); - return isolate->heap()->undefined_value(); + return *subject; } int start = current_match[0]; @@ -3118,7 +3172,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString( Handle<ResultSeqString> answer; if (ResultSeqString::kHasAsciiEncoding) { answer = Handle<ResultSeqString>::cast( - isolate->factory()->NewRawOneByteString(new_length)); + isolate->factory()->NewRawAsciiString(new_length)); } else { answer = Handle<ResultSeqString>::cast( isolate->factory()->NewRawTwoByteString(new_length)); @@ -3210,7 +3264,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) { if (replacement->length() == 0) { if (subject->HasOnlyAsciiChars()) { - return StringReplaceRegExpWithEmptyString<SeqOneByteString>( + return StringReplaceRegExpWithEmptyString<SeqAsciiString>( isolate, subject, regexp, last_match_info); } else { return StringReplaceRegExpWithEmptyString<SeqTwoByteString>( @@ -3795,7 +3849,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) { } char* str = DoubleToRadixCString(value, radix); MaybeObject* result = - isolate->heap()->AllocateStringFromOneByte(CStrVector(str)); + isolate->heap()->AllocateStringFromAscii(CStrVector(str)); DeleteArray(str); return result; } @@ -3806,12 +3860,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) { ASSERT(args.length() == 2); CONVERT_DOUBLE_ARG_CHECKED(value, 0); + if (isnan(value)) { + return *isolate->factory()->nan_symbol(); + } + if (isinf(value)) { + if (value < 0) { + return *isolate->factory()->minus_infinity_symbol(); + } + return *isolate->factory()->infinity_symbol(); + } CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); int f = FastD2IChecked(f_number); RUNTIME_ASSERT(f >= 0); char* str = DoubleToFixedCString(value, f); MaybeObject* res = - isolate->heap()->AllocateStringFromOneByte(CStrVector(str)); + isolate->heap()->AllocateStringFromAscii(CStrVector(str)); DeleteArray(str); return res; } @@ -3822,12 +3885,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) { ASSERT(args.length() == 2); CONVERT_DOUBLE_ARG_CHECKED(value, 0); + if (isnan(value)) { + return *isolate->factory()->nan_symbol(); + } + if (isinf(value)) { + if (value < 0) { + return *isolate->factory()->minus_infinity_symbol(); + } + return *isolate->factory()->infinity_symbol(); + } CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); int f = FastD2IChecked(f_number); RUNTIME_ASSERT(f >= -1 && f <= 20); char* str = DoubleToExponentialCString(value, f); MaybeObject* res = - isolate->heap()->AllocateStringFromOneByte(CStrVector(str)); + isolate->heap()->AllocateStringFromAscii(CStrVector(str)); DeleteArray(str); return res; } @@ -3838,12 +3910,21 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) { ASSERT(args.length() == 2); CONVERT_DOUBLE_ARG_CHECKED(value, 0); + if (isnan(value)) { + return *isolate->factory()->nan_symbol(); + } + if (isinf(value)) { + if (value < 0) { + return *isolate->factory()->minus_infinity_symbol(); + } + return *isolate->factory()->infinity_symbol(); + } CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); int f = FastD2IChecked(f_number); RUNTIME_ASSERT(f >= 1 && f <= 21); char* str = DoubleToPrecisionCString(value, f); MaybeObject* res = - isolate->heap()->AllocateStringFromOneByte(CStrVector(str)); + isolate->heap()->AllocateStringFromAscii(CStrVector(str)); DeleteArray(str); return res; } @@ -3976,7 +4057,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { LookupResult result(isolate); receiver->LocalLookup(key, &result); if (result.IsField()) { - int offset = result.GetFieldIndex().field_index(); + int offset = result.GetFieldIndex(); keyed_lookup_cache->Update(receiver_map, key, offset); return receiver->FastPropertyAt(offset); } @@ -4002,7 +4083,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { // become FAST_DOUBLE_ELEMENTS. Handle<JSObject> js_object(args.at<JSObject>(0)); ElementsKind elements_kind = js_object->GetElementsKind(); - if (IsFastDoubleElementsKind(elements_kind)) { + if (IsFastElementsKind(elements_kind) && + !IsFastObjectElementsKind(elements_kind)) { FixedArrayBase* elements = js_object->elements(); if (args.at<Smi>(1)->value() >= elements->length()) { if (IsFastHoleyElementsKind(elements_kind)) { @@ -4015,9 +4097,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { isolate); if (maybe_object->IsFailure()) return maybe_object; } - } else { - ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) || - !IsFastElementsKind(elements_kind)); } } } else if (args[0]->IsString() && args[1]->IsSmi()) { @@ -4140,34 +4219,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { } -// Return property without being observable by accessors or interceptors. -RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) { - ASSERT(args.length() == 2); - CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); - CONVERT_ARG_HANDLE_CHECKED(String, key, 1); - LookupResult lookup(isolate); - object->LookupRealNamedProperty(*key, &lookup); - if (!lookup.IsFound()) return isolate->heap()->undefined_value(); - switch (lookup.type()) { - case NORMAL: - return lookup.holder()->GetNormalizedProperty(&lookup); - case FIELD: - return lookup.holder()->FastPropertyAt( - lookup.GetFieldIndex().field_index()); - case CONSTANT_FUNCTION: - return lookup.GetConstantFunction(); - case CALLBACKS: - case HANDLER: - case INTERCEPTOR: - case TRANSITION: - return isolate->heap()->undefined_value(); - case NONEXISTENT: - UNREACHABLE(); - } - return isolate->heap()->undefined_value(); -} - - MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, Handle<Object> object, Handle<Object> key, @@ -4627,6 +4678,41 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) { CONVERT_ARG_CHECKED(JSObject, object, 0); CONVERT_ARG_CHECKED(String, key, 1); + uint32_t index; + if (key->AsArrayIndex(&index)) { + JSObject::LocalElementType type = object->HasLocalElement(index); + switch (type) { + case JSObject::UNDEFINED_ELEMENT: + case JSObject::STRING_CHARACTER_ELEMENT: + return isolate->heap()->false_value(); + case JSObject::INTERCEPTED_ELEMENT: + case JSObject::FAST_ELEMENT: + return isolate->heap()->true_value(); + case JSObject::DICTIONARY_ELEMENT: { + if (object->IsJSGlobalProxy()) { + Object* proto = object->GetPrototype(); + if (proto->IsNull()) { + return isolate->heap()->false_value(); + } + ASSERT(proto->IsJSGlobalObject()); + object = JSObject::cast(proto); + } + FixedArray* elements = FixedArray::cast(object->elements()); + SeededNumberDictionary* dictionary = NULL; + if (elements->map() == + isolate->heap()->non_strict_arguments_elements_map()) { + dictionary = SeededNumberDictionary::cast(elements->get(1)); + } else { + dictionary = SeededNumberDictionary::cast(elements); + } + int entry = dictionary->FindEntry(index); + ASSERT(entry != SeededNumberDictionary::kNotFound); + PropertyDetails details = dictionary->DetailsAt(entry); + return isolate->heap()->ToBoolean(!details.IsDontEnum()); + } + } + } + PropertyAttributes att = object->GetLocalPropertyAttribute(key); return isolate->heap()->ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0); } @@ -5026,10 +5112,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) { // Fast case: short integer or some sorts of junk values. int len = subject->length(); - if (subject->IsSeqOneByteString()) { + if (subject->IsSeqAsciiString()) { if (len == 0) return Smi::FromInt(0); - char const* data = SeqOneByteString::cast(subject)->GetChars(); + char const* data = SeqAsciiString::cast(subject)->GetChars(); bool minus = (data[0] == '-'); int start_pos = (minus ? 1 : 0); @@ -5073,22 +5159,46 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) { } -RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) { - CONVERT_SMI_ARG_CHECKED(length, 0); - CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1); - if (length == 0) return isolate->heap()->empty_string(); - if (is_one_byte) { - return isolate->heap()->AllocateRawOneByteString(length); - } else { - return isolate->heap()->AllocateRawTwoByteString(length); +RUNTIME_FUNCTION(MaybeObject*, Runtime_StringFromCharCodeArray) { + NoHandleAllocation ha; + ASSERT(args.length() == 1); + + CONVERT_ARG_CHECKED(JSArray, codes, 0); + int length = Smi::cast(codes->length())->value(); + + // Check if the string can be ASCII. + int i; + for (i = 0; i < length; i++) { + Object* element; + { MaybeObject* maybe_element = codes->GetElement(i); + // We probably can't get an exception here, but just in order to enforce + // the checking of inputs in the runtime calls we check here. + if (!maybe_element->ToObject(&element)) return maybe_element; + } + CONVERT_NUMBER_CHECKED(int, chr, Int32, element); + if ((chr & 0xffff) > String::kMaxAsciiCharCode) + break; } -} + MaybeObject* maybe_object = NULL; + if (i == length) { // The string is ASCII. + maybe_object = isolate->heap()->AllocateRawAsciiString(length); + } else { // The string is not ASCII. + maybe_object = isolate->heap()->AllocateRawTwoByteString(length); + } -RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) { - CONVERT_ARG_CHECKED(SeqString, string, 0); - CONVERT_SMI_ARG_CHECKED(new_length, 1); - return string->Truncate(new_length); + Object* object = NULL; + if (!maybe_object->ToObject(&object)) return maybe_object; + String* result = String::cast(object); + for (int i = 0; i < length; i++) { + Object* element; + { MaybeObject* maybe_element = codes->GetElement(i); + if (!maybe_element->ToObject(&element)) return maybe_element; + } + CONVERT_NUMBER_CHECKED(int, chr, Int32, element); + result->Set(i, chr & 0xffff); + } + return result; } @@ -5166,7 +5276,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) { } Object* o; { MaybeObject* maybe_o = - isolate->heap()->AllocateRawOneByteString(escaped_length); + isolate->heap()->AllocateRawAsciiString(escaped_length); if (!maybe_o->ToObject(&o)) return maybe_o; } String* destination = String::cast(o); @@ -5274,7 +5384,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) { Object* o; { MaybeObject* maybe_o = ascii ? - isolate->heap()->AllocateRawOneByteString(unescaped_length) : + isolate->heap()->AllocateRawAsciiString(unescaped_length) : isolate->heap()->AllocateRawTwoByteString(unescaped_length); if (!maybe_o->ToObject(&o)) return maybe_o; } @@ -5372,8 +5482,8 @@ MaybeObject* AllocateRawString<SeqTwoByteString>(Isolate* isolate, int length) { template <> -MaybeObject* AllocateRawString<SeqOneByteString>(Isolate* isolate, int length) { - return isolate->heap()->AllocateRawOneByteString(length); +MaybeObject* AllocateRawString<SeqAsciiString>(Isolate* isolate, int length) { + return isolate->heap()->AllocateRawAsciiString(length); } @@ -5524,7 +5634,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) { return QuoteJsonString<uc16, SeqTwoByteString, false>(isolate, flat.ToUC16Vector()); } else { - return QuoteJsonString<char, SeqOneByteString, false>(isolate, + return QuoteJsonString<char, SeqAsciiString, false>(isolate, flat.ToAsciiVector()); } } @@ -5547,7 +5657,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringComma) { return QuoteJsonString<uc16, SeqTwoByteString, true>(isolate, flat.ToUC16Vector()); } else { - return QuoteJsonString<char, SeqOneByteString, true>(isolate, + return QuoteJsonString<char, SeqAsciiString, true>(isolate, flat.ToAsciiVector()); } } @@ -5639,7 +5749,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) { } if (ascii) { - return QuoteJsonStringArray<char, SeqOneByteString>(isolate, + return QuoteJsonStringArray<char, SeqAsciiString>(isolate, elements, worst_case_length); } else { @@ -5650,14 +5760,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONStringArray) { } -RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) { - ASSERT(args.length() == 1); - HandleScope scope(isolate); - BasicJsonStringifier stringifier(isolate); - return stringifier.Stringify(Handle<Object>(args[0])); -} - - RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) { NoHandleAllocation ha; @@ -5704,8 +5806,8 @@ MUST_USE_RESULT static MaybeObject* ConvertCaseHelper( // might break in the future if we implement more context and locale // dependent upper/lower conversions. Object* o; - { MaybeObject* maybe_o = s->IsOneByteRepresentation() - ? isolate->heap()->AllocateRawOneByteString(length) + { MaybeObject* maybe_o = s->IsAsciiRepresentation() + ? isolate->heap()->AllocateRawAsciiString(length) : isolate->heap()->AllocateRawTwoByteString(length); if (!maybe_o->ToObject(&o)) return maybe_o; } @@ -5936,14 +6038,14 @@ MUST_USE_RESULT static MaybeObject* ConvertCase( // character is also ASCII. This is currently the case, but it // might break in the future if we implement more context and locale // dependent upper/lower conversions. - if (s->IsSeqOneByteString()) { + if (s->IsSeqAsciiString()) { Object* o; - { MaybeObject* maybe_o = isolate->heap()->AllocateRawOneByteString(length); + { MaybeObject* maybe_o = isolate->heap()->AllocateRawAsciiString(length); if (!maybe_o->ToObject(&o)) return maybe_o; } - SeqOneByteString* result = SeqOneByteString::cast(o); + SeqAsciiString* result = SeqAsciiString::cast(o); bool has_changed_character = ConvertTraits::AsciiConverter::Convert( - result->GetChars(), SeqOneByteString::cast(s)->GetChars(), length); + result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length); return has_changed_character ? result : s; } @@ -6145,7 +6247,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) { Handle<FixedArray> elements; int position = 0; - if (s->IsFlat() && s->IsOneByteRepresentation()) { + if (s->IsFlat() && s->IsAsciiRepresentation()) { // Try using cached chars where possible. Object* obj; { MaybeObject* maybe_obj = @@ -6518,10 +6620,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) { if (ascii) { { MaybeObject* maybe_object = - isolate->heap()->AllocateRawOneByteString(length); + isolate->heap()->AllocateRawAsciiString(length); if (!maybe_object->ToObject(&object)) return maybe_object; } - SeqOneByteString* answer = SeqOneByteString::cast(object); + SeqAsciiString* answer = SeqAsciiString::cast(object); StringBuilderConcatHelper(special, answer->GetChars(), fixed_array, @@ -6680,10 +6782,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { // Find total length of join result. int string_length = 0; - bool is_ascii = separator->IsOneByteRepresentation(); + bool is_ascii = separator->IsAsciiRepresentation(); int max_string_length; if (is_ascii) { - max_string_length = SeqOneByteString::kMaxLength; + max_string_length = SeqAsciiString::kMaxLength; } else { max_string_length = SeqTwoByteString::kMaxLength; } @@ -6697,7 +6799,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { RUNTIME_ASSERT(elements->get(i + 1)->IsString()); String* string = String::cast(elements->get(i + 1)); int length = string->length(); - if (is_ascii && !string->IsOneByteRepresentation()) { + if (is_ascii && !string->IsAsciiRepresentation()) { is_ascii = false; max_string_length = SeqTwoByteString::kMaxLength; } @@ -6733,10 +6835,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) { if (is_ascii) { MaybeObject* result_allocation = - isolate->heap()->AllocateRawOneByteString(string_length); + isolate->heap()->AllocateRawAsciiString(string_length); if (result_allocation->IsFailure()) return result_allocation; - SeqOneByteString* result_string = - SeqOneByteString::cast(result_allocation->ToObjectUnchecked()); + SeqAsciiString* result_string = + SeqAsciiString::cast(result_allocation->ToObjectUnchecked()); JoinSparseArrayWithSeparator<char>(elements, elements_length, array_length, @@ -7139,8 +7241,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) { isolate->counters()->math_exp()->Increment(); CONVERT_DOUBLE_ARG_CHECKED(x, 0); - lazily_initialize_fast_exp(); - return isolate->heap()->NumberFromDouble(fast_exp(x)); + return isolate->transcendental_cache()->Get(TranscendentalCache::EXP, x); } @@ -7832,34 +7933,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ParallelRecompile) { HandleScope handle_scope(isolate); ASSERT(FLAG_parallel_recompilation); Compiler::RecompileParallel(args.at<JSFunction>(0)); - return isolate->heap()->undefined_value(); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_ForceParallelRecompile) { - if (!V8::UseCrankshaft()) return isolate->heap()->undefined_value(); - HandleScope handle_scope(isolate); - ASSERT(FLAG_parallel_recompilation && FLAG_manual_parallel_recompilation); - if (!isolate->optimizing_compiler_thread()->IsQueueAvailable()) { - return isolate->Throw( - *isolate->factory()->LookupAsciiSymbol("Recompile queue is full.")); - } - CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); - fun->ReplaceCode(isolate->builtins()->builtin(Builtins::kParallelRecompile)); - Compiler::RecompileParallel(fun); - return isolate->heap()->undefined_value(); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_InstallRecompiledCode) { - if (!V8::UseCrankshaft()) return isolate->heap()->undefined_value(); - HandleScope handle_scope(isolate); - ASSERT(FLAG_parallel_recompilation && FLAG_manual_parallel_recompilation); - CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); - OptimizingCompilerThread* opt_thread = isolate->optimizing_compiler_thread(); - Handle<SharedFunctionInfo> shared(fun->shared()); - while (*opt_thread->InstallNextOptimizedFunction() != *shared) { } - return isolate->heap()->undefined_value(); + return *isolate->factory()->undefined_value(); } @@ -8134,8 +8208,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) { function->PrintName(); PrintF("]\n"); } - InterruptStub interrupt_stub; - Handle<Code> check_code = interrupt_stub.GetCode(); + Handle<Code> check_code; + if (FLAG_count_based_interrupts) { + InterruptStub interrupt_stub; + check_code = interrupt_stub.GetCode(); + } else // NOLINT + { // NOLINT + StackCheckStub check_stub; + check_code = check_stub.GetCode(); + } Handle<Code> replacement_code = isolate->builtins()->OnStackReplacement(); Deoptimizer::RevertStackCheckCode(*unoptimized, *check_code, @@ -8397,89 +8478,20 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) { RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) { - ASSERT(args.length() == 2); - CONVERT_SMI_ARG_CHECKED(index, 0); - - if (!args[1]->IsScopeInfo()) { - // Module already initialized. Find hosting context and retrieve context. - Context* host = Context::cast(isolate->context())->global_context(); - Context* context = Context::cast(host->get(index)); - ASSERT(context->previous() == isolate->context()); - isolate->set_context(context); - return context; - } - - CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1); + NoHandleAllocation ha; + ASSERT(args.length() == 1); + CONVERT_ARG_HANDLE_CHECKED(JSModule, instance, 0); - // Allocate module context. - HandleScope scope(isolate); - Factory* factory = isolate->factory(); - Handle<Context> context = factory->NewModuleContext(scope_info); - Handle<JSModule> module = factory->NewJSModule(context, scope_info); - context->set_module(*module); + Context* context = Context::cast(instance->context()); Context* previous = isolate->context(); + ASSERT(context->IsModuleContext()); + // Initialize the context links. context->set_previous(previous); context->set_closure(previous->closure()); context->set_global_object(previous->global_object()); - isolate->set_context(*context); - - // Find hosting scope and initialize internal variable holding module there. - previous->global_context()->set(index, *context); - - return *context; -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) { - HandleScope scope(isolate); - ASSERT(args.length() == 1); - CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0); - Context* host_context = isolate->context(); - - for (int i = 0; i < descriptions->length(); ++i) { - Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i))); - int host_index = description->host_index(); - Handle<Context> context(Context::cast(host_context->get(host_index))); - Handle<JSModule> module(context->module()); - - for (int j = 0; j < description->length(); ++j) { - Handle<String> name(description->name(j)); - VariableMode mode = description->mode(j); - int index = description->index(j); - switch (mode) { - case VAR: - case LET: - case CONST: - case CONST_HARMONY: { - PropertyAttributes attr = - IsImmutableVariableMode(mode) ? FROZEN : SEALED; - Handle<AccessorInfo> info = - Accessors::MakeModuleExport(name, index, attr); - Handle<Object> result = SetAccessor(module, info); - ASSERT(!(result.is_null() || result->IsUndefined())); - USE(result); - break; - } - case MODULE: { - Object* referenced_context = Context::cast(host_context)->get(index); - Handle<JSModule> value(Context::cast(referenced_context)->module()); - JSReceiver::SetProperty(module, name, value, FROZEN, kStrictMode); - break; - } - case INTERNAL: - case TEMPORARY: - case DYNAMIC: - case DYNAMIC_GLOBAL: - case DYNAMIC_LOCAL: - UNREACHABLE(); - } - } - - JSObject::PreventExtensions(module); - } + isolate->set_context(context); - ASSERT(!isolate->has_pending_exception()); - return isolate->heap()->undefined_value(); + return context; } @@ -8997,7 +9009,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) { source = Handle<String>(source->TryFlattenGetString()); // Optimized fast case where we only have ASCII characters. Handle<Object> result; - if (source->IsSeqOneByteString()) { + if (source->IsSeqAsciiString()) { result = JsonParser<true>::Parse(source, zone); } else { result = JsonParser<false>::Parse(source, zone); @@ -9167,7 +9179,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) { RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) { ASSERT(args.length() == 2); CONVERT_ARG_CHECKED(JSArray, array, 0); - CONVERT_ARG_CHECKED(JSReceiver, element, 1); + CONVERT_ARG_CHECKED(JSObject, element, 1); RUNTIME_ASSERT(array->HasFastSmiOrObjectElements()); int length = Smi::cast(array->length())->value(); FixedArray* elements = FixedArray::cast(array->elements()); @@ -9236,7 +9248,7 @@ class ArrayConcatVisitor { clear_storage(); set_storage(*result); } - } +} void increase_index_offset(uint32_t delta) { if (JSObject::kMaxElementCount - index_offset_ < delta) { @@ -9327,22 +9339,10 @@ static uint32_t EstimateElementCount(Handle<JSArray> array) { break; } case FAST_DOUBLE_ELEMENTS: - case FAST_HOLEY_DOUBLE_ELEMENTS: { - // Fast elements can't have lengths that are not representable by - // a 32-bit signed integer. - ASSERT(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0); - int fast_length = static_cast<int>(length); - if (array->elements()->IsFixedArray()) { - ASSERT(FixedArray::cast(array->elements())->length() == 0); - break; - } - Handle<FixedDoubleArray> elements( - FixedDoubleArray::cast(array->elements())); - for (int i = 0; i < fast_length; i++) { - if (!elements->is_the_hole(i)) element_count++; - } + case FAST_HOLEY_DOUBLE_ELEMENTS: + // TODO(1810): Decide if it's worthwhile to implement this. + UNREACHABLE(); break; - } case DICTIONARY_ELEMENTS: { Handle<SeededNumberDictionary> dictionary( SeededNumberDictionary::cast(array->elements())); @@ -9585,27 +9585,8 @@ static bool IterateElements(Isolate* isolate, } case FAST_HOLEY_DOUBLE_ELEMENTS: case FAST_DOUBLE_ELEMENTS: { - // Run through the elements FixedArray and use HasElement and GetElement - // to check the prototype for missing elements. - Handle<FixedDoubleArray> elements( - FixedDoubleArray::cast(receiver->elements())); - int fast_length = static_cast<int>(length); - ASSERT(fast_length <= elements->length()); - for (int j = 0; j < fast_length; j++) { - HandleScope loop_scope(isolate); - if (!elements->is_the_hole(j)) { - double double_value = elements->get_scalar(j); - Handle<Object> element_value = - isolate->factory()->NewNumber(double_value); - visitor->visit(j, element_value); - } 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); - RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false); - visitor->visit(j, element_value); - } - } + // TODO(1810): Decide if it's worthwhile to implement this. + UNREACHABLE(); break; } case DICTIONARY_ELEMENTS: { @@ -9708,51 +9689,48 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) { // that mutate other arguments (but will otherwise be precise). // The number of elements is precise if there are no inherited elements. - ElementsKind kind = FAST_SMI_ELEMENTS; - uint32_t estimate_result_length = 0; uint32_t estimate_nof_elements = 0; - for (int i = 0; i < argument_count; i++) { - HandleScope loop_scope; - Handle<Object> obj(elements->get(i)); - uint32_t length_estimate; - uint32_t element_estimate; - if (obj->IsJSArray()) { - Handle<JSArray> array(Handle<JSArray>::cast(obj)); - length_estimate = static_cast<uint32_t>(array->length()->Number()); - if (length_estimate != 0) { - ElementsKind array_kind = - GetPackedElementsKind(array->map()->elements_kind()); - if (IsMoreGeneralElementsKindTransition(kind, array_kind)) { - kind = array_kind; - } - } - element_estimate = EstimateElementCount(array); - } else { - if (obj->IsHeapObject()) { - if (obj->IsNumber()) { - if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) { - kind = FAST_DOUBLE_ELEMENTS; + { + for (int i = 0; i < argument_count; i++) { + HandleScope loop_scope; + Handle<Object> obj(elements->get(i)); + uint32_t length_estimate; + uint32_t element_estimate; + if (obj->IsJSArray()) { + Handle<JSArray> array(Handle<JSArray>::cast(obj)); + // TODO(1810): Find out if it's worthwhile to properly support + // arbitrary ElementsKinds. For now, pessimistically transition to + // FAST_*_ELEMENTS. + if (array->HasFastDoubleElements()) { + ElementsKind to_kind = FAST_ELEMENTS; + if (array->HasFastHoleyElements()) { + to_kind = FAST_HOLEY_ELEMENTS; } - } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) { - kind = FAST_ELEMENTS; + array = Handle<JSArray>::cast( + JSObject::TransitionElementsKind(array, to_kind)); } + length_estimate = + static_cast<uint32_t>(array->length()->Number()); + element_estimate = + EstimateElementCount(array); + } else { + length_estimate = 1; + element_estimate = 1; + } + // Avoid overflows by capping at kMaxElementCount. + if (JSObject::kMaxElementCount - estimate_result_length < + length_estimate) { + estimate_result_length = JSObject::kMaxElementCount; + } else { + estimate_result_length += length_estimate; + } + if (JSObject::kMaxElementCount - estimate_nof_elements < + element_estimate) { + estimate_nof_elements = JSObject::kMaxElementCount; + } else { + estimate_nof_elements += element_estimate; } - length_estimate = 1; - element_estimate = 1; - } - // Avoid overflows by capping at kMaxElementCount. - if (JSObject::kMaxElementCount - estimate_result_length < - length_estimate) { - estimate_result_length = JSObject::kMaxElementCount; - } else { - estimate_result_length += length_estimate; - } - if (JSObject::kMaxElementCount - estimate_nof_elements < - element_estimate) { - estimate_nof_elements = JSObject::kMaxElementCount; - } else { - estimate_nof_elements += element_estimate; } } @@ -9763,76 +9741,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) { Handle<FixedArray> storage; if (fast_case) { - if (kind == FAST_DOUBLE_ELEMENTS) { - Handle<FixedDoubleArray> double_storage = - isolate->factory()->NewFixedDoubleArray(estimate_result_length); - int j = 0; - bool failure = false; - for (int i = 0; i < argument_count; i++) { - Handle<Object> obj(elements->get(i)); - if (obj->IsSmi()) { - double_storage->set(j, Smi::cast(*obj)->value()); - j++; - } else if (obj->IsNumber()) { - double_storage->set(j, obj->Number()); - j++; - } else { - JSArray* array = JSArray::cast(*obj); - uint32_t length = static_cast<uint32_t>(array->length()->Number()); - switch (array->map()->elements_kind()) { - case FAST_HOLEY_DOUBLE_ELEMENTS: - case FAST_DOUBLE_ELEMENTS: { - // Empty fixed array indicates that there are no elements. - if (array->elements()->IsFixedArray()) break; - FixedDoubleArray* elements = - FixedDoubleArray::cast(array->elements()); - for (uint32_t i = 0; i < length; i++) { - if (elements->is_the_hole(i)) { - failure = true; - break; - } - double double_value = elements->get_scalar(i); - double_storage->set(j, double_value); - j++; - } - break; - } - case FAST_HOLEY_SMI_ELEMENTS: - case FAST_SMI_ELEMENTS: { - FixedArray* elements( - FixedArray::cast(array->elements())); - for (uint32_t i = 0; i < length; i++) { - Object* element = elements->get(i); - if (element->IsTheHole()) { - failure = true; - break; - } - int32_t int_value = Smi::cast(element)->value(); - double_storage->set(j, int_value); - j++; - } - break; - } - case FAST_HOLEY_ELEMENTS: - ASSERT_EQ(0, length); - break; - default: - UNREACHABLE(); - } - } - if (failure) break; - } - Handle<JSArray> array = isolate->factory()->NewJSArray(0); - Smi* length = Smi::FromInt(j); - Handle<Map> map; - map = isolate->factory()->GetElementsTransitionMap(array, kind); - array->set_map(*map); - array->set_length(length); - array->set_elements(*double_storage); - return *array; - } - // The backing storage array must have non-existing elements to preserve - // holes across concat operations. + // The backing storage array must have non-existing elements to + // preserve holes across concat operations. storage = isolate->factory()->NewFixedArrayWithHoles( estimate_result_length); } else { @@ -10046,8 +9956,8 @@ static MaybeObject* DebugLookupResultValue(Heap* heap, return value; case FIELD: value = - JSObject::cast(result->holder())->FastPropertyAt( - result->GetFieldIndex().field_index()); + JSObject::cast( + result->holder())->FastPropertyAt(result->GetFieldIndex()); if (value->IsTheHole()) { return heap->undefined_value(); } @@ -10686,8 +10596,7 @@ static bool CopyContextLocalsToScopeObject( RETURN_IF_EMPTY_HANDLE_VALUE( isolate, - SetProperty(isolate, - scope_object, + SetProperty(scope_object, Handle<String>(scope_info->ContextLocalName(i)), Handle<Object>(context->get(context_index), isolate), NONE, @@ -10722,8 +10631,7 @@ static Handle<JSObject> MaterializeLocalScopeWithFrameInspector( RETURN_IF_EMPTY_HANDLE_VALUE( isolate, - SetProperty(isolate, - local_scope, + SetProperty(local_scope, Handle<String>(scope_info->ParameterName(i)), value, NONE, @@ -10735,8 +10643,7 @@ static Handle<JSObject> MaterializeLocalScopeWithFrameInspector( for (int i = 0; i < scope_info->StackLocalCount(); ++i) { RETURN_IF_EMPTY_HANDLE_VALUE( isolate, - SetProperty(isolate, - local_scope, + SetProperty(local_scope, Handle<String>(scope_info->StackLocalName(i)), Handle<Object>(frame_inspector->GetExpression(i)), NONE, @@ -10770,8 +10677,7 @@ static Handle<JSObject> MaterializeLocalScopeWithFrameInspector( Handle<String> key(String::cast(keys->get(i))); RETURN_IF_EMPTY_HANDLE_VALUE( isolate, - SetProperty(isolate, - local_scope, + SetProperty(local_scope, key, GetProperty(ext, key), NONE, @@ -10832,8 +10738,7 @@ static Handle<JSObject> MaterializeClosure(Isolate* isolate, Handle<String> key(String::cast(keys->get(i))); RETURN_IF_EMPTY_HANDLE_VALUE( isolate, - SetProperty(isolate, - closure_scope, + SetProperty(closure_scope, key, GetProperty(ext, key), NONE, @@ -10846,52 +10751,6 @@ static Handle<JSObject> MaterializeClosure(Isolate* isolate, } -// This method copies structure of MaterializeClosure method above. -static bool SetClosureVariableValue(Isolate* isolate, - Handle<Context> context, - Handle<String> variable_name, - Handle<Object> new_value) { - ASSERT(context->IsFunctionContext()); - - Handle<SharedFunctionInfo> shared(context->closure()->shared()); - Handle<ScopeInfo> scope_info(shared->scope_info()); - - // Context locals to the context extension. - for (int i = 0; i < scope_info->ContextLocalCount(); i++) { - Handle<String> next_name(scope_info->ContextLocalName(i)); - if (variable_name->Equals(*next_name)) { - VariableMode mode; - InitializationFlag init_flag; - int context_index = - scope_info->ContextSlotIndex(*next_name, &mode, &init_flag); - if (context_index < 0) { - return false; - } - context->set(context_index, *new_value); - return true; - } - } - - // Properties from the function context extension. This will - // be variables introduced by eval. - if (context->has_extension()) { - Handle<JSObject> ext(JSObject::cast(context->extension())); - if (ext->HasProperty(*variable_name)) { - // We don't expect this to do anything except replacing property value. - SetProperty(isolate, - ext, - variable_name, - new_value, - NONE, - kNonStrictMode); - return true; - } - } - - return false; -} - - // Create a plain JSObject which materializes the scope for the specified // catch context. static Handle<JSObject> MaterializeCatchScope(Isolate* isolate, @@ -10903,12 +10762,7 @@ static Handle<JSObject> MaterializeCatchScope(Isolate* isolate, isolate->factory()->NewJSObject(isolate->object_function()); RETURN_IF_EMPTY_HANDLE_VALUE( isolate, - SetProperty(isolate, - catch_scope, - name, - thrown_object, - NONE, - kNonStrictMode), + SetProperty(catch_scope, name, thrown_object, NONE, kNonStrictMode), Handle<JSObject>()); return catch_scope; } @@ -11172,33 +11026,6 @@ class ScopeIterator { return Handle<JSObject>(); } - bool SetVariableValue(Handle<String> variable_name, - Handle<Object> new_value) { - ASSERT(!failed_); - switch (Type()) { - case ScopeIterator::ScopeTypeGlobal: - break; - case ScopeIterator::ScopeTypeLocal: - // TODO(2399): implement. - break; - case ScopeIterator::ScopeTypeWith: - break; - case ScopeIterator::ScopeTypeCatch: - // TODO(2399): implement. - break; - case ScopeIterator::ScopeTypeClosure: - return SetClosureVariableValue(isolate_, CurrentContext(), - variable_name, new_value); - case ScopeIterator::ScopeTypeBlock: - // TODO(2399): should we implement it? - break; - case ScopeIterator::ScopeTypeModule: - // TODO(2399): should we implement it? - break; - } - return false; - } - Handle<ScopeInfo> CurrentScopeInfo() { ASSERT(!failed_); if (!nested_scope_chain_.is_empty()) { @@ -11438,64 +11265,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) { } -static bool SetScopeVariableValue(ScopeIterator* it, int index, - Handle<String> variable_name, - Handle<Object> new_value) { - for (int n = 0; !it->Done() && n < index; it->Next()) { - n++; - } - if (it->Done()) { - return false; - } - return it->SetVariableValue(variable_name, new_value); -} - - -// Change variable value in closure or local scope -// args[0]: number or JsFunction: break id or function -// args[1]: number: frame index (when arg[0] is break id) -// args[2]: number: inlined frame index (when arg[0] is break id) -// args[3]: number: scope index -// args[4]: string: variable name -// args[5]: object: new value -// -// Return true if success and false otherwise -RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) { - HandleScope scope(isolate); - ASSERT(args.length() == 6); - - // Check arguments. - CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]); - CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4); - Handle<Object> new_value = args.at<Object>(5); - - bool res; - if (args[0]->IsNumber()) { - Object* check; - { MaybeObject* maybe_check = Runtime_CheckExecutionState( - RUNTIME_ARGUMENTS(isolate, args)); - if (!maybe_check->ToObject(&check)) return maybe_check; - } - CONVERT_SMI_ARG_CHECKED(wrapped_id, 1); - CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]); - - // Get the frame where the debugging is performed. - StackFrame::Id id = UnwrapFrameId(wrapped_id); - JavaScriptFrameIterator frame_it(isolate, id); - JavaScriptFrame* frame = frame_it.frame(); - - ScopeIterator it(isolate, frame, inlined_jsframe_index); - res = SetScopeVariableValue(&it, index, variable_name, new_value); - } else { - CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0); - ScopeIterator it(isolate, fun); - res = SetScopeVariableValue(&it, index, variable_name, new_value); - } - - return isolate->heap()->ToBoolean(res); -} - - RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) { HandleScope scope(isolate); ASSERT(args.length() == 0); @@ -13080,6 +12849,47 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) { } +// Determines whether the given stack frame should be displayed in +// a stack trace. The caller is the error constructor that asked +// for the stack trace to be collected. The first time a construct +// call to this function is encountered it is skipped. The seen_caller +// in/out parameter is used to remember if the caller has been seen +// yet. +static bool ShowFrameInStackTrace(StackFrame* raw_frame, + Object* caller, + bool* seen_caller) { + // Only display JS frames. + if (!raw_frame->is_java_script()) { + return false; + } + JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); + Object* raw_fun = frame->function(); + // Not sure when this can happen but skip it just in case. + if (!raw_fun->IsJSFunction()) { + return false; + } + if ((raw_fun == caller) && !(*seen_caller)) { + *seen_caller = true; + return false; + } + // Skip all frames until we've seen the caller. + if (!(*seen_caller)) return false; + // Also, skip non-visible built-in functions and any call with the builtins + // object as receiver, so as to not reveal either the builtins object or + // an internal function. + // The --builtins-in-stack-traces command line flag allows including + // internal call sites in the stack trace for debugging purposes. + if (!FLAG_builtins_in_stack_traces) { + JSFunction* fun = JSFunction::cast(raw_fun); + if (frame->receiver()->IsJSBuiltinsObject() || + (fun->IsBuiltin() && !fun->shared()->native())) { + return false; + } + } + return true; +} + + // Collect the raw data for a stack trace. Returns an array of 4 // element segments each containing a receiver, function, code and // native code offset. @@ -13090,23 +12900,57 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) { CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]); HandleScope scope(isolate); - // Optionally capture a more detailed stack trace for the message. - isolate->CaptureAndSetDetailedStackTrace(error_object); - // Capture a simple stack trace for the stack property. - return *isolate->CaptureSimpleStackTrace(error_object, caller, limit); -} + Factory* factory = isolate->factory(); + limit = Max(limit, 0); // Ensure that limit is not negative. + int initial_size = Min(limit, 10); + Handle<FixedArray> elements = + factory->NewFixedArrayWithHoles(initial_size * 4); -// Retrieve the raw stack trace collected on stack overflow and delete -// it since it is used only once to avoid keeping it alive. -RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOverflowedRawStackTrace) { - ASSERT_EQ(args.length(), 1); - CONVERT_ARG_CHECKED(JSObject, error_object, 0); - String* key = isolate->heap()->hidden_stack_trace_symbol(); - Object* result = error_object->GetHiddenProperty(key); - RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined()); - error_object->DeleteHiddenProperty(key); - return result; + StackFrameIterator iter(isolate); + // If the caller parameter is a function we skip frames until we're + // under it before starting to collect. + bool seen_caller = !caller->IsJSFunction(); + int cursor = 0; + int frames_seen = 0; + while (!iter.done() && frames_seen < limit) { + StackFrame* raw_frame = iter.frame(); + if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) { + frames_seen++; + JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); + // Set initial size to the maximum inlining level + 1 for the outermost + // function. + List<FrameSummary> frames(Compiler::kMaxInliningLevels + 1); + frame->Summarize(&frames); + for (int i = frames.length() - 1; i >= 0; i--) { + if (cursor + 4 > elements->length()) { + int new_capacity = JSObject::NewElementsCapacity(elements->length()); + Handle<FixedArray> new_elements = + factory->NewFixedArrayWithHoles(new_capacity); + for (int i = 0; i < cursor; i++) { + new_elements->set(i, elements->get(i)); + } + elements = new_elements; + } + ASSERT(cursor + 4 <= elements->length()); + + Handle<Object> recv = frames[i].receiver(); + Handle<JSFunction> fun = frames[i].function(); + Handle<Code> code = frames[i].code(); + Handle<Smi> offset(Smi::FromInt(frames[i].offset())); + elements->set(cursor++, *recv); + elements->set(cursor++, *fun); + elements->set(cursor++, *code); + elements->set(cursor++, *offset); + } + } + iter.Advance(); + } + Handle<JSArray> result = factory->NewJSArrayWithElements(elements); + // Capture and attach a more detailed stack trace if necessary. + isolate->CaptureAndSetCurrentStackTraceFor(error_object); + result->set_length(Smi::FromInt(cursor)); + return *result; } @@ -13118,7 +12962,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) { const char* version_string = v8::V8::GetVersion(); - return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string), + return isolate->heap()->AllocateStringFromAscii(CStrVector(version_string), NOT_TENURED); } @@ -13230,6 +13074,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) { } +RUNTIME_FUNCTION(MaybeObject*, Runtime_NewMessageObject) { + HandleScope scope(isolate); + CONVERT_ARG_HANDLE_CHECKED(String, type, 0); + CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 1); + return *isolate->factory()->NewJSMessageObject( + type, + arguments, + 0, + 0, + isolate->factory()->undefined_value(), + isolate->factory()->undefined_value(), + isolate->factory()->undefined_value()); +} + + +RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetType) { + CONVERT_ARG_CHECKED(JSMessageObject, message, 0); + return message->type(); +} + + +RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetArguments) { + CONVERT_ARG_CHECKED(JSMessageObject, message, 0); + return message->arguments(); +} + + RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) { CONVERT_ARG_CHECKED(JSMessageObject, message, 0); return Smi::FromInt(message->start_position()); @@ -13342,88 +13213,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) { return isolate->heap()->ToBoolean(obj1->map() == obj2->map()); } - -RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) { - ASSERT(args.length() == 1); - CONVERT_ARG_CHECKED(JSReceiver, obj, 0); - if (obj->IsJSGlobalProxy()) { - Object* proto = obj->GetPrototype(); - if (obj->IsNull()) return isolate->heap()->false_value(); - ASSERT(proto->IsJSGlobalObject()); - obj = JSReceiver::cast(proto); - } - return isolate->heap()->ToBoolean(obj->map()->is_observed()); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) { - ASSERT(args.length() == 2); - CONVERT_ARG_CHECKED(JSReceiver, obj, 0); - CONVERT_BOOLEAN_ARG_CHECKED(is_observed, 1); - if (obj->IsJSGlobalProxy()) { - Object* proto = obj->GetPrototype(); - if (obj->IsNull()) return isolate->heap()->undefined_value(); - ASSERT(proto->IsJSGlobalObject()); - obj = JSReceiver::cast(proto); - } - if (obj->map()->is_observed() != is_observed) { - MaybeObject* maybe = obj->map()->Copy(); - Map* map; - if (!maybe->To(&map)) return maybe; - map->set_is_observed(is_observed); - obj->set_map(map); - } - return isolate->heap()->undefined_value(); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_SetObserverDeliveryPending) { - ASSERT(args.length() == 0); - isolate->set_observer_delivery_pending(true); - return isolate->heap()->undefined_value(); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) { - ASSERT(args.length() == 0); - return isolate->heap()->observation_state(); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectHashTable) { - ASSERT(args.length() == 0); - return ObjectHashTable::Allocate(0); -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectHashTableGet) { - NoHandleAllocation ha; - ASSERT(args.length() == 2); - CONVERT_ARG_CHECKED(ObjectHashTable, table, 0); - Object* key = args[1]; - if (key->IsJSGlobalProxy()) { - key = key->GetPrototype(); - if (key->IsNull()) return isolate->heap()->undefined_value(); - } - Object* lookup = table->Lookup(key); - return lookup->IsTheHole() ? isolate->heap()->undefined_value() : lookup; -} - - -RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectHashTableSet) { - HandleScope scope(isolate); - ASSERT(args.length() == 3); - CONVERT_ARG_HANDLE_CHECKED(ObjectHashTable, table, 0); - Handle<Object> key = args.at<Object>(1); - if (key->IsJSGlobalProxy()) { - key = handle(key->GetPrototype(), isolate); - if (key->IsNull()) return *table; - } - Handle<Object> value = args.at<Object>(2); - return *PutIntoObjectHashTable(table, key, value); -} - - // ---------------------------------------------------------------------------- // Implementation of Runtime |