| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 738942c471424b414b0dbc98bad92176d652dab8..cffb2c78abb6ba191b64a741a7981ebeff52cc8f 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -32,6 +32,7 @@
|
| #include "accessors.h"
|
| #include "api.h"
|
| #include "arguments.h"
|
| +#include "bootstrapper.h"
|
| #include "codegen.h"
|
| #include "compilation-cache.h"
|
| #include "compiler.h"
|
| @@ -1149,22 +1150,14 @@ static Failure* ThrowRedeclarationError(Isolate* isolate,
|
|
|
|
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
|
| - ASSERT(args.length() == 4);
|
| + ASSERT(args.length() == 3);
|
| HandleScope scope(isolate);
|
| Handle<GlobalObject> global = Handle<GlobalObject>(
|
| isolate->context()->global());
|
|
|
| Handle<Context> context = args.at<Context>(0);
|
| CONVERT_ARG_CHECKED(FixedArray, pairs, 1);
|
| - bool is_eval = args.smi_at(2) == 1;
|
| - StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(3));
|
| - ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode);
|
| -
|
| - // Compute the property attributes. According to ECMA-262, section
|
| - // 13, page 71, the property must be read-only and
|
| - // non-deletable. However, neither SpiderMonkey nor KJS creates the
|
| - // property as read-only, so we don't either.
|
| - PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
|
| + CONVERT_SMI_ARG_CHECKED(flags, 2);
|
|
|
| // Traverse the name/value pairs and set the properties.
|
| int length = pairs->length();
|
| @@ -1177,7 +1170,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
|
| // assign to it when evaluating the assignment for "const x =
|
| // <expr>" the initial value is the hole.
|
| bool is_const_property = value->IsTheHole();
|
| -
|
| + bool is_function_declaration = false;
|
| if (value->IsUndefined() || is_const_property) {
|
| // Lookup the property in the global object, and don't set the
|
| // value of the variable if the property is already there.
|
| @@ -1226,6 +1219,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
|
| }
|
| }
|
| } else {
|
| + is_function_declaration = true;
|
| // Copy the function and update its context. Use it as value.
|
| Handle<SharedFunctionInfo> shared =
|
| Handle<SharedFunctionInfo>::cast(value);
|
| @@ -1239,10 +1233,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
|
| LookupResult lookup;
|
| global->LocalLookup(*name, &lookup);
|
|
|
| - PropertyAttributes attributes = is_const_property
|
| - ? static_cast<PropertyAttributes>(base | READ_ONLY)
|
| - : base;
|
| -
|
| // There's a local property that we need to overwrite because
|
| // we're either declaring a function or there's an interceptor
|
| // that claims the property is absent.
|
| @@ -1257,6 +1247,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
|
| return ThrowRedeclarationError(isolate, type, name);
|
| }
|
|
|
| + // Compute the property attributes. According to ECMA-262, section
|
| + // 13, page 71, the property must be read-only and
|
| + // non-deletable. However, neither SpiderMonkey nor KJS creates the
|
| + // property as read-only, so we don't either.
|
| + int attr = NONE;
|
| + if ((flags & kDeclareGlobalsEvalFlag) == 0) {
|
| + attr |= DONT_DELETE;
|
| + }
|
| + bool is_native = (flags & kDeclareGlobalsNativeFlag) != 0;
|
| + if (is_const_property || (is_native && is_function_declaration)) {
|
| + attr |= READ_ONLY;
|
| + }
|
| +
|
| // Safari does not allow the invocation of callback setters for
|
| // function declarations. To mimic this behavior, we do not allow
|
| // the invocation of setters for function values. This makes a
|
| @@ -1267,20 +1270,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
|
| if (value->IsJSFunction()) {
|
| // Do not change DONT_DELETE to false from true.
|
| if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) {
|
| - attributes = static_cast<PropertyAttributes>(
|
| - attributes | (lookup.GetAttributes() & DONT_DELETE));
|
| + attr |= lookup.GetAttributes() & DONT_DELETE;
|
| }
|
| + PropertyAttributes attributes = static_cast<PropertyAttributes>(attr);
|
| +
|
| RETURN_IF_EMPTY_HANDLE(isolate,
|
| SetLocalPropertyIgnoreAttributes(global,
|
| name,
|
| value,
|
| attributes));
|
| } else {
|
| + StrictModeFlag strict_mode =
|
| + ((flags & kDeclareGlobalsStrictModeFlag) != 0) ? kStrictMode
|
| + : kNonStrictMode;
|
| RETURN_IF_EMPTY_HANDLE(isolate,
|
| SetProperty(global,
|
| name,
|
| value,
|
| - attributes,
|
| + static_cast<PropertyAttributes>(attr),
|
| strict_mode));
|
| }
|
| }
|
| @@ -1306,8 +1313,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
|
| + BindingFlags binding_flags;
|
| Handle<Object> holder =
|
| - context->Lookup(name, flags, &index, &attributes);
|
| + context->Lookup(name, flags, &index, &attributes, &binding_flags);
|
|
|
| if (attributes != ABSENT) {
|
| // The name was declared before; check for conflicting
|
| @@ -1594,8 +1602,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = FOLLOW_CHAINS;
|
| + BindingFlags binding_flags;
|
| Handle<Object> holder =
|
| - context->Lookup(name, flags, &index, &attributes);
|
| + context->Lookup(name, flags, &index, &attributes, &binding_flags);
|
|
|
| // In most situations, the property introduced by the const
|
| // declaration should be present in the context extension object.
|
| @@ -1866,10 +1875,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
|
| }
|
|
|
|
|
| -RUNTIME_FUNCTION(MaybeObject*, Runtime_GetGlobalReceiver) {
|
| - // Returns a real global receiver, not one of builtins object.
|
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
|
| + NoHandleAllocation handle_free;
|
| + ASSERT(args.length() == 1);
|
| + CONVERT_CHECKED(JSFunction, function, args[0]);
|
| + SharedFunctionInfo* shared = function->shared();
|
| + if (shared->native() || shared->strict_mode()) {
|
| + return isolate->heap()->undefined_value();
|
| + }
|
| + // Returns undefined for strict or native functions, or
|
| + // the associated global receiver for "normal" functions.
|
| +
|
| Context* global_context =
|
| - isolate->context()->global()->global_context();
|
| + function->context()->global()->global_context();
|
| return global_context->global()->global_receiver();
|
| }
|
|
|
| @@ -2136,6 +2154,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
|
|
|
|
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
|
| + RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
|
| HandleScope scope(isolate);
|
| ASSERT(args.length() == 2);
|
|
|
| @@ -2486,7 +2505,7 @@ class ReplacementStringBuilder {
|
| class CompiledReplacement {
|
| public:
|
| CompiledReplacement()
|
| - : parts_(1), replacement_substrings_(0) {}
|
| + : parts_(1), replacement_substrings_(0), simple_hint_(false) {}
|
|
|
| void Compile(Handle<String> replacement,
|
| int capture_count,
|
| @@ -2502,6 +2521,10 @@ class CompiledReplacement {
|
| return parts_.length();
|
| }
|
|
|
| + bool simple_hint() {
|
| + return simple_hint_;
|
| + }
|
| +
|
| private:
|
| enum PartType {
|
| SUBJECT_PREFIX = 1,
|
| @@ -2560,7 +2583,7 @@ class CompiledReplacement {
|
| };
|
|
|
| template<typename Char>
|
| - static void ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
|
| + static bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
|
| Vector<Char> characters,
|
| int capture_count,
|
| int subject_length) {
|
| @@ -2657,14 +2680,17 @@ class CompiledReplacement {
|
| if (length > last) {
|
| if (last == 0) {
|
| parts->Add(ReplacementPart::ReplacementString());
|
| + return true;
|
| } else {
|
| parts->Add(ReplacementPart::ReplacementSubString(last, length));
|
| }
|
| }
|
| + return false;
|
| }
|
|
|
| ZoneList<ReplacementPart> parts_;
|
| ZoneList<Handle<String> > replacement_substrings_;
|
| + bool simple_hint_;
|
| };
|
|
|
|
|
| @@ -2676,16 +2702,16 @@ void CompiledReplacement::Compile(Handle<String> replacement,
|
| String::FlatContent content = replacement->GetFlatContent();
|
| ASSERT(content.IsFlat());
|
| if (content.IsAscii()) {
|
| - ParseReplacementPattern(&parts_,
|
| - content.ToAsciiVector(),
|
| - capture_count,
|
| - subject_length);
|
| + simple_hint_ = ParseReplacementPattern(&parts_,
|
| + content.ToAsciiVector(),
|
| + capture_count,
|
| + subject_length);
|
| } else {
|
| ASSERT(content.IsTwoByte());
|
| - ParseReplacementPattern(&parts_,
|
| - content.ToUC16Vector(),
|
| - capture_count,
|
| - subject_length);
|
| + simple_hint_ = ParseReplacementPattern(&parts_,
|
| + content.ToUC16Vector(),
|
| + capture_count,
|
| + subject_length);
|
| }
|
| }
|
| Isolate* isolate = replacement->GetIsolate();
|
| @@ -2748,6 +2774,170 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
|
| }
|
|
|
|
|
| +void FindAsciiStringIndices(Vector<const char> subject,
|
| + char pattern,
|
| + ZoneList<int>* indices,
|
| + unsigned int limit) {
|
| + ASSERT(limit > 0);
|
| + // Collect indices of pattern in subject using memchr.
|
| + // Stop after finding at most limit values.
|
| + const char* subject_start = reinterpret_cast<const char*>(subject.start());
|
| + const char* subject_end = subject_start + subject.length();
|
| + const char* pos = subject_start;
|
| + while (limit > 0) {
|
| + pos = reinterpret_cast<const char*>(
|
| + memchr(pos, pattern, subject_end - pos));
|
| + if (pos == NULL) return;
|
| + indices->Add(static_cast<int>(pos - subject_start));
|
| + pos++;
|
| + limit--;
|
| + }
|
| +}
|
| +
|
| +
|
| +template <typename SubjectChar, typename PatternChar>
|
| +void FindStringIndices(Isolate* isolate,
|
| + Vector<const SubjectChar> subject,
|
| + Vector<const PatternChar> pattern,
|
| + ZoneList<int>* indices,
|
| + unsigned int limit) {
|
| + ASSERT(limit > 0);
|
| + // Collect indices of pattern in subject.
|
| + // Stop after finding at most limit values.
|
| + int pattern_length = pattern.length();
|
| + int index = 0;
|
| + StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
|
| + while (limit > 0) {
|
| + index = search.Search(subject, index);
|
| + if (index < 0) return;
|
| + indices->Add(index);
|
| + index += pattern_length;
|
| + limit--;
|
| + }
|
| +}
|
| +
|
| +
|
| +void FindStringIndicesDispatch(Isolate* isolate,
|
| + String* subject,
|
| + String* pattern,
|
| + ZoneList<int>* indices,
|
| + unsigned int limit) {
|
| + {
|
| + AssertNoAllocation no_gc;
|
| + String::FlatContent subject_content = subject->GetFlatContent();
|
| + String::FlatContent pattern_content = pattern->GetFlatContent();
|
| + ASSERT(subject_content.IsFlat());
|
| + ASSERT(pattern_content.IsFlat());
|
| + if (subject_content.IsAscii()) {
|
| + Vector<const char> subject_vector = subject_content.ToAsciiVector();
|
| + if (pattern_content.IsAscii()) {
|
| + Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
|
| + if (pattern_vector.length() == 1) {
|
| + FindAsciiStringIndices(subject_vector,
|
| + pattern_vector[0],
|
| + indices,
|
| + limit);
|
| + } else {
|
| + FindStringIndices(isolate,
|
| + subject_vector,
|
| + pattern_vector,
|
| + indices,
|
| + limit);
|
| + }
|
| + } else {
|
| + FindStringIndices(isolate,
|
| + subject_vector,
|
| + pattern_content.ToUC16Vector(),
|
| + indices,
|
| + limit);
|
| + }
|
| + } else {
|
| + Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
|
| + if (pattern->IsAsciiRepresentation()) {
|
| + FindStringIndices(isolate,
|
| + subject_vector,
|
| + pattern_content.ToAsciiVector(),
|
| + indices,
|
| + limit);
|
| + } else {
|
| + FindStringIndices(isolate,
|
| + subject_vector,
|
| + pattern_content.ToUC16Vector(),
|
| + indices,
|
| + limit);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +template<typename ResultSeqString>
|
| +MUST_USE_RESULT static MaybeObject* StringReplaceStringWithString(
|
| + Isolate* isolate,
|
| + Handle<String> subject,
|
| + Handle<JSRegExp> pattern_regexp,
|
| + Handle<String> replacement) {
|
| + ASSERT(subject->IsFlat());
|
| + ASSERT(replacement->IsFlat());
|
| +
|
| + ZoneScope zone_space(isolate, DELETE_ON_EXIT);
|
| + ZoneList<int> indices(8);
|
| + ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
|
| + String* pattern =
|
| + String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
|
| + int subject_len = subject->length();
|
| + int pattern_len = pattern->length();
|
| + int replacement_len = replacement->length();
|
| +
|
| + FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff);
|
| +
|
| + int matches = indices.length();
|
| + if (matches == 0) return *subject;
|
| +
|
| + int result_len = (replacement_len - pattern_len) * matches + subject_len;
|
| + int subject_pos = 0;
|
| + int result_pos = 0;
|
| +
|
| + Handle<ResultSeqString> result;
|
| + if (ResultSeqString::kHasAsciiEncoding) {
|
| + result = Handle<ResultSeqString>::cast(
|
| + isolate->factory()->NewRawAsciiString(result_len));
|
| + } else {
|
| + result = Handle<ResultSeqString>::cast(
|
| + isolate->factory()->NewRawTwoByteString(result_len));
|
| + }
|
| +
|
| + for (int i = 0; i < matches; i++) {
|
| + // Copy non-matched subject content.
|
| + if (subject_pos < indices.at(i)) {
|
| + String::WriteToFlat(*subject,
|
| + result->GetChars() + result_pos,
|
| + subject_pos,
|
| + indices.at(i));
|
| + result_pos += indices.at(i) - subject_pos;
|
| + }
|
| +
|
| + // Replace match.
|
| + if (replacement_len > 0) {
|
| + String::WriteToFlat(*replacement,
|
| + result->GetChars() + result_pos,
|
| + 0,
|
| + replacement_len);
|
| + result_pos += replacement_len;
|
| + }
|
| +
|
| + subject_pos = indices.at(i) + pattern_len;
|
| + }
|
| + // Add remaining subject content at the end.
|
| + if (subject_pos < subject_len) {
|
| + String::WriteToFlat(*subject,
|
| + result->GetChars() + result_pos,
|
| + subject_pos,
|
| + subject_len);
|
| + }
|
| + return *result;
|
| +}
|
| +
|
|
|
| MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
|
| Isolate* isolate,
|
| @@ -2787,6 +2977,20 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
|
|
|
| bool is_global = regexp_handle->GetFlags().is_global();
|
|
|
| + // Shortcut for simple non-regexp global replacements
|
| + if (is_global &&
|
| + regexp->TypeTag() == JSRegExp::ATOM &&
|
| + compiled_replacement.simple_hint()) {
|
| + if (subject_handle->HasOnlyAsciiChars() &&
|
| + replacement_handle->HasOnlyAsciiChars()) {
|
| + return StringReplaceStringWithString<SeqAsciiString>(
|
| + isolate, subject_handle, regexp_handle, replacement_handle);
|
| + } else {
|
| + return StringReplaceStringWithString<SeqTwoByteString>(
|
| + isolate, subject_handle, regexp_handle, replacement_handle);
|
| + }
|
| + }
|
| +
|
| // Guessing the number of parts that the final result string is built
|
| // from. Global regexps can match any number of times, so we guess
|
| // conservatively.
|
| @@ -2872,6 +3076,20 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
|
|
|
| Handle<String> subject_handle(subject);
|
| Handle<JSRegExp> regexp_handle(regexp);
|
| +
|
| + // Shortcut for simple non-regexp global replacements
|
| + if (regexp_handle->GetFlags().is_global() &&
|
| + regexp_handle->TypeTag() == JSRegExp::ATOM) {
|
| + Handle<String> empty_string_handle(HEAP->empty_string());
|
| + if (subject_handle->HasOnlyAsciiChars()) {
|
| + return StringReplaceStringWithString<SeqAsciiString>(
|
| + isolate, subject_handle, regexp_handle, empty_string_handle);
|
| + } else {
|
| + return StringReplaceStringWithString<SeqTwoByteString>(
|
| + isolate, subject_handle, regexp_handle, empty_string_handle);
|
| + }
|
| + }
|
| +
|
| Handle<JSArray> last_match_info_handle(last_match_info);
|
| Handle<Object> match = RegExpImpl::Exec(regexp_handle,
|
| subject_handle,
|
| @@ -3675,7 +3893,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
|
| HandleScope handles(isolate);
|
|
|
| CONVERT_ARG_CHECKED(String, subject, 1);
|
| - if (!subject->IsFlat()) { FlattenString(subject); }
|
| + if (!subject->IsFlat()) FlattenString(subject);
|
| CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
|
| CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
|
| CONVERT_ARG_CHECKED(JSArray, result_array, 3);
|
| @@ -5912,49 +6130,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
|
| }
|
|
|
|
|
| -void FindAsciiStringIndices(Vector<const char> subject,
|
| - char pattern,
|
| - ZoneList<int>* indices,
|
| - unsigned int limit) {
|
| - ASSERT(limit > 0);
|
| - // Collect indices of pattern in subject using memchr.
|
| - // Stop after finding at most limit values.
|
| - const char* subject_start = reinterpret_cast<const char*>(subject.start());
|
| - const char* subject_end = subject_start + subject.length();
|
| - const char* pos = subject_start;
|
| - while (limit > 0) {
|
| - pos = reinterpret_cast<const char*>(
|
| - memchr(pos, pattern, subject_end - pos));
|
| - if (pos == NULL) return;
|
| - indices->Add(static_cast<int>(pos - subject_start));
|
| - pos++;
|
| - limit--;
|
| - }
|
| -}
|
| -
|
| -
|
| -template <typename SubjectChar, typename PatternChar>
|
| -void FindStringIndices(Isolate* isolate,
|
| - Vector<const SubjectChar> subject,
|
| - Vector<const PatternChar> pattern,
|
| - ZoneList<int>* indices,
|
| - unsigned int limit) {
|
| - ASSERT(limit > 0);
|
| - // Collect indices of pattern in subject.
|
| - // Stop after finding at most limit values.
|
| - int pattern_length = pattern.length();
|
| - int index = 0;
|
| - StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
|
| - while (limit > 0) {
|
| - index = search.Search(subject, index);
|
| - if (index < 0) return;
|
| - indices->Add(index);
|
| - index += pattern_length;
|
| - limit--;
|
| - }
|
| -}
|
| -
|
| -
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
|
| ASSERT(args.length() == 3);
|
| HandleScope handle_scope(isolate);
|
| @@ -5966,6 +6141,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
|
| int pattern_length = pattern->length();
|
| RUNTIME_ASSERT(pattern_length > 0);
|
|
|
| + if (limit == 0xffffffffu) {
|
| + Handle<Object> cached_answer(StringSplitCache::Lookup(
|
| + isolate->heap()->string_split_cache(),
|
| + *subject,
|
| + *pattern));
|
| + if (*cached_answer != Smi::FromInt(0)) {
|
| + Handle<JSArray> result =
|
| + isolate->factory()->NewJSArrayWithElements(
|
| + Handle<FixedArray>::cast(cached_answer));
|
| + return *result;
|
| + }
|
| + }
|
| +
|
| // The limit can be very large (0xffffffffu), but since the pattern
|
| // isn't empty, we can never create more parts than ~half the length
|
| // of the subject.
|
| @@ -5981,53 +6169,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
|
| ZoneList<int> indices(initial_capacity);
|
| if (!pattern->IsFlat()) FlattenString(pattern);
|
|
|
| - // No allocation block.
|
| - {
|
| - AssertNoAllocation no_gc;
|
| - String::FlatContent subject_content = subject->GetFlatContent();
|
| - String::FlatContent pattern_content = pattern->GetFlatContent();
|
| - ASSERT(subject_content.IsFlat());
|
| - ASSERT(pattern_content.IsFlat());
|
| - if (subject_content.IsAscii()) {
|
| - Vector<const char> subject_vector = subject_content.ToAsciiVector();
|
| - if (pattern_content.IsAscii()) {
|
| - Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
|
| - if (pattern_vector.length() == 1) {
|
| - FindAsciiStringIndices(subject_vector,
|
| - pattern_vector[0],
|
| - &indices,
|
| - limit);
|
| - } else {
|
| - FindStringIndices(isolate,
|
| - subject_vector,
|
| - pattern_vector,
|
| - &indices,
|
| - limit);
|
| - }
|
| - } else {
|
| - FindStringIndices(isolate,
|
| - subject_vector,
|
| - pattern_content.ToUC16Vector(),
|
| - &indices,
|
| - limit);
|
| - }
|
| - } else {
|
| - Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
|
| - if (pattern->IsAsciiRepresentation()) {
|
| - FindStringIndices(isolate,
|
| - subject_vector,
|
| - pattern_content.ToAsciiVector(),
|
| - &indices,
|
| - limit);
|
| - } else {
|
| - FindStringIndices(isolate,
|
| - subject_vector,
|
| - pattern_content.ToUC16Vector(),
|
| - &indices,
|
| - limit);
|
| - }
|
| - }
|
| - }
|
| + FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit);
|
|
|
| if (static_cast<uint32_t>(indices.length()) < limit) {
|
| indices.Add(subject_length);
|
| @@ -6059,6 +6201,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
|
| part_start = part_end + pattern_length;
|
| }
|
|
|
| + if (limit == 0xffffffffu) {
|
| + if (result->HasFastElements()) {
|
| + StringSplitCache::Enter(isolate->heap(),
|
| + isolate->heap()->string_split_cache(),
|
| + *subject,
|
| + *pattern,
|
| + *elements);
|
| + }
|
| + }
|
| +
|
| return *result;
|
| }
|
|
|
| @@ -8240,6 +8392,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
|
| }
|
|
|
|
|
| +RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
|
| + RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
|
| + return isolate->heap()->undefined_value();
|
| +}
|
| +
|
| +
|
| RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
|
| HandleScope scope(isolate);
|
| ASSERT(args.length() == 1);
|
| @@ -8378,7 +8536,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = FOLLOW_CHAINS;
|
| - Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
|
| + BindingFlags binding_flags;
|
| + Handle<Object> holder = context->Lookup(name,
|
| + flags,
|
| + &index,
|
| + &attributes,
|
| + &binding_flags);
|
|
|
| // If the slot was not found the result is true.
|
| if (holder.is_null()) {
|
| @@ -8480,7 +8643,12 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = FOLLOW_CHAINS;
|
| - Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
|
| + BindingFlags binding_flags;
|
| + Handle<Object> holder = context->Lookup(name,
|
| + flags,
|
| + &index,
|
| + &attributes,
|
| + &binding_flags);
|
|
|
| // If the index is non-negative, the slot has been found in a local
|
| // variable or a parameter. Read it from the context object or the
|
| @@ -8496,7 +8664,17 @@ static ObjectPair LoadContextSlotHelper(Arguments args,
|
| MaybeObject* value = (holder->IsContext())
|
| ? Context::cast(*holder)->get(index)
|
| : JSObject::cast(*holder)->GetElement(index);
|
| - return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
|
| + // Check for uninitialized bindings.
|
| + if (holder->IsContext() &&
|
| + binding_flags == MUTABLE_CHECK_INITIALIZED &&
|
| + value->IsTheHole()) {
|
| + Handle<Object> reference_error =
|
| + isolate->factory()->NewReferenceError("not_defined",
|
| + HandleVector(&name, 1));
|
| + return MakePair(isolate->Throw(*reference_error), NULL);
|
| + } else {
|
| + return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
|
| + }
|
| }
|
|
|
| // If the holder is found, we read the property from it.
|
| @@ -8562,14 +8740,27 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
|
| int index;
|
| PropertyAttributes attributes;
|
| ContextLookupFlags flags = FOLLOW_CHAINS;
|
| - Handle<Object> holder = context->Lookup(name, flags, &index, &attributes);
|
| + BindingFlags binding_flags;
|
| + Handle<Object> holder = context->Lookup(name,
|
| + flags,
|
| + &index,
|
| + &attributes,
|
| + &binding_flags);
|
|
|
| if (index >= 0) {
|
| if (holder->IsContext()) {
|
| + Handle<Context> context = Handle<Context>::cast(holder);
|
| + if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
|
| + context->get(index)->IsTheHole()) {
|
| + Handle<Object> error =
|
| + isolate->factory()->NewReferenceError("not_defined",
|
| + HandleVector(&name, 1));
|
| + return isolate->Throw(*error);
|
| + }
|
| // Ignore if read_only variable.
|
| if ((attributes & READ_ONLY) == 0) {
|
| // Context is a fixed array and set cannot fail.
|
| - Context::cast(*holder)->set(index, *value);
|
| + context->set(index, *value);
|
| } else if (strict_mode == kStrictMode) {
|
| // Setting read only property in strict mode.
|
| Handle<Object> error =
|
| @@ -9021,10 +9212,13 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
|
| // it is bound in the global context.
|
| int index = -1;
|
| PropertyAttributes attributes = ABSENT;
|
| + BindingFlags binding_flags;
|
| while (true) {
|
| receiver = context->Lookup(isolate->factory()->eval_symbol(),
|
| FOLLOW_PROTOTYPE_CHAIN,
|
| - &index, &attributes);
|
| + &index,
|
| + &attributes,
|
| + &binding_flags);
|
| // Stop search when eval is found or when the global context is
|
| // reached.
|
| if (attributes != ABSENT || context->IsGlobalContext()) break;
|
|
|