| Index: src/runtime.cc
|
| ===================================================================
|
| --- src/runtime.cc (revision 4955)
|
| +++ src/runtime.cc (working copy)
|
| @@ -52,6 +52,13 @@
|
| namespace internal {
|
|
|
|
|
| +RuntimeState::RuntimeState()
|
| + : algorithm_(SIMPLE_SEARCH) {
|
| + memset(bad_char_occurrence_, 0,
|
| + sizeof(bad_char_occurrence_[0]) * kBMAlphabetSize);
|
| +}
|
| +
|
| +
|
| #define RUNTIME_ASSERT(value) \
|
| if (!(value)) return Isolate::Current()->ThrowIllegalOperation();
|
|
|
| @@ -94,10 +101,7 @@
|
| RUNTIME_ASSERT(obj->IsNumber()); \
|
| type name = NumberTo##Type(obj);
|
|
|
| -// Non-reentrant string buffer for efficient general use in this file.
|
| -static StaticResource<StringInputBuffer> runtime_string_input_buffer;
|
|
|
| -
|
| static Object* DeepCopyBoilerplate(Heap* heap, JSObject* boilerplate) {
|
| StackLimitCheck check;
|
| if (check.HasOverflowed()) return Isolate::Current()->StackOverflow();
|
| @@ -1390,7 +1394,7 @@
|
| const char* name,
|
| Builtins::Name builtin_name) {
|
| Handle<String> key = Factory::LookupAsciiSymbol(name);
|
| - Handle<Code> code(Builtins::builtin(builtin_name));
|
| + Handle<Code> code(Isolate::Current()->builtins()->builtin(builtin_name));
|
| Handle<JSFunction> optimized = Factory::NewFunction(key,
|
| JS_OBJECT_TYPE,
|
| JSObject::kHeaderSize,
|
| @@ -2317,73 +2321,19 @@
|
| }
|
|
|
|
|
| -// Cap on the maximal shift in the Boyer-Moore implementation. By setting a
|
| -// limit, we can fix the size of tables.
|
| -static const int kBMMaxShift = 0xff;
|
| -// Reduce alphabet to this size.
|
| -static const int kBMAlphabetSize = 0x100;
|
| -// For patterns below this length, the skip length of Boyer-Moore is too short
|
| -// to compensate for the algorithmic overhead compared to simple brute force.
|
| -static const int kBMMinPatternLength = 5;
|
| -
|
| -// Holds the two buffers used by Boyer-Moore string search's Good Suffix
|
| -// shift. Only allows the last kBMMaxShift characters of the needle
|
| -// to be indexed.
|
| -class BMGoodSuffixBuffers {
|
| - public:
|
| - BMGoodSuffixBuffers() {}
|
| - inline void init(int needle_length) {
|
| - ASSERT(needle_length > 1);
|
| - int start = needle_length < kBMMaxShift ? 0 : needle_length - kBMMaxShift;
|
| - int len = needle_length - start;
|
| - biased_suffixes_ = suffixes_ - start;
|
| - biased_good_suffix_shift_ = good_suffix_shift_ - start;
|
| - for (int i = 0; i <= len; i++) {
|
| - good_suffix_shift_[i] = len;
|
| - }
|
| - }
|
| - inline int& suffix(int index) {
|
| - ASSERT(biased_suffixes_ + index >= suffixes_);
|
| - return biased_suffixes_[index];
|
| - }
|
| - inline int& shift(int index) {
|
| - ASSERT(biased_good_suffix_shift_ + index >= good_suffix_shift_);
|
| - return biased_good_suffix_shift_[index];
|
| - }
|
| - private:
|
| - int suffixes_[kBMMaxShift + 1];
|
| - int good_suffix_shift_[kBMMaxShift + 1];
|
| - int* biased_suffixes_;
|
| - int* biased_good_suffix_shift_;
|
| - DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers);
|
| -};
|
| -
|
| -// buffers reused by BoyerMoore
|
| -static int bad_char_occurrence[kBMAlphabetSize];
|
| -static BMGoodSuffixBuffers bmgs_buffers;
|
| -
|
| -// State of the string match tables.
|
| -// SIMPLE: No usable content in the buffers.
|
| -// BOYER_MOORE_HORSPOOL: The bad_char_occurences table has been populated.
|
| -// BOYER_MOORE: The bmgs_buffers tables have also been populated.
|
| -// Whenever starting with a new needle, one should call InitializeStringSearch
|
| -// to determine which search strategy to use, and in the case of a long-needle
|
| -// strategy, the call also initializes the algorithm to SIMPLE.
|
| -enum StringSearchAlgorithm { SIMPLE_SEARCH, BOYER_MOORE_HORSPOOL, BOYER_MOORE };
|
| -static StringSearchAlgorithm algorithm;
|
| -
|
| -
|
| // Compute the bad-char table for Boyer-Moore in the static buffer.
|
| template <typename pchar>
|
| -static void BoyerMoorePopulateBadCharTable(Vector<const pchar> pattern) {
|
| +static void BoyerMoorePopulateBadCharTable(RuntimeState* state,
|
| + Vector<const pchar> pattern) {
|
| + int* bad_char_occurrence = state->bad_char_occurrence();
|
| // Only preprocess at most kBMMaxShift last characters of pattern.
|
| - int start = pattern.length() < kBMMaxShift ? 0
|
| - : pattern.length() - kBMMaxShift;
|
| + int start = pattern.length() < RuntimeState::kBMMaxShift ? 0
|
| + : pattern.length() - RuntimeState::kBMMaxShift;
|
| // Run forwards to populate bad_char_table, so that *last* instance
|
| // of character equivalence class is the one registered.
|
| // Notice: Doesn't include the last character.
|
| int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1
|
| - : kBMAlphabetSize;
|
| + : RuntimeState::kBMAlphabetSize;
|
| if (start == 0) { // All patterns less than kBMMaxShift in length.
|
| memset(bad_char_occurrence, -1, table_size * sizeof(*bad_char_occurrence));
|
| } else {
|
| @@ -2393,16 +2343,18 @@
|
| }
|
| for (int i = start; i < pattern.length() - 1; i++) {
|
| pchar c = pattern[i];
|
| - int bucket = (sizeof(pchar) ==1) ? c : c % kBMAlphabetSize;
|
| + int bucket = (sizeof(pchar) ==1) ? c : c % RuntimeState::kBMAlphabetSize;
|
| bad_char_occurrence[bucket] = i;
|
| }
|
| }
|
|
|
|
|
| template <typename pchar>
|
| -static void BoyerMoorePopulateGoodSuffixTable(Vector<const pchar> pattern) {
|
| +static void BoyerMoorePopulateGoodSuffixTable(RuntimeState* state,
|
| + Vector<const pchar> pattern) {
|
| + RuntimeState::BMGoodSuffixBuffers& bmgs_buffers = *state->bmgs_buffers();
|
| int m = pattern.length();
|
| - int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
|
| + int start = m < RuntimeState::kBMMaxShift ? 0 : m - RuntimeState::kBMMaxShift;
|
| int len = m - start;
|
| // Compute Good Suffix tables.
|
| bmgs_buffers.init(m);
|
| @@ -2451,7 +2403,8 @@
|
|
|
|
|
| template <typename schar, typename pchar>
|
| -static inline int CharOccurrence(int char_code) {
|
| +static inline int CharOccurrence(RuntimeState* state, int char_code) {
|
| + int* bad_char_occurrence = state->bad_char_occurrence();
|
| if (sizeof(schar) == 1) {
|
| return bad_char_occurrence[char_code];
|
| }
|
| @@ -2461,7 +2414,7 @@
|
| }
|
| return bad_char_occurrence[char_code];
|
| }
|
| - return bad_char_occurrence[char_code % kBMAlphabetSize];
|
| + return bad_char_occurrence[char_code % RuntimeState::kBMAlphabetSize];
|
| }
|
|
|
|
|
| @@ -2469,11 +2422,12 @@
|
| // Uses only the bad-shift table of Boyer-Moore and only uses it
|
| // for the character compared to the last character of the needle.
|
| template <typename schar, typename pchar>
|
| -static int BoyerMooreHorspool(Vector<const schar> subject,
|
| +static int BoyerMooreHorspool(RuntimeState* state,
|
| + Vector<const schar> subject,
|
| Vector<const pchar> pattern,
|
| int start_index,
|
| bool* complete) {
|
| - ASSERT(algorithm <= BOYER_MOORE_HORSPOOL);
|
| + ASSERT(state->algorithm() <= RuntimeState::BOYER_MOORE_HORSPOOL);
|
| int n = subject.length();
|
| int m = pattern.length();
|
|
|
| @@ -2482,13 +2436,13 @@
|
| // How bad we are doing without a good-suffix table.
|
| int idx; // No matches found prior to this index.
|
| pchar last_char = pattern[m - 1];
|
| - int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(last_char);
|
| + int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(state, last_char);
|
| // Perform search
|
| for (idx = start_index; idx <= n - m;) {
|
| int j = m - 1;
|
| int c;
|
| while (last_char != (c = subject[idx + j])) {
|
| - int bc_occ = CharOccurrence<schar, pchar>(c);
|
| + int bc_occ = CharOccurrence<schar, pchar>(state, c);
|
| int shift = j - bc_occ;
|
| idx += shift;
|
| badness += 1 - shift; // at most zero, so badness cannot increase.
|
| @@ -2521,14 +2475,16 @@
|
|
|
|
|
| template <typename schar, typename pchar>
|
| -static int BoyerMooreIndexOf(Vector<const schar> subject,
|
| +static int BoyerMooreIndexOf(RuntimeState* state,
|
| + Vector<const schar> subject,
|
| Vector<const pchar> pattern,
|
| int idx) {
|
| - ASSERT(algorithm <= BOYER_MOORE);
|
| + ASSERT(state->algorithm() <= RuntimeState::BOYER_MOORE);
|
| + RuntimeState::BMGoodSuffixBuffers& bmgs_buffers = *state->bmgs_buffers();
|
| int n = subject.length();
|
| int m = pattern.length();
|
| // Only preprocess at most kBMMaxShift last characters of pattern.
|
| - int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
|
| + int start = m < RuntimeState::kBMMaxShift ? 0 : m - RuntimeState::kBMMaxShift;
|
|
|
| pchar last_char = pattern[m - 1];
|
| // Continue search from i.
|
| @@ -2536,7 +2492,7 @@
|
| int j = m - 1;
|
| schar c;
|
| while (last_char != (c = subject[idx + j])) {
|
| - int shift = j - CharOccurrence<schar, pchar>(c);
|
| + int shift = j - CharOccurrence<schar, pchar>(state, c);
|
| idx += shift;
|
| if (idx > n - m) {
|
| return -1;
|
| @@ -2548,10 +2504,10 @@
|
| } else if (j < start) {
|
| // we have matched more than our tables allow us to be smart about.
|
| // Fall back on BMH shift.
|
| - idx += m - 1 - CharOccurrence<schar, pchar>(last_char);
|
| + idx += m - 1 - CharOccurrence<schar, pchar>(state, last_char);
|
| } else {
|
| int gs_shift = bmgs_buffers.shift(j + 1); // Good suffix shift.
|
| - int bc_occ = CharOccurrence<schar, pchar>(c);
|
| + int bc_occ = CharOccurrence<schar, pchar>(state, c);
|
| int shift = j - bc_occ; // Bad-char shift.
|
| if (gs_shift > shift) {
|
| shift = gs_shift;
|
| @@ -2691,7 +2647,7 @@
|
|
|
| template <typename pchar>
|
| static inline StringSearchStrategy InitializeStringSearch(
|
| - Vector<const pchar> pat, bool ascii_subject) {
|
| + RuntimeState* state, Vector<const pchar> pat, bool ascii_subject) {
|
| ASSERT(pat.length() > 1);
|
| // We have an ASCII haystack and a non-ASCII needle. Check if there
|
| // really is a non-ASCII character in the needle and bail out if there
|
| @@ -2704,39 +2660,40 @@
|
| }
|
| }
|
| }
|
| - if (pat.length() < kBMMinPatternLength) {
|
| + if (pat.length() < RuntimeState::kBMMinPatternLength) {
|
| return SEARCH_SHORT;
|
| }
|
| - algorithm = SIMPLE_SEARCH;
|
| + state->set_algorithm(RuntimeState::SIMPLE_SEARCH);
|
| return SEARCH_LONG;
|
| }
|
|
|
|
|
| // Dispatch long needle searches to different algorithms.
|
| template <typename schar, typename pchar>
|
| -static int ComplexIndexOf(Vector<const schar> sub,
|
| +static int ComplexIndexOf(RuntimeState* state,
|
| + Vector<const schar> sub,
|
| Vector<const pchar> pat,
|
| int start_index) {
|
| - ASSERT(pat.length() >= kBMMinPatternLength);
|
| + ASSERT(pat.length() >= RuntimeState::kBMMinPatternLength);
|
| // Try algorithms in order of increasing setup cost and expected performance.
|
| bool complete;
|
| int idx = start_index;
|
| - switch (algorithm) {
|
| - case SIMPLE_SEARCH:
|
| + switch (state->algorithm()) {
|
| + case RuntimeState::SIMPLE_SEARCH:
|
| idx = SimpleIndexOf(sub, pat, idx, &complete);
|
| if (complete) return idx;
|
| - BoyerMoorePopulateBadCharTable(pat);
|
| - algorithm = BOYER_MOORE_HORSPOOL;
|
| + BoyerMoorePopulateBadCharTable(state, pat);
|
| + state->set_algorithm(RuntimeState::BOYER_MOORE_HORSPOOL);
|
| // FALLTHROUGH.
|
| - case BOYER_MOORE_HORSPOOL:
|
| - idx = BoyerMooreHorspool(sub, pat, idx, &complete);
|
| + case RuntimeState::BOYER_MOORE_HORSPOOL:
|
| + idx = BoyerMooreHorspool(state, sub, pat, idx, &complete);
|
| if (complete) return idx;
|
| // Build the Good Suffix table and continue searching.
|
| - BoyerMoorePopulateGoodSuffixTable(pat);
|
| - algorithm = BOYER_MOORE;
|
| + BoyerMoorePopulateGoodSuffixTable(state, pat);
|
| + state->set_algorithm(RuntimeState::BOYER_MOORE);
|
| // FALLTHROUGH.
|
| - case BOYER_MOORE:
|
| - return BoyerMooreIndexOf(sub, pat, idx);
|
| + case RuntimeState::BOYER_MOORE:
|
| + return BoyerMooreIndexOf(state, sub, pat, idx);
|
| }
|
| UNREACHABLE();
|
| return -1;
|
| @@ -2748,15 +2705,17 @@
|
| // strategy should only be computed once and then dispatch to different
|
| // loops.
|
| template <typename schar, typename pchar>
|
| -static int StringSearch(Vector<const schar> sub,
|
| +static int StringSearch(RuntimeState* state,
|
| + Vector<const schar> sub,
|
| Vector<const pchar> pat,
|
| int start_index) {
|
| bool ascii_subject = (sizeof(schar) == 1);
|
| - StringSearchStrategy strategy = InitializeStringSearch(pat, ascii_subject);
|
| + StringSearchStrategy strategy = InitializeStringSearch(state, pat,
|
| + ascii_subject);
|
| switch (strategy) {
|
| case SEARCH_FAIL: return -1;
|
| case SEARCH_SHORT: return SimpleIndexOf(sub, pat, start_index);
|
| - case SEARCH_LONG: return ComplexIndexOf(sub, pat, start_index);
|
| + case SEARCH_LONG: return ComplexIndexOf(state, sub, pat, start_index);
|
| }
|
| UNREACHABLE();
|
| return -1;
|
| @@ -2771,6 +2730,7 @@
|
| int start_index) {
|
| ASSERT(0 <= start_index);
|
| ASSERT(start_index <= sub->length());
|
| + Isolate* isolate = Isolate::Current();
|
|
|
| int pattern_length = pat->length();
|
| if (pattern_length == 0) return start_index;
|
| @@ -2815,15 +2775,19 @@
|
| if (pat->IsAsciiRepresentation()) {
|
| Vector<const char> pat_vector = pat->ToAsciiVector();
|
| if (sub->IsAsciiRepresentation()) {
|
| - return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
|
| + return StringSearch(isolate->runtime_state(), sub->ToAsciiVector(),
|
| + pat_vector, start_index);
|
| }
|
| - return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
|
| + return StringSearch(isolate->runtime_state(), sub->ToUC16Vector(),
|
| + pat_vector, start_index);
|
| }
|
| Vector<const uc16> pat_vector = pat->ToUC16Vector();
|
| if (sub->IsAsciiRepresentation()) {
|
| - return StringSearch(sub->ToAsciiVector(), pat_vector, start_index);
|
| + return StringSearch(isolate->runtime_state(), sub->ToAsciiVector(),
|
| + pat_vector, start_index);
|
| }
|
| - return StringSearch(sub->ToUC16Vector(), pat_vector, start_index);
|
| + return StringSearch(isolate->runtime_state(), sub->ToUC16Vector(), pat_vector,
|
| + start_index);
|
| }
|
|
|
|
|
| @@ -2986,8 +2950,11 @@
|
| str1->TryFlatten();
|
| str2->TryFlatten();
|
|
|
| - static StringInputBuffer buf1;
|
| - static StringInputBuffer buf2;
|
| + Isolate* isolate = Isolate::Current();
|
| + StringInputBuffer& buf1 =
|
| + *isolate->runtime_state()->string_locale_compare_buf1();
|
| + StringInputBuffer& buf2 =
|
| + *isolate->runtime_state()->string_locale_compare_buf2();
|
|
|
| buf1.Reset(str1);
|
| buf2.Reset(str2);
|
| @@ -3183,7 +3150,8 @@
|
|
|
|
|
| template <typename schar, typename pchar>
|
| -static bool SearchStringMultiple(Vector<schar> subject,
|
| +static bool SearchStringMultiple(RuntimeState* state,
|
| + Vector<schar> subject,
|
| String* pattern,
|
| Vector<pchar> pattern_string,
|
| FixedArrayBuilder* builder,
|
| @@ -3194,7 +3162,7 @@
|
| int max_search_start = subject_length - pattern_length;
|
| bool is_ascii = (sizeof(schar) == 1);
|
| StringSearchStrategy strategy =
|
| - InitializeStringSearch(pattern_string, is_ascii);
|
| + InitializeStringSearch(state, pattern_string, is_ascii);
|
| switch (strategy) {
|
| case SEARCH_FAIL: break;
|
| case SEARCH_SHORT:
|
| @@ -3227,7 +3195,7 @@
|
| return false;
|
| }
|
| int match_end = pos + pattern_length;
|
| - int new_pos = ComplexIndexOf(subject, pattern_string, match_end);
|
| + int new_pos = ComplexIndexOf(state, subject, pattern_string, match_end);
|
| if (new_pos >= 0) {
|
| // A match has been found.
|
| if (new_pos > match_end) {
|
| @@ -3253,7 +3221,8 @@
|
| }
|
|
|
|
|
| -static bool SearchStringMultiple(Handle<String> subject,
|
| +static bool SearchStringMultiple(RuntimeState* state,
|
| + Handle<String> subject,
|
| Handle<String> pattern,
|
| Handle<JSArray> last_match_info,
|
| FixedArrayBuilder* builder) {
|
| @@ -3270,13 +3239,15 @@
|
| if (subject->IsAsciiRepresentation()) {
|
| Vector<const char> subject_vector = subject->ToAsciiVector();
|
| if (pattern->IsAsciiRepresentation()) {
|
| - if (SearchStringMultiple(subject_vector,
|
| + if (SearchStringMultiple(state,
|
| + subject_vector,
|
| *pattern,
|
| pattern->ToAsciiVector(),
|
| builder,
|
| &match_pos)) break;
|
| } else {
|
| - if (SearchStringMultiple(subject_vector,
|
| + if (SearchStringMultiple(state,
|
| + subject_vector,
|
| *pattern,
|
| pattern->ToUC16Vector(),
|
| builder,
|
| @@ -3285,13 +3256,15 @@
|
| } else {
|
| Vector<const uc16> subject_vector = subject->ToUC16Vector();
|
| if (pattern->IsAsciiRepresentation()) {
|
| - if (SearchStringMultiple(subject_vector,
|
| + if (SearchStringMultiple(state,
|
| + subject_vector,
|
| *pattern,
|
| pattern->ToAsciiVector(),
|
| builder,
|
| &match_pos)) break;
|
| } else {
|
| - if (SearchStringMultiple(subject_vector,
|
| + if (SearchStringMultiple(state,
|
| + subject_vector,
|
| *pattern,
|
| pattern->ToUC16Vector(),
|
| builder,
|
| @@ -3495,6 +3468,7 @@
|
|
|
| static Object* Runtime_RegExpExecMultiple(Arguments args) {
|
| ASSERT(args.length() == 4);
|
| + Isolate* isolate = Isolate::Current();
|
| HandleScope handles;
|
|
|
| CONVERT_ARG_CHECKED(String, subject, 1);
|
| @@ -3526,7 +3500,8 @@
|
| }
|
|
|
| if (!pattern->IsFlat()) FlattenString(pattern);
|
| - if (SearchStringMultiple(subject, pattern, last_match_info, &builder)) {
|
| + if (SearchStringMultiple(isolate->runtime_state(), subject, pattern,
|
| + last_match_info, &builder)) {
|
| return *builder.ToJSArray(result_array);
|
| }
|
| return HEAP->null_value();
|
| @@ -4674,6 +4649,7 @@
|
|
|
| static Object* Runtime_URIEscape(Arguments args) {
|
| const char hex_chars[] = "0123456789ABCDEF";
|
| + Isolate* isolate = Isolate::Current();
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 1);
|
| CONVERT_CHECKED(String, source, args[0]);
|
| @@ -4683,7 +4659,8 @@
|
| int escaped_length = 0;
|
| int length = source->length();
|
| {
|
| - Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
|
| + Access<StringInputBuffer> buffer(
|
| + isolate->runtime_state()->string_input_buffer());
|
| buffer->Reset(source);
|
| while (buffer->has_more()) {
|
| uint16_t character = buffer->GetNext();
|
| @@ -4711,7 +4688,8 @@
|
| String* destination = String::cast(o);
|
| int dest_position = 0;
|
|
|
| - Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
|
| + Access<StringInputBuffer> buffer(
|
| + isolate->runtime_state()->string_input_buffer());
|
| buffer->Rewind();
|
| while (buffer->has_more()) {
|
| uint16_t chr = buffer->GetNext();
|
| @@ -4852,12 +4830,9 @@
|
| }
|
|
|
|
|
| -static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
|
| -static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
|
| -
|
| -
|
| template <class Converter>
|
| -static Object* ConvertCaseHelper(String* s,
|
| +static Object* ConvertCaseHelper(RuntimeState* state,
|
| + String* s,
|
| int length,
|
| int input_string_length,
|
| unibrow::Mapping<Converter, 128>* mapping) {
|
| @@ -4881,7 +4856,7 @@
|
|
|
| // Convert all characters to upper case, assuming that they will fit
|
| // in the buffer
|
| - Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
|
| + Access<StringInputBuffer> buffer(state->string_input_buffer());
|
| buffer->Reset(s);
|
| unibrow::uchar chars[Converter::kMaxWidth];
|
| // We can assume that the string is not empty
|
| @@ -5007,7 +4982,7 @@
|
|
|
| template <typename ConvertTraits>
|
| static Object* ConvertCase(
|
| - Arguments args,
|
| + RuntimeState* state, Arguments args,
|
| unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
|
| NoHandleAllocation ha;
|
| CONVERT_CHECKED(String, s, args[0]);
|
| @@ -5033,22 +5008,25 @@
|
| return has_changed_character ? result : s;
|
| }
|
|
|
| - Object* answer = ConvertCaseHelper(s, length, length, mapping);
|
| + Object* answer = ConvertCaseHelper(state, s, length, length, mapping);
|
| if (answer->IsSmi()) {
|
| // Retry with correct length.
|
| - answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping);
|
| + answer = ConvertCaseHelper(state, s, Smi::cast(answer)->value(), length,
|
| + mapping);
|
| }
|
| return answer; // This may be a failure.
|
| }
|
|
|
|
|
| static Object* Runtime_StringToLowerCase(Arguments args) {
|
| - return ConvertCase<ToLowerTraits>(args, &to_lower_mapping);
|
| + RuntimeState* state = Isolate::Current()->runtime_state();
|
| + return ConvertCase<ToLowerTraits>(state, args, state->to_lower_mapping());
|
| }
|
|
|
|
|
| static Object* Runtime_StringToUpperCase(Arguments args) {
|
| - return ConvertCase<ToUpperTraits>(args, &to_upper_mapping);
|
| + RuntimeState* state = Isolate::Current()->runtime_state();
|
| + return ConvertCase<ToUpperTraits>(state, args, state->to_upper_mapping());
|
| }
|
|
|
|
|
| @@ -5086,7 +5064,8 @@
|
|
|
|
|
| template <typename schar, typename pchar>
|
| -void FindStringIndices(Vector<const schar> subject,
|
| +void FindStringIndices(RuntimeState* state,
|
| + Vector<const schar> subject,
|
| Vector<const pchar> pattern,
|
| ZoneList<int>* indices,
|
| unsigned int limit) {
|
| @@ -5094,7 +5073,7 @@
|
| // Collect indices of pattern in subject, and the end-of-string index.
|
| // Stop after finding at most limit values.
|
| StringSearchStrategy strategy =
|
| - InitializeStringSearch(pattern, sizeof(schar) == 1);
|
| + InitializeStringSearch(state, pattern, sizeof(schar) == 1);
|
| switch (strategy) {
|
| case SEARCH_FAIL: return;
|
| case SEARCH_SHORT: {
|
| @@ -5113,7 +5092,7 @@
|
| int pattern_length = pattern.length();
|
| int index = 0;
|
| while (limit > 0) {
|
| - index = ComplexIndexOf(subject, pattern, index);
|
| + index = ComplexIndexOf(state, subject, pattern, index);
|
| if (index < 0) return;
|
| indices->Add(index);
|
| index += pattern_length;
|
| @@ -5147,6 +5126,7 @@
|
|
|
| static Object* Runtime_StringSplit(Arguments args) {
|
| ASSERT(args.length() == 3);
|
| + Isolate* isolate = Isolate::Current();
|
| HandleScope handle_scope;
|
| CONVERT_ARG_CHECKED(String, subject, 0);
|
| CONVERT_ARG_CHECKED(String, pattern, 1);
|
| @@ -5174,7 +5154,8 @@
|
| AssertNoAllocation nogc;
|
| uc16 pattern_char = pattern->Get(0);
|
| if (subject->IsTwoByteRepresentation()) {
|
| - FindCharIndices(subject->ToUC16Vector(), pattern_char,
|
| + FindCharIndices(subject->ToUC16Vector(),
|
| + pattern_char,
|
| &indices,
|
| limit);
|
| } else if (pattern_char <= String::kMaxAsciiCharCode) {
|
| @@ -5189,12 +5170,14 @@
|
| if (subject->IsAsciiRepresentation()) {
|
| Vector<const char> subject_vector = subject->ToAsciiVector();
|
| if (pattern->IsAsciiRepresentation()) {
|
| - FindStringIndices(subject_vector,
|
| + FindStringIndices(isolate->runtime_state(),
|
| + subject_vector,
|
| pattern->ToAsciiVector(),
|
| &indices,
|
| limit);
|
| } else {
|
| - FindStringIndices(subject_vector,
|
| + FindStringIndices(isolate->runtime_state(),
|
| + subject_vector,
|
| pattern->ToUC16Vector(),
|
| &indices,
|
| limit);
|
| @@ -5202,12 +5185,14 @@
|
| } else {
|
| Vector<const uc16> subject_vector = subject->ToUC16Vector();
|
| if (pattern->IsAsciiRepresentation()) {
|
| - FindStringIndices(subject_vector,
|
| + FindStringIndices(isolate->runtime_state(),
|
| + subject_vector,
|
| pattern->ToAsciiVector(),
|
| &indices,
|
| limit);
|
| } else {
|
| - FindStringIndices(subject_vector,
|
| + FindStringIndices(isolate->runtime_state(),
|
| + subject_vector,
|
| pattern->ToUC16Vector(),
|
| &indices,
|
| limit);
|
| @@ -5325,7 +5310,8 @@
|
|
|
| bool Runtime::IsUpperCaseChar(uint16_t ch) {
|
| unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
|
| - int char_length = to_upper_mapping.get(ch, 0, chars);
|
| + int char_length = Isolate::Current()->runtime_state()->to_upper_mapping()->
|
| + get(ch, 0, chars);
|
| return char_length == 0;
|
| }
|
|
|
| @@ -5777,11 +5763,6 @@
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
|
|
| - // Arrays for the individual characters of the two Smis. Smis are
|
| - // 31 bit integers and 10 decimal digits are therefore enough.
|
| - static int x_elms[10];
|
| - static int y_elms[10];
|
| -
|
| // Extract the integer values from the Smis.
|
| CONVERT_CHECKED(Smi, x, args[0]);
|
| CONVERT_CHECKED(Smi, y, args[1]);
|
| @@ -5805,6 +5786,13 @@
|
| y_value = -y_value;
|
| }
|
|
|
| + Isolate* isolate = Isolate::Current();
|
| + // Arrays for the individual characters of the two Smis. Smis are
|
| + // 31 bit integers and 10 decimal digits are therefore enough.
|
| + int* x_elms = isolate->runtime_state()->smi_lexicographic_compare_x_elms();
|
| + int* y_elms = isolate->runtime_state()->smi_lexicographic_compare_y_elms();
|
| +
|
| +
|
| // Convert the integers to arrays of their decimal digits.
|
| int x_index = 0;
|
| int y_index = 0;
|
| @@ -5831,9 +5819,10 @@
|
| }
|
|
|
|
|
| -static Object* StringInputBufferCompare(String* x, String* y) {
|
| - static StringInputBuffer bufx;
|
| - static StringInputBuffer bufy;
|
| +static Object* StringInputBufferCompare(RuntimeState* state, String* x,
|
| + String* y) {
|
| + StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx();
|
| + StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy();
|
| bufx.Reset(x);
|
| bufy.Reset(y);
|
| while (bufx.has_more() && bufy.has_more()) {
|
| @@ -5886,7 +5875,8 @@
|
| } else {
|
| result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
|
| }
|
| - ASSERT(result == StringInputBufferCompare(x, y));
|
| + ASSERT(result == StringInputBufferCompare(Isolate::Current()->runtime_state(),
|
| + x, y));
|
| return result;
|
| }
|
|
|
| @@ -5919,7 +5909,7 @@
|
| if (obj->IsFailure()) return obj;
|
|
|
| return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
|
| - : StringInputBufferCompare(x, y);
|
| + : StringInputBufferCompare(Isolate::Current()->runtime_state(), x, y);
|
| }
|
|
|
|
|
| @@ -5956,6 +5946,9 @@
|
| }
|
|
|
|
|
| +static const double kPiDividedBy4 = 0.78539816339744830962;
|
| +
|
| +
|
| static Object* Runtime_Math_atan2(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
| @@ -5969,7 +5962,6 @@
|
| // is a multiple of Pi / 4. The sign of the result is determined
|
| // by the first argument (x) and the sign of the second argument
|
| // determines the multiplier: one or three.
|
| - static double kPiDividedBy4 = 0.78539816339744830962;
|
| int multiplier = (x < 0) ? -1 : 1;
|
| if (y < 0) multiplier *= 3;
|
| result = multiplier * kPiDividedBy4;
|
| @@ -6604,7 +6596,8 @@
|
| ConstructStubCompiler compiler;
|
| Object* code = compiler.CompileConstructStub(function->shared());
|
| if (code->IsFailure()) {
|
| - return Builtins::builtin(Builtins::JSConstructStubGeneric);
|
| + return Isolate::Current()->builtins()->builtin(
|
| + Builtins::JSConstructStubGeneric);
|
| }
|
| return Code::cast(code);
|
| }
|
| @@ -9365,6 +9358,11 @@
|
| }
|
|
|
|
|
| +static const char* source_str =
|
| + "(function(arguments,__source__){return eval(__source__);})";
|
| +static const int source_str_length = StrLength(source_str);
|
| +
|
| +
|
| // Evaluate a piece of JavaScript in the context of a stack frame for
|
| // debugging. This is accomplished by creating a new context which in its
|
| // extension part has all the parameters and locals of the function on the
|
| @@ -9442,9 +9440,8 @@
|
| // 'arguments'. This it to have access to what would have been 'arguments' in
|
| // the function being debugged.
|
| // function(arguments,__source__) {return eval(__source__);}
|
| - static const char* source_str =
|
| - "(function(arguments,__source__){return eval(__source__);})";
|
| - static const int source_str_length = StrLength(source_str);
|
| + ASSERT(source_str_length == StrLength(source_str));
|
| +
|
| Handle<String> function_source =
|
| Factory::NewStringFromAscii(Vector<const char>(source_str,
|
| source_str_length));
|
| @@ -10391,7 +10388,7 @@
|
| { #name, FUNCTION_ADDR(Runtime_##name), nargs, \
|
| static_cast<int>(Runtime::k##name), ressize },
|
|
|
| -static Runtime::Function Runtime_functions[] = {
|
| +static const Runtime::Function Runtime_functions[] = {
|
| RUNTIME_FUNCTION_LIST(F)
|
| { NULL, NULL, 0, -1, 0 }
|
| };
|
| @@ -10399,14 +10396,14 @@
|
| #undef F
|
|
|
|
|
| -Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
|
| +const Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
|
| ASSERT(0 <= fid && fid < kNofFunctions);
|
| return &Runtime_functions[fid];
|
| }
|
|
|
|
|
| -Runtime::Function* Runtime::FunctionForName(const char* name) {
|
| - for (Function* f = Runtime_functions; f->name != NULL; f++) {
|
| +const Runtime::Function* Runtime::FunctionForName(const char* name) {
|
| + for (const Function* f = Runtime_functions; f->name != NULL; f++) {
|
| if (strcmp(f->name, name) == 0) {
|
| return f;
|
| }
|
| @@ -10430,4 +10427,18 @@
|
| }
|
|
|
|
|
| +InlineRuntimeFunctionsTable::InlineRuntimeFunctionsTable() {
|
| + // List of special runtime calls which are generated inline. For some of these
|
| + // functions the code will be generated inline, and for others a call to a
|
| + // code stub will be inlined.
|
| + int lut_index = 0;
|
| +#define SETUP_RUNTIME_ENTRIES(Name, argc, resize) \
|
| + entries_[lut_index].method = &CodeGenerator::Generate##Name; \
|
| + entries_[lut_index].name = "_" #Name; \
|
| + entries_[lut_index++].nargs = argc;
|
| + INLINE_RUNTIME_FUNCTION_LIST(SETUP_RUNTIME_ENTRIES);
|
| +#undef SETUP_RUNTIME_ENTRIES
|
| +}
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|