OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 #include "runtime.h" | 45 #include "runtime.h" |
46 #include "scopeinfo.h" | 46 #include "scopeinfo.h" |
47 #include "smart-pointer.h" | 47 #include "smart-pointer.h" |
48 #include "stub-cache.h" | 48 #include "stub-cache.h" |
49 #include "v8threads.h" | 49 #include "v8threads.h" |
50 | 50 |
51 namespace v8 { | 51 namespace v8 { |
52 namespace internal { | 52 namespace internal { |
53 | 53 |
54 | 54 |
| 55 RuntimeState::RuntimeState() |
| 56 : algorithm_(SIMPLE_SEARCH) { |
| 57 memset(bad_char_occurrence_, 0, |
| 58 sizeof(bad_char_occurrence_[0]) * kBMAlphabetSize); |
| 59 } |
| 60 |
| 61 |
55 #define RUNTIME_ASSERT(value) \ | 62 #define RUNTIME_ASSERT(value) \ |
56 if (!(value)) return Isolate::Current()->ThrowIllegalOperation(); | 63 if (!(value)) return Isolate::Current()->ThrowIllegalOperation(); |
57 | 64 |
58 // Cast the given object to a value of the specified type and store | 65 // Cast the given object to a value of the specified type and store |
59 // it in a variable with the given name. If the object is not of the | 66 // it in a variable with the given name. If the object is not of the |
60 // expected type call IllegalOperation and return. | 67 // expected type call IllegalOperation and return. |
61 #define CONVERT_CHECKED(Type, name, obj) \ | 68 #define CONVERT_CHECKED(Type, name, obj) \ |
62 RUNTIME_ASSERT(obj->Is##Type()); \ | 69 RUNTIME_ASSERT(obj->Is##Type()); \ |
63 Type* name = Type::cast(obj); | 70 Type* name = Type::cast(obj); |
64 | 71 |
(...skipping 22 matching lines...) Expand all Loading... |
87 RUNTIME_ASSERT(obj->IsNumber()); \ | 94 RUNTIME_ASSERT(obj->IsNumber()); \ |
88 double name = (obj)->Number(); | 95 double name = (obj)->Number(); |
89 | 96 |
90 // Call the specified converter on the object *comand store the result in | 97 // Call the specified converter on the object *comand store the result in |
91 // a variable of the specified type with the given name. If the | 98 // a variable of the specified type with the given name. If the |
92 // object is not a Number call IllegalOperation and return. | 99 // object is not a Number call IllegalOperation and return. |
93 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \ | 100 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \ |
94 RUNTIME_ASSERT(obj->IsNumber()); \ | 101 RUNTIME_ASSERT(obj->IsNumber()); \ |
95 type name = NumberTo##Type(obj); | 102 type name = NumberTo##Type(obj); |
96 | 103 |
97 // Non-reentrant string buffer for efficient general use in this file. | |
98 static StaticResource<StringInputBuffer> runtime_string_input_buffer; | |
99 | |
100 | 104 |
101 static Object* DeepCopyBoilerplate(Heap* heap, JSObject* boilerplate) { | 105 static Object* DeepCopyBoilerplate(Heap* heap, JSObject* boilerplate) { |
102 StackLimitCheck check; | 106 StackLimitCheck check; |
103 if (check.HasOverflowed()) return Isolate::Current()->StackOverflow(); | 107 if (check.HasOverflowed()) return Isolate::Current()->StackOverflow(); |
104 | 108 |
105 Object* result = heap->CopyJSObject(boilerplate); | 109 Object* result = heap->CopyJSObject(boilerplate); |
106 if (result->IsFailure()) return result; | 110 if (result->IsFailure()) return result; |
107 JSObject* copy = JSObject::cast(result); | 111 JSObject* copy = JSObject::cast(result); |
108 | 112 |
109 // Deep copy local properties. | 113 // Deep copy local properties. |
(...skipping 1273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1383 // on Array.prototype and below. | 1387 // on Array.prototype and below. |
1384 prototype->set_elements(HEAP->empty_fixed_array()); | 1388 prototype->set_elements(HEAP->empty_fixed_array()); |
1385 return Smi::FromInt(0); | 1389 return Smi::FromInt(0); |
1386 } | 1390 } |
1387 | 1391 |
1388 | 1392 |
1389 static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder, | 1393 static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder, |
1390 const char* name, | 1394 const char* name, |
1391 Builtins::Name builtin_name) { | 1395 Builtins::Name builtin_name) { |
1392 Handle<String> key = Factory::LookupAsciiSymbol(name); | 1396 Handle<String> key = Factory::LookupAsciiSymbol(name); |
1393 Handle<Code> code(Builtins::builtin(builtin_name)); | 1397 Handle<Code> code(Isolate::Current()->builtins()->builtin(builtin_name)); |
1394 Handle<JSFunction> optimized = Factory::NewFunction(key, | 1398 Handle<JSFunction> optimized = Factory::NewFunction(key, |
1395 JS_OBJECT_TYPE, | 1399 JS_OBJECT_TYPE, |
1396 JSObject::kHeaderSize, | 1400 JSObject::kHeaderSize, |
1397 code, | 1401 code, |
1398 false); | 1402 false); |
1399 optimized->shared()->DontAdaptArguments(); | 1403 optimized->shared()->DontAdaptArguments(); |
1400 SetProperty(holder, key, optimized, NONE); | 1404 SetProperty(holder, key, optimized, NONE); |
1401 return optimized; | 1405 return optimized; |
1402 } | 1406 } |
1403 | 1407 |
(...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2310 | 2314 |
2311 ASSERT(last_match_info->HasFastElements()); | 2315 ASSERT(last_match_info->HasFastElements()); |
2312 | 2316 |
2313 return StringReplaceRegExpWithString(subject, | 2317 return StringReplaceRegExpWithString(subject, |
2314 regexp, | 2318 regexp, |
2315 replacement, | 2319 replacement, |
2316 last_match_info); | 2320 last_match_info); |
2317 } | 2321 } |
2318 | 2322 |
2319 | 2323 |
2320 // Cap on the maximal shift in the Boyer-Moore implementation. By setting a | |
2321 // limit, we can fix the size of tables. | |
2322 static const int kBMMaxShift = 0xff; | |
2323 // Reduce alphabet to this size. | |
2324 static const int kBMAlphabetSize = 0x100; | |
2325 // For patterns below this length, the skip length of Boyer-Moore is too short | |
2326 // to compensate for the algorithmic overhead compared to simple brute force. | |
2327 static const int kBMMinPatternLength = 5; | |
2328 | |
2329 // Holds the two buffers used by Boyer-Moore string search's Good Suffix | |
2330 // shift. Only allows the last kBMMaxShift characters of the needle | |
2331 // to be indexed. | |
2332 class BMGoodSuffixBuffers { | |
2333 public: | |
2334 BMGoodSuffixBuffers() {} | |
2335 inline void init(int needle_length) { | |
2336 ASSERT(needle_length > 1); | |
2337 int start = needle_length < kBMMaxShift ? 0 : needle_length - kBMMaxShift; | |
2338 int len = needle_length - start; | |
2339 biased_suffixes_ = suffixes_ - start; | |
2340 biased_good_suffix_shift_ = good_suffix_shift_ - start; | |
2341 for (int i = 0; i <= len; i++) { | |
2342 good_suffix_shift_[i] = len; | |
2343 } | |
2344 } | |
2345 inline int& suffix(int index) { | |
2346 ASSERT(biased_suffixes_ + index >= suffixes_); | |
2347 return biased_suffixes_[index]; | |
2348 } | |
2349 inline int& shift(int index) { | |
2350 ASSERT(biased_good_suffix_shift_ + index >= good_suffix_shift_); | |
2351 return biased_good_suffix_shift_[index]; | |
2352 } | |
2353 private: | |
2354 int suffixes_[kBMMaxShift + 1]; | |
2355 int good_suffix_shift_[kBMMaxShift + 1]; | |
2356 int* biased_suffixes_; | |
2357 int* biased_good_suffix_shift_; | |
2358 DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers); | |
2359 }; | |
2360 | |
2361 // buffers reused by BoyerMoore | |
2362 static int bad_char_occurrence[kBMAlphabetSize]; | |
2363 static BMGoodSuffixBuffers bmgs_buffers; | |
2364 | |
2365 // State of the string match tables. | |
2366 // SIMPLE: No usable content in the buffers. | |
2367 // BOYER_MOORE_HORSPOOL: The bad_char_occurences table has been populated. | |
2368 // BOYER_MOORE: The bmgs_buffers tables have also been populated. | |
2369 // Whenever starting with a new needle, one should call InitializeStringSearch | |
2370 // to determine which search strategy to use, and in the case of a long-needle | |
2371 // strategy, the call also initializes the algorithm to SIMPLE. | |
2372 enum StringSearchAlgorithm { SIMPLE_SEARCH, BOYER_MOORE_HORSPOOL, BOYER_MOORE }; | |
2373 static StringSearchAlgorithm algorithm; | |
2374 | |
2375 | |
2376 // Compute the bad-char table for Boyer-Moore in the static buffer. | 2324 // Compute the bad-char table for Boyer-Moore in the static buffer. |
2377 template <typename pchar> | 2325 template <typename pchar> |
2378 static void BoyerMoorePopulateBadCharTable(Vector<const pchar> pattern) { | 2326 static void BoyerMoorePopulateBadCharTable(RuntimeState* state, |
| 2327 Vector<const pchar> pattern) { |
| 2328 int* bad_char_occurrence = state->bad_char_occurrence(); |
2379 // Only preprocess at most kBMMaxShift last characters of pattern. | 2329 // Only preprocess at most kBMMaxShift last characters of pattern. |
2380 int start = pattern.length() < kBMMaxShift ? 0 | 2330 int start = pattern.length() < RuntimeState::kBMMaxShift ? 0 |
2381 : pattern.length() - kBMMaxShift; | 2331 : pattern.length() - RuntimeState::kBMMaxShift; |
2382 // Run forwards to populate bad_char_table, so that *last* instance | 2332 // Run forwards to populate bad_char_table, so that *last* instance |
2383 // of character equivalence class is the one registered. | 2333 // of character equivalence class is the one registered. |
2384 // Notice: Doesn't include the last character. | 2334 // Notice: Doesn't include the last character. |
2385 int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1 | 2335 int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1 |
2386 : kBMAlphabetSize; | 2336 : RuntimeState::kBMAlphabetSize; |
2387 if (start == 0) { // All patterns less than kBMMaxShift in length. | 2337 if (start == 0) { // All patterns less than kBMMaxShift in length. |
2388 memset(bad_char_occurrence, -1, table_size * sizeof(*bad_char_occurrence)); | 2338 memset(bad_char_occurrence, -1, table_size * sizeof(*bad_char_occurrence)); |
2389 } else { | 2339 } else { |
2390 for (int i = 0; i < table_size; i++) { | 2340 for (int i = 0; i < table_size; i++) { |
2391 bad_char_occurrence[i] = start - 1; | 2341 bad_char_occurrence[i] = start - 1; |
2392 } | 2342 } |
2393 } | 2343 } |
2394 for (int i = start; i < pattern.length() - 1; i++) { | 2344 for (int i = start; i < pattern.length() - 1; i++) { |
2395 pchar c = pattern[i]; | 2345 pchar c = pattern[i]; |
2396 int bucket = (sizeof(pchar) ==1) ? c : c % kBMAlphabetSize; | 2346 int bucket = (sizeof(pchar) ==1) ? c : c % RuntimeState::kBMAlphabetSize; |
2397 bad_char_occurrence[bucket] = i; | 2347 bad_char_occurrence[bucket] = i; |
2398 } | 2348 } |
2399 } | 2349 } |
2400 | 2350 |
2401 | 2351 |
2402 template <typename pchar> | 2352 template <typename pchar> |
2403 static void BoyerMoorePopulateGoodSuffixTable(Vector<const pchar> pattern) { | 2353 static void BoyerMoorePopulateGoodSuffixTable(RuntimeState* state, |
| 2354 Vector<const pchar> pattern) { |
| 2355 RuntimeState::BMGoodSuffixBuffers& bmgs_buffers = *state->bmgs_buffers(); |
2404 int m = pattern.length(); | 2356 int m = pattern.length(); |
2405 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift; | 2357 int start = m < RuntimeState::kBMMaxShift ? 0 : m - RuntimeState::kBMMaxShift; |
2406 int len = m - start; | 2358 int len = m - start; |
2407 // Compute Good Suffix tables. | 2359 // Compute Good Suffix tables. |
2408 bmgs_buffers.init(m); | 2360 bmgs_buffers.init(m); |
2409 | 2361 |
2410 bmgs_buffers.shift(m-1) = 1; | 2362 bmgs_buffers.shift(m-1) = 1; |
2411 bmgs_buffers.suffix(m) = m + 1; | 2363 bmgs_buffers.suffix(m) = m + 1; |
2412 pchar last_char = pattern[m - 1]; | 2364 pchar last_char = pattern[m - 1]; |
2413 int suffix = m + 1; | 2365 int suffix = m + 1; |
2414 for (int i = m; i > start;) { | 2366 for (int i = m; i > start;) { |
2415 for (pchar c = pattern[i - 1]; suffix <= m && c != pattern[suffix - 1];) { | 2367 for (pchar c = pattern[i - 1]; suffix <= m && c != pattern[suffix - 1];) { |
(...skipping 28 matching lines...) Expand all Loading... |
2444 } | 2396 } |
2445 if (i == suffix) { | 2397 if (i == suffix) { |
2446 suffix = bmgs_buffers.suffix(suffix); | 2398 suffix = bmgs_buffers.suffix(suffix); |
2447 } | 2399 } |
2448 } | 2400 } |
2449 } | 2401 } |
2450 } | 2402 } |
2451 | 2403 |
2452 | 2404 |
2453 template <typename schar, typename pchar> | 2405 template <typename schar, typename pchar> |
2454 static inline int CharOccurrence(int char_code) { | 2406 static inline int CharOccurrence(RuntimeState* state, int char_code) { |
| 2407 int* bad_char_occurrence = state->bad_char_occurrence(); |
2455 if (sizeof(schar) == 1) { | 2408 if (sizeof(schar) == 1) { |
2456 return bad_char_occurrence[char_code]; | 2409 return bad_char_occurrence[char_code]; |
2457 } | 2410 } |
2458 if (sizeof(pchar) == 1) { | 2411 if (sizeof(pchar) == 1) { |
2459 if (char_code > String::kMaxAsciiCharCode) { | 2412 if (char_code > String::kMaxAsciiCharCode) { |
2460 return -1; | 2413 return -1; |
2461 } | 2414 } |
2462 return bad_char_occurrence[char_code]; | 2415 return bad_char_occurrence[char_code]; |
2463 } | 2416 } |
2464 return bad_char_occurrence[char_code % kBMAlphabetSize]; | 2417 return bad_char_occurrence[char_code % RuntimeState::kBMAlphabetSize]; |
2465 } | 2418 } |
2466 | 2419 |
2467 | 2420 |
2468 // Restricted simplified Boyer-Moore string matching. | 2421 // Restricted simplified Boyer-Moore string matching. |
2469 // Uses only the bad-shift table of Boyer-Moore and only uses it | 2422 // Uses only the bad-shift table of Boyer-Moore and only uses it |
2470 // for the character compared to the last character of the needle. | 2423 // for the character compared to the last character of the needle. |
2471 template <typename schar, typename pchar> | 2424 template <typename schar, typename pchar> |
2472 static int BoyerMooreHorspool(Vector<const schar> subject, | 2425 static int BoyerMooreHorspool(RuntimeState* state, |
| 2426 Vector<const schar> subject, |
2473 Vector<const pchar> pattern, | 2427 Vector<const pchar> pattern, |
2474 int start_index, | 2428 int start_index, |
2475 bool* complete) { | 2429 bool* complete) { |
2476 ASSERT(algorithm <= BOYER_MOORE_HORSPOOL); | 2430 ASSERT(state->algorithm() <= RuntimeState::BOYER_MOORE_HORSPOOL); |
2477 int n = subject.length(); | 2431 int n = subject.length(); |
2478 int m = pattern.length(); | 2432 int m = pattern.length(); |
2479 | 2433 |
2480 int badness = -m; | 2434 int badness = -m; |
2481 | 2435 |
2482 // How bad we are doing without a good-suffix table. | 2436 // How bad we are doing without a good-suffix table. |
2483 int idx; // No matches found prior to this index. | 2437 int idx; // No matches found prior to this index. |
2484 pchar last_char = pattern[m - 1]; | 2438 pchar last_char = pattern[m - 1]; |
2485 int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(last_char); | 2439 int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(state, last_char); |
2486 // Perform search | 2440 // Perform search |
2487 for (idx = start_index; idx <= n - m;) { | 2441 for (idx = start_index; idx <= n - m;) { |
2488 int j = m - 1; | 2442 int j = m - 1; |
2489 int c; | 2443 int c; |
2490 while (last_char != (c = subject[idx + j])) { | 2444 while (last_char != (c = subject[idx + j])) { |
2491 int bc_occ = CharOccurrence<schar, pchar>(c); | 2445 int bc_occ = CharOccurrence<schar, pchar>(state, c); |
2492 int shift = j - bc_occ; | 2446 int shift = j - bc_occ; |
2493 idx += shift; | 2447 idx += shift; |
2494 badness += 1 - shift; // at most zero, so badness cannot increase. | 2448 badness += 1 - shift; // at most zero, so badness cannot increase. |
2495 if (idx > n - m) { | 2449 if (idx > n - m) { |
2496 *complete = true; | 2450 *complete = true; |
2497 return -1; | 2451 return -1; |
2498 } | 2452 } |
2499 } | 2453 } |
2500 j--; | 2454 j--; |
2501 while (j >= 0 && pattern[j] == (subject[idx + j])) j--; | 2455 while (j >= 0 && pattern[j] == (subject[idx + j])) j--; |
(...skipping 12 matching lines...) Expand all Loading... |
2514 return idx; | 2468 return idx; |
2515 } | 2469 } |
2516 } | 2470 } |
2517 } | 2471 } |
2518 *complete = true; | 2472 *complete = true; |
2519 return -1; | 2473 return -1; |
2520 } | 2474 } |
2521 | 2475 |
2522 | 2476 |
2523 template <typename schar, typename pchar> | 2477 template <typename schar, typename pchar> |
2524 static int BoyerMooreIndexOf(Vector<const schar> subject, | 2478 static int BoyerMooreIndexOf(RuntimeState* state, |
| 2479 Vector<const schar> subject, |
2525 Vector<const pchar> pattern, | 2480 Vector<const pchar> pattern, |
2526 int idx) { | 2481 int idx) { |
2527 ASSERT(algorithm <= BOYER_MOORE); | 2482 ASSERT(state->algorithm() <= RuntimeState::BOYER_MOORE); |
| 2483 RuntimeState::BMGoodSuffixBuffers& bmgs_buffers = *state->bmgs_buffers(); |
2528 int n = subject.length(); | 2484 int n = subject.length(); |
2529 int m = pattern.length(); | 2485 int m = pattern.length(); |
2530 // Only preprocess at most kBMMaxShift last characters of pattern. | 2486 // Only preprocess at most kBMMaxShift last characters of pattern. |
2531 int start = m < kBMMaxShift ? 0 : m - kBMMaxShift; | 2487 int start = m < RuntimeState::kBMMaxShift ? 0 : m - RuntimeState::kBMMaxShift; |
2532 | 2488 |
2533 pchar last_char = pattern[m - 1]; | 2489 pchar last_char = pattern[m - 1]; |
2534 // Continue search from i. | 2490 // Continue search from i. |
2535 while (idx <= n - m) { | 2491 while (idx <= n - m) { |
2536 int j = m - 1; | 2492 int j = m - 1; |
2537 schar c; | 2493 schar c; |
2538 while (last_char != (c = subject[idx + j])) { | 2494 while (last_char != (c = subject[idx + j])) { |
2539 int shift = j - CharOccurrence<schar, pchar>(c); | 2495 int shift = j - CharOccurrence<schar, pchar>(state, c); |
2540 idx += shift; | 2496 idx += shift; |
2541 if (idx > n - m) { | 2497 if (idx > n - m) { |
2542 return -1; | 2498 return -1; |
2543 } | 2499 } |
2544 } | 2500 } |
2545 while (j >= 0 && pattern[j] == (c = subject[idx + j])) j--; | 2501 while (j >= 0 && pattern[j] == (c = subject[idx + j])) j--; |
2546 if (j < 0) { | 2502 if (j < 0) { |
2547 return idx; | 2503 return idx; |
2548 } else if (j < start) { | 2504 } else if (j < start) { |
2549 // we have matched more than our tables allow us to be smart about. | 2505 // we have matched more than our tables allow us to be smart about. |
2550 // Fall back on BMH shift. | 2506 // Fall back on BMH shift. |
2551 idx += m - 1 - CharOccurrence<schar, pchar>(last_char); | 2507 idx += m - 1 - CharOccurrence<schar, pchar>(state, last_char); |
2552 } else { | 2508 } else { |
2553 int gs_shift = bmgs_buffers.shift(j + 1); // Good suffix shift. | 2509 int gs_shift = bmgs_buffers.shift(j + 1); // Good suffix shift. |
2554 int bc_occ = CharOccurrence<schar, pchar>(c); | 2510 int bc_occ = CharOccurrence<schar, pchar>(state, c); |
2555 int shift = j - bc_occ; // Bad-char shift. | 2511 int shift = j - bc_occ; // Bad-char shift. |
2556 if (gs_shift > shift) { | 2512 if (gs_shift > shift) { |
2557 shift = gs_shift; | 2513 shift = gs_shift; |
2558 } | 2514 } |
2559 idx += shift; | 2515 idx += shift; |
2560 } | 2516 } |
2561 } | 2517 } |
2562 | 2518 |
2563 return -1; | 2519 return -1; |
2564 } | 2520 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2684 return -1; | 2640 return -1; |
2685 } | 2641 } |
2686 | 2642 |
2687 | 2643 |
2688 // Strategy for searching for a string in another string. | 2644 // Strategy for searching for a string in another string. |
2689 enum StringSearchStrategy { SEARCH_FAIL, SEARCH_SHORT, SEARCH_LONG }; | 2645 enum StringSearchStrategy { SEARCH_FAIL, SEARCH_SHORT, SEARCH_LONG }; |
2690 | 2646 |
2691 | 2647 |
2692 template <typename pchar> | 2648 template <typename pchar> |
2693 static inline StringSearchStrategy InitializeStringSearch( | 2649 static inline StringSearchStrategy InitializeStringSearch( |
2694 Vector<const pchar> pat, bool ascii_subject) { | 2650 RuntimeState* state, Vector<const pchar> pat, bool ascii_subject) { |
2695 ASSERT(pat.length() > 1); | 2651 ASSERT(pat.length() > 1); |
2696 // We have an ASCII haystack and a non-ASCII needle. Check if there | 2652 // We have an ASCII haystack and a non-ASCII needle. Check if there |
2697 // really is a non-ASCII character in the needle and bail out if there | 2653 // really is a non-ASCII character in the needle and bail out if there |
2698 // is. | 2654 // is. |
2699 if (ascii_subject && sizeof(pchar) > 1) { | 2655 if (ascii_subject && sizeof(pchar) > 1) { |
2700 for (int i = 0; i < pat.length(); i++) { | 2656 for (int i = 0; i < pat.length(); i++) { |
2701 uc16 c = pat[i]; | 2657 uc16 c = pat[i]; |
2702 if (c > String::kMaxAsciiCharCode) { | 2658 if (c > String::kMaxAsciiCharCode) { |
2703 return SEARCH_FAIL; | 2659 return SEARCH_FAIL; |
2704 } | 2660 } |
2705 } | 2661 } |
2706 } | 2662 } |
2707 if (pat.length() < kBMMinPatternLength) { | 2663 if (pat.length() < RuntimeState::kBMMinPatternLength) { |
2708 return SEARCH_SHORT; | 2664 return SEARCH_SHORT; |
2709 } | 2665 } |
2710 algorithm = SIMPLE_SEARCH; | 2666 state->set_algorithm(RuntimeState::SIMPLE_SEARCH); |
2711 return SEARCH_LONG; | 2667 return SEARCH_LONG; |
2712 } | 2668 } |
2713 | 2669 |
2714 | 2670 |
2715 // Dispatch long needle searches to different algorithms. | 2671 // Dispatch long needle searches to different algorithms. |
2716 template <typename schar, typename pchar> | 2672 template <typename schar, typename pchar> |
2717 static int ComplexIndexOf(Vector<const schar> sub, | 2673 static int ComplexIndexOf(RuntimeState* state, |
| 2674 Vector<const schar> sub, |
2718 Vector<const pchar> pat, | 2675 Vector<const pchar> pat, |
2719 int start_index) { | 2676 int start_index) { |
2720 ASSERT(pat.length() >= kBMMinPatternLength); | 2677 ASSERT(pat.length() >= RuntimeState::kBMMinPatternLength); |
2721 // Try algorithms in order of increasing setup cost and expected performance. | 2678 // Try algorithms in order of increasing setup cost and expected performance. |
2722 bool complete; | 2679 bool complete; |
2723 int idx = start_index; | 2680 int idx = start_index; |
2724 switch (algorithm) { | 2681 switch (state->algorithm()) { |
2725 case SIMPLE_SEARCH: | 2682 case RuntimeState::SIMPLE_SEARCH: |
2726 idx = SimpleIndexOf(sub, pat, idx, &complete); | 2683 idx = SimpleIndexOf(sub, pat, idx, &complete); |
2727 if (complete) return idx; | 2684 if (complete) return idx; |
2728 BoyerMoorePopulateBadCharTable(pat); | 2685 BoyerMoorePopulateBadCharTable(state, pat); |
2729 algorithm = BOYER_MOORE_HORSPOOL; | 2686 state->set_algorithm(RuntimeState::BOYER_MOORE_HORSPOOL); |
2730 // FALLTHROUGH. | 2687 // FALLTHROUGH. |
2731 case BOYER_MOORE_HORSPOOL: | 2688 case RuntimeState::BOYER_MOORE_HORSPOOL: |
2732 idx = BoyerMooreHorspool(sub, pat, idx, &complete); | 2689 idx = BoyerMooreHorspool(state, sub, pat, idx, &complete); |
2733 if (complete) return idx; | 2690 if (complete) return idx; |
2734 // Build the Good Suffix table and continue searching. | 2691 // Build the Good Suffix table and continue searching. |
2735 BoyerMoorePopulateGoodSuffixTable(pat); | 2692 BoyerMoorePopulateGoodSuffixTable(state, pat); |
2736 algorithm = BOYER_MOORE; | 2693 state->set_algorithm(RuntimeState::BOYER_MOORE); |
2737 // FALLTHROUGH. | 2694 // FALLTHROUGH. |
2738 case BOYER_MOORE: | 2695 case RuntimeState::BOYER_MOORE: |
2739 return BoyerMooreIndexOf(sub, pat, idx); | 2696 return BoyerMooreIndexOf(state, sub, pat, idx); |
2740 } | 2697 } |
2741 UNREACHABLE(); | 2698 UNREACHABLE(); |
2742 return -1; | 2699 return -1; |
2743 } | 2700 } |
2744 | 2701 |
2745 | 2702 |
2746 // Dispatch to different search strategies for a single search. | 2703 // Dispatch to different search strategies for a single search. |
2747 // If searching multiple times on the same needle, the search | 2704 // If searching multiple times on the same needle, the search |
2748 // strategy should only be computed once and then dispatch to different | 2705 // strategy should only be computed once and then dispatch to different |
2749 // loops. | 2706 // loops. |
2750 template <typename schar, typename pchar> | 2707 template <typename schar, typename pchar> |
2751 static int StringSearch(Vector<const schar> sub, | 2708 static int StringSearch(RuntimeState* state, |
| 2709 Vector<const schar> sub, |
2752 Vector<const pchar> pat, | 2710 Vector<const pchar> pat, |
2753 int start_index) { | 2711 int start_index) { |
2754 bool ascii_subject = (sizeof(schar) == 1); | 2712 bool ascii_subject = (sizeof(schar) == 1); |
2755 StringSearchStrategy strategy = InitializeStringSearch(pat, ascii_subject); | 2713 StringSearchStrategy strategy = InitializeStringSearch(state, pat, |
| 2714 ascii_subject); |
2756 switch (strategy) { | 2715 switch (strategy) { |
2757 case SEARCH_FAIL: return -1; | 2716 case SEARCH_FAIL: return -1; |
2758 case SEARCH_SHORT: return SimpleIndexOf(sub, pat, start_index); | 2717 case SEARCH_SHORT: return SimpleIndexOf(sub, pat, start_index); |
2759 case SEARCH_LONG: return ComplexIndexOf(sub, pat, start_index); | 2718 case SEARCH_LONG: return ComplexIndexOf(state, sub, pat, start_index); |
2760 } | 2719 } |
2761 UNREACHABLE(); | 2720 UNREACHABLE(); |
2762 return -1; | 2721 return -1; |
2763 } | 2722 } |
2764 | 2723 |
2765 | 2724 |
2766 // Perform string match of pattern on subject, starting at start index. | 2725 // Perform string match of pattern on subject, starting at start index. |
2767 // Caller must ensure that 0 <= start_index <= sub->length(), | 2726 // Caller must ensure that 0 <= start_index <= sub->length(), |
2768 // and should check that pat->length() + start_index <= sub->length() | 2727 // and should check that pat->length() + start_index <= sub->length() |
2769 int Runtime::StringMatch(Handle<String> sub, | 2728 int Runtime::StringMatch(Handle<String> sub, |
2770 Handle<String> pat, | 2729 Handle<String> pat, |
2771 int start_index) { | 2730 int start_index) { |
2772 ASSERT(0 <= start_index); | 2731 ASSERT(0 <= start_index); |
2773 ASSERT(start_index <= sub->length()); | 2732 ASSERT(start_index <= sub->length()); |
| 2733 Isolate* isolate = Isolate::Current(); |
2774 | 2734 |
2775 int pattern_length = pat->length(); | 2735 int pattern_length = pat->length(); |
2776 if (pattern_length == 0) return start_index; | 2736 if (pattern_length == 0) return start_index; |
2777 | 2737 |
2778 int subject_length = sub->length(); | 2738 int subject_length = sub->length(); |
2779 if (start_index + pattern_length > subject_length) return -1; | 2739 if (start_index + pattern_length > subject_length) return -1; |
2780 | 2740 |
2781 if (!sub->IsFlat()) { | 2741 if (!sub->IsFlat()) { |
2782 FlattenString(sub); | 2742 FlattenString(sub); |
2783 } | 2743 } |
(...skipping 24 matching lines...) Expand all Loading... |
2808 | 2768 |
2809 if (!pat->IsFlat()) { | 2769 if (!pat->IsFlat()) { |
2810 FlattenString(pat); | 2770 FlattenString(pat); |
2811 } | 2771 } |
2812 | 2772 |
2813 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid | 2773 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid |
2814 // dispatch on type of strings | 2774 // dispatch on type of strings |
2815 if (pat->IsAsciiRepresentation()) { | 2775 if (pat->IsAsciiRepresentation()) { |
2816 Vector<const char> pat_vector = pat->ToAsciiVector(); | 2776 Vector<const char> pat_vector = pat->ToAsciiVector(); |
2817 if (sub->IsAsciiRepresentation()) { | 2777 if (sub->IsAsciiRepresentation()) { |
2818 return StringSearch(sub->ToAsciiVector(), pat_vector, start_index); | 2778 return StringSearch(isolate->runtime_state(), sub->ToAsciiVector(), |
| 2779 pat_vector, start_index); |
2819 } | 2780 } |
2820 return StringSearch(sub->ToUC16Vector(), pat_vector, start_index); | 2781 return StringSearch(isolate->runtime_state(), sub->ToUC16Vector(), |
| 2782 pat_vector, start_index); |
2821 } | 2783 } |
2822 Vector<const uc16> pat_vector = pat->ToUC16Vector(); | 2784 Vector<const uc16> pat_vector = pat->ToUC16Vector(); |
2823 if (sub->IsAsciiRepresentation()) { | 2785 if (sub->IsAsciiRepresentation()) { |
2824 return StringSearch(sub->ToAsciiVector(), pat_vector, start_index); | 2786 return StringSearch(isolate->runtime_state(), sub->ToAsciiVector(), |
| 2787 pat_vector, start_index); |
2825 } | 2788 } |
2826 return StringSearch(sub->ToUC16Vector(), pat_vector, start_index); | 2789 return StringSearch(isolate->runtime_state(), sub->ToUC16Vector(), pat_vector, |
| 2790 start_index); |
2827 } | 2791 } |
2828 | 2792 |
2829 | 2793 |
2830 static Object* Runtime_StringIndexOf(Arguments args) { | 2794 static Object* Runtime_StringIndexOf(Arguments args) { |
2831 HandleScope scope; // create a new handle scope | 2795 HandleScope scope; // create a new handle scope |
2832 ASSERT(args.length() == 3); | 2796 ASSERT(args.length() == 3); |
2833 | 2797 |
2834 CONVERT_ARG_CHECKED(String, sub, 0); | 2798 CONVERT_ARG_CHECKED(String, sub, 0); |
2835 CONVERT_ARG_CHECKED(String, pat, 1); | 2799 CONVERT_ARG_CHECKED(String, pat, 1); |
2836 | 2800 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2979 | 2943 |
2980 // No need to flatten if we are going to find the answer on the first | 2944 // No need to flatten if we are going to find the answer on the first |
2981 // character. At this point we know there is at least one character | 2945 // character. At this point we know there is at least one character |
2982 // in each string, due to the trivial case handling above. | 2946 // in each string, due to the trivial case handling above. |
2983 int d = str1->Get(0) - str2->Get(0); | 2947 int d = str1->Get(0) - str2->Get(0); |
2984 if (d != 0) return Smi::FromInt(d); | 2948 if (d != 0) return Smi::FromInt(d); |
2985 | 2949 |
2986 str1->TryFlatten(); | 2950 str1->TryFlatten(); |
2987 str2->TryFlatten(); | 2951 str2->TryFlatten(); |
2988 | 2952 |
2989 static StringInputBuffer buf1; | 2953 Isolate* isolate = Isolate::Current(); |
2990 static StringInputBuffer buf2; | 2954 StringInputBuffer& buf1 = |
| 2955 *isolate->runtime_state()->string_locale_compare_buf1(); |
| 2956 StringInputBuffer& buf2 = |
| 2957 *isolate->runtime_state()->string_locale_compare_buf2(); |
2991 | 2958 |
2992 buf1.Reset(str1); | 2959 buf1.Reset(str1); |
2993 buf2.Reset(str2); | 2960 buf2.Reset(str2); |
2994 | 2961 |
2995 for (int i = 0; i < end; i++) { | 2962 for (int i = 0; i < end; i++) { |
2996 uint16_t char1 = buf1.GetNext(); | 2963 uint16_t char1 = buf1.GetNext(); |
2997 uint16_t char2 = buf2.GetNext(); | 2964 uint16_t char2 = buf2.GetNext(); |
2998 if (char1 != char2) return Smi::FromInt(char1 - char2); | 2965 if (char1 != char2) return Smi::FromInt(char1 - char2); |
2999 } | 2966 } |
3000 | 2967 |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3176 last_match_info, | 3143 last_match_info, |
3177 match_pos, | 3144 match_pos, |
3178 match_pos + 1); | 3145 match_pos + 1); |
3179 return true; | 3146 return true; |
3180 } | 3147 } |
3181 return false; // No matches at all. | 3148 return false; // No matches at all. |
3182 } | 3149 } |
3183 | 3150 |
3184 | 3151 |
3185 template <typename schar, typename pchar> | 3152 template <typename schar, typename pchar> |
3186 static bool SearchStringMultiple(Vector<schar> subject, | 3153 static bool SearchStringMultiple(RuntimeState* state, |
| 3154 Vector<schar> subject, |
3187 String* pattern, | 3155 String* pattern, |
3188 Vector<pchar> pattern_string, | 3156 Vector<pchar> pattern_string, |
3189 FixedArrayBuilder* builder, | 3157 FixedArrayBuilder* builder, |
3190 int* match_pos) { | 3158 int* match_pos) { |
3191 int pos = *match_pos; | 3159 int pos = *match_pos; |
3192 int subject_length = subject.length(); | 3160 int subject_length = subject.length(); |
3193 int pattern_length = pattern_string.length(); | 3161 int pattern_length = pattern_string.length(); |
3194 int max_search_start = subject_length - pattern_length; | 3162 int max_search_start = subject_length - pattern_length; |
3195 bool is_ascii = (sizeof(schar) == 1); | 3163 bool is_ascii = (sizeof(schar) == 1); |
3196 StringSearchStrategy strategy = | 3164 StringSearchStrategy strategy = |
3197 InitializeStringSearch(pattern_string, is_ascii); | 3165 InitializeStringSearch(state, pattern_string, is_ascii); |
3198 switch (strategy) { | 3166 switch (strategy) { |
3199 case SEARCH_FAIL: break; | 3167 case SEARCH_FAIL: break; |
3200 case SEARCH_SHORT: | 3168 case SEARCH_SHORT: |
3201 while (pos <= max_search_start) { | 3169 while (pos <= max_search_start) { |
3202 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) { | 3170 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) { |
3203 *match_pos = pos; | 3171 *match_pos = pos; |
3204 return false; | 3172 return false; |
3205 } | 3173 } |
3206 // Position of end of previous match. | 3174 // Position of end of previous match. |
3207 int match_end = pos + pattern_length; | 3175 int match_end = pos + pattern_length; |
(...skipping 12 matching lines...) Expand all Loading... |
3220 } | 3188 } |
3221 } | 3189 } |
3222 break; | 3190 break; |
3223 case SEARCH_LONG: | 3191 case SEARCH_LONG: |
3224 while (pos <= max_search_start) { | 3192 while (pos <= max_search_start) { |
3225 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) { | 3193 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) { |
3226 *match_pos = pos; | 3194 *match_pos = pos; |
3227 return false; | 3195 return false; |
3228 } | 3196 } |
3229 int match_end = pos + pattern_length; | 3197 int match_end = pos + pattern_length; |
3230 int new_pos = ComplexIndexOf(subject, pattern_string, match_end); | 3198 int new_pos = ComplexIndexOf(state, subject, pattern_string, match_end); |
3231 if (new_pos >= 0) { | 3199 if (new_pos >= 0) { |
3232 // A match has been found. | 3200 // A match has been found. |
3233 if (new_pos > match_end) { | 3201 if (new_pos > match_end) { |
3234 ReplacementStringBuilder::AddSubjectSlice(builder, | 3202 ReplacementStringBuilder::AddSubjectSlice(builder, |
3235 match_end, | 3203 match_end, |
3236 new_pos); | 3204 new_pos); |
3237 } | 3205 } |
3238 pos = new_pos; | 3206 pos = new_pos; |
3239 builder->Add(pattern); | 3207 builder->Add(pattern); |
3240 } else { | 3208 } else { |
3241 break; | 3209 break; |
3242 } | 3210 } |
3243 } | 3211 } |
3244 break; | 3212 break; |
3245 } | 3213 } |
3246 if (pos < max_search_start) { | 3214 if (pos < max_search_start) { |
3247 ReplacementStringBuilder::AddSubjectSlice(builder, | 3215 ReplacementStringBuilder::AddSubjectSlice(builder, |
3248 pos + pattern_length, | 3216 pos + pattern_length, |
3249 subject_length); | 3217 subject_length); |
3250 } | 3218 } |
3251 *match_pos = pos; | 3219 *match_pos = pos; |
3252 return true; | 3220 return true; |
3253 } | 3221 } |
3254 | 3222 |
3255 | 3223 |
3256 static bool SearchStringMultiple(Handle<String> subject, | 3224 static bool SearchStringMultiple(RuntimeState* state, |
| 3225 Handle<String> subject, |
3257 Handle<String> pattern, | 3226 Handle<String> pattern, |
3258 Handle<JSArray> last_match_info, | 3227 Handle<JSArray> last_match_info, |
3259 FixedArrayBuilder* builder) { | 3228 FixedArrayBuilder* builder) { |
3260 ASSERT(subject->IsFlat()); | 3229 ASSERT(subject->IsFlat()); |
3261 ASSERT(pattern->IsFlat()); | 3230 ASSERT(pattern->IsFlat()); |
3262 ASSERT(pattern->length() > 1); | 3231 ASSERT(pattern->length() > 1); |
3263 | 3232 |
3264 // Treating as if a previous match was before first character. | 3233 // Treating as if a previous match was before first character. |
3265 int match_pos = -pattern->length(); | 3234 int match_pos = -pattern->length(); |
3266 | 3235 |
3267 for (;;) { // Break when search complete. | 3236 for (;;) { // Break when search complete. |
3268 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); | 3237 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
3269 AssertNoAllocation no_gc; | 3238 AssertNoAllocation no_gc; |
3270 if (subject->IsAsciiRepresentation()) { | 3239 if (subject->IsAsciiRepresentation()) { |
3271 Vector<const char> subject_vector = subject->ToAsciiVector(); | 3240 Vector<const char> subject_vector = subject->ToAsciiVector(); |
3272 if (pattern->IsAsciiRepresentation()) { | 3241 if (pattern->IsAsciiRepresentation()) { |
3273 if (SearchStringMultiple(subject_vector, | 3242 if (SearchStringMultiple(state, |
| 3243 subject_vector, |
3274 *pattern, | 3244 *pattern, |
3275 pattern->ToAsciiVector(), | 3245 pattern->ToAsciiVector(), |
3276 builder, | 3246 builder, |
3277 &match_pos)) break; | 3247 &match_pos)) break; |
3278 } else { | 3248 } else { |
3279 if (SearchStringMultiple(subject_vector, | 3249 if (SearchStringMultiple(state, |
| 3250 subject_vector, |
3280 *pattern, | 3251 *pattern, |
3281 pattern->ToUC16Vector(), | 3252 pattern->ToUC16Vector(), |
3282 builder, | 3253 builder, |
3283 &match_pos)) break; | 3254 &match_pos)) break; |
3284 } | 3255 } |
3285 } else { | 3256 } else { |
3286 Vector<const uc16> subject_vector = subject->ToUC16Vector(); | 3257 Vector<const uc16> subject_vector = subject->ToUC16Vector(); |
3287 if (pattern->IsAsciiRepresentation()) { | 3258 if (pattern->IsAsciiRepresentation()) { |
3288 if (SearchStringMultiple(subject_vector, | 3259 if (SearchStringMultiple(state, |
| 3260 subject_vector, |
3289 *pattern, | 3261 *pattern, |
3290 pattern->ToAsciiVector(), | 3262 pattern->ToAsciiVector(), |
3291 builder, | 3263 builder, |
3292 &match_pos)) break; | 3264 &match_pos)) break; |
3293 } else { | 3265 } else { |
3294 if (SearchStringMultiple(subject_vector, | 3266 if (SearchStringMultiple(state, |
| 3267 subject_vector, |
3295 *pattern, | 3268 *pattern, |
3296 pattern->ToUC16Vector(), | 3269 pattern->ToUC16Vector(), |
3297 builder, | 3270 builder, |
3298 &match_pos)) break; | 3271 &match_pos)) break; |
3299 } | 3272 } |
3300 } | 3273 } |
3301 } | 3274 } |
3302 | 3275 |
3303 if (match_pos >= 0) { | 3276 if (match_pos >= 0) { |
3304 SetLastMatchInfoNoCaptures(subject, | 3277 SetLastMatchInfoNoCaptures(subject, |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3488 return RegExpImpl::RE_SUCCESS; | 3461 return RegExpImpl::RE_SUCCESS; |
3489 } | 3462 } |
3490 } | 3463 } |
3491 // No matches at all, return failure or exception result directly. | 3464 // No matches at all, return failure or exception result directly. |
3492 return result; | 3465 return result; |
3493 } | 3466 } |
3494 | 3467 |
3495 | 3468 |
3496 static Object* Runtime_RegExpExecMultiple(Arguments args) { | 3469 static Object* Runtime_RegExpExecMultiple(Arguments args) { |
3497 ASSERT(args.length() == 4); | 3470 ASSERT(args.length() == 4); |
| 3471 Isolate* isolate = Isolate::Current(); |
3498 HandleScope handles; | 3472 HandleScope handles; |
3499 | 3473 |
3500 CONVERT_ARG_CHECKED(String, subject, 1); | 3474 CONVERT_ARG_CHECKED(String, subject, 1); |
3501 if (!subject->IsFlat()) { FlattenString(subject); } | 3475 if (!subject->IsFlat()) { FlattenString(subject); } |
3502 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); | 3476 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); |
3503 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2); | 3477 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2); |
3504 CONVERT_ARG_CHECKED(JSArray, result_array, 3); | 3478 CONVERT_ARG_CHECKED(JSArray, result_array, 3); |
3505 | 3479 |
3506 ASSERT(last_match_info->HasFastElements()); | 3480 ASSERT(last_match_info->HasFastElements()); |
3507 ASSERT(regexp->GetFlags().is_global()); | 3481 ASSERT(regexp->GetFlags().is_global()); |
(...skipping 11 matching lines...) Expand all Loading... |
3519 String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex))); | 3493 String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex))); |
3520 int pattern_length = pattern->length(); | 3494 int pattern_length = pattern->length(); |
3521 if (pattern_length == 1) { | 3495 if (pattern_length == 1) { |
3522 if (SearchCharMultiple(subject, pattern, last_match_info, &builder)) { | 3496 if (SearchCharMultiple(subject, pattern, last_match_info, &builder)) { |
3523 return *builder.ToJSArray(result_array); | 3497 return *builder.ToJSArray(result_array); |
3524 } | 3498 } |
3525 return HEAP->null_value(); | 3499 return HEAP->null_value(); |
3526 } | 3500 } |
3527 | 3501 |
3528 if (!pattern->IsFlat()) FlattenString(pattern); | 3502 if (!pattern->IsFlat()) FlattenString(pattern); |
3529 if (SearchStringMultiple(subject, pattern, last_match_info, &builder)) { | 3503 if (SearchStringMultiple(isolate->runtime_state(), subject, pattern, |
| 3504 last_match_info, &builder)) { |
3530 return *builder.ToJSArray(result_array); | 3505 return *builder.ToJSArray(result_array); |
3531 } | 3506 } |
3532 return HEAP->null_value(); | 3507 return HEAP->null_value(); |
3533 } | 3508 } |
3534 | 3509 |
3535 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); | 3510 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); |
3536 | 3511 |
3537 RegExpImpl::IrregexpResult result; | 3512 RegExpImpl::IrregexpResult result; |
3538 if (regexp->CaptureCount() == 0) { | 3513 if (regexp->CaptureCount() == 0) { |
3539 result = SearchRegExpNoCaptureMultiple(subject, | 3514 result = SearchRegExpNoCaptureMultiple(subject, |
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4667 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 4642 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
4668 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 4643 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
4669 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | 4644 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
4670 }; | 4645 }; |
4671 return kNotEscaped[character] != 0; | 4646 return kNotEscaped[character] != 0; |
4672 } | 4647 } |
4673 | 4648 |
4674 | 4649 |
4675 static Object* Runtime_URIEscape(Arguments args) { | 4650 static Object* Runtime_URIEscape(Arguments args) { |
4676 const char hex_chars[] = "0123456789ABCDEF"; | 4651 const char hex_chars[] = "0123456789ABCDEF"; |
| 4652 Isolate* isolate = Isolate::Current(); |
4677 NoHandleAllocation ha; | 4653 NoHandleAllocation ha; |
4678 ASSERT(args.length() == 1); | 4654 ASSERT(args.length() == 1); |
4679 CONVERT_CHECKED(String, source, args[0]); | 4655 CONVERT_CHECKED(String, source, args[0]); |
4680 | 4656 |
4681 source->TryFlatten(); | 4657 source->TryFlatten(); |
4682 | 4658 |
4683 int escaped_length = 0; | 4659 int escaped_length = 0; |
4684 int length = source->length(); | 4660 int length = source->length(); |
4685 { | 4661 { |
4686 Access<StringInputBuffer> buffer(&runtime_string_input_buffer); | 4662 Access<StringInputBuffer> buffer( |
| 4663 isolate->runtime_state()->string_input_buffer()); |
4687 buffer->Reset(source); | 4664 buffer->Reset(source); |
4688 while (buffer->has_more()) { | 4665 while (buffer->has_more()) { |
4689 uint16_t character = buffer->GetNext(); | 4666 uint16_t character = buffer->GetNext(); |
4690 if (character >= 256) { | 4667 if (character >= 256) { |
4691 escaped_length += 6; | 4668 escaped_length += 6; |
4692 } else if (IsNotEscaped(character)) { | 4669 } else if (IsNotEscaped(character)) { |
4693 escaped_length++; | 4670 escaped_length++; |
4694 } else { | 4671 } else { |
4695 escaped_length += 3; | 4672 escaped_length += 3; |
4696 } | 4673 } |
4697 // We don't allow strings that are longer than a maximal length. | 4674 // We don't allow strings that are longer than a maximal length. |
4698 ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow. | 4675 ASSERT(String::kMaxLength < 0x7fffffff - 6); // Cannot overflow. |
4699 if (escaped_length > String::kMaxLength) { | 4676 if (escaped_length > String::kMaxLength) { |
4700 Isolate::Current()->context()->mark_out_of_memory(); | 4677 Isolate::Current()->context()->mark_out_of_memory(); |
4701 return Failure::OutOfMemoryException(); | 4678 return Failure::OutOfMemoryException(); |
4702 } | 4679 } |
4703 } | 4680 } |
4704 } | 4681 } |
4705 // No length change implies no change. Return original string if no change. | 4682 // No length change implies no change. Return original string if no change. |
4706 if (escaped_length == length) { | 4683 if (escaped_length == length) { |
4707 return source; | 4684 return source; |
4708 } | 4685 } |
4709 Object* o = HEAP->AllocateRawAsciiString(escaped_length); | 4686 Object* o = HEAP->AllocateRawAsciiString(escaped_length); |
4710 if (o->IsFailure()) return o; | 4687 if (o->IsFailure()) return o; |
4711 String* destination = String::cast(o); | 4688 String* destination = String::cast(o); |
4712 int dest_position = 0; | 4689 int dest_position = 0; |
4713 | 4690 |
4714 Access<StringInputBuffer> buffer(&runtime_string_input_buffer); | 4691 Access<StringInputBuffer> buffer( |
| 4692 isolate->runtime_state()->string_input_buffer()); |
4715 buffer->Rewind(); | 4693 buffer->Rewind(); |
4716 while (buffer->has_more()) { | 4694 while (buffer->has_more()) { |
4717 uint16_t chr = buffer->GetNext(); | 4695 uint16_t chr = buffer->GetNext(); |
4718 if (chr >= 256) { | 4696 if (chr >= 256) { |
4719 destination->Set(dest_position, '%'); | 4697 destination->Set(dest_position, '%'); |
4720 destination->Set(dest_position+1, 'u'); | 4698 destination->Set(dest_position+1, 'u'); |
4721 destination->Set(dest_position+2, hex_chars[chr >> 12]); | 4699 destination->Set(dest_position+2, hex_chars[chr >> 12]); |
4722 destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]); | 4700 destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]); |
4723 destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]); | 4701 destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]); |
4724 destination->Set(dest_position+5, hex_chars[chr & 0xf]); | 4702 destination->Set(dest_position+5, hex_chars[chr & 0xf]); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4845 CONVERT_CHECKED(String, str, args[0]); | 4823 CONVERT_CHECKED(String, str, args[0]); |
4846 | 4824 |
4847 // ECMA-262 section 15.1.2.3, empty string is NaN | 4825 // ECMA-262 section 15.1.2.3, empty string is NaN |
4848 double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value()); | 4826 double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value()); |
4849 | 4827 |
4850 // Create a number object from the value. | 4828 // Create a number object from the value. |
4851 return HEAP->NumberFromDouble(value); | 4829 return HEAP->NumberFromDouble(value); |
4852 } | 4830 } |
4853 | 4831 |
4854 | 4832 |
4855 static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping; | |
4856 static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping; | |
4857 | |
4858 | |
4859 template <class Converter> | 4833 template <class Converter> |
4860 static Object* ConvertCaseHelper(String* s, | 4834 static Object* ConvertCaseHelper(RuntimeState* state, |
| 4835 String* s, |
4861 int length, | 4836 int length, |
4862 int input_string_length, | 4837 int input_string_length, |
4863 unibrow::Mapping<Converter, 128>* mapping) { | 4838 unibrow::Mapping<Converter, 128>* mapping) { |
4864 // We try this twice, once with the assumption that the result is no longer | 4839 // We try this twice, once with the assumption that the result is no longer |
4865 // than the input and, if that assumption breaks, again with the exact | 4840 // than the input and, if that assumption breaks, again with the exact |
4866 // length. This may not be pretty, but it is nicer than what was here before | 4841 // length. This may not be pretty, but it is nicer than what was here before |
4867 // and I hereby claim my vaffel-is. | 4842 // and I hereby claim my vaffel-is. |
4868 // | 4843 // |
4869 // Allocate the resulting string. | 4844 // Allocate the resulting string. |
4870 // | 4845 // |
4871 // NOTE: This assumes that the upper/lower case of an ascii | 4846 // NOTE: This assumes that the upper/lower case of an ascii |
4872 // character is also ascii. This is currently the case, but it | 4847 // character is also ascii. This is currently the case, but it |
4873 // might break in the future if we implement more context and locale | 4848 // might break in the future if we implement more context and locale |
4874 // dependent upper/lower conversions. | 4849 // dependent upper/lower conversions. |
4875 Object* o = s->IsAsciiRepresentation() | 4850 Object* o = s->IsAsciiRepresentation() |
4876 ? HEAP->AllocateRawAsciiString(length) | 4851 ? HEAP->AllocateRawAsciiString(length) |
4877 : HEAP->AllocateRawTwoByteString(length); | 4852 : HEAP->AllocateRawTwoByteString(length); |
4878 if (o->IsFailure()) return o; | 4853 if (o->IsFailure()) return o; |
4879 String* result = String::cast(o); | 4854 String* result = String::cast(o); |
4880 bool has_changed_character = false; | 4855 bool has_changed_character = false; |
4881 | 4856 |
4882 // Convert all characters to upper case, assuming that they will fit | 4857 // Convert all characters to upper case, assuming that they will fit |
4883 // in the buffer | 4858 // in the buffer |
4884 Access<StringInputBuffer> buffer(&runtime_string_input_buffer); | 4859 Access<StringInputBuffer> buffer(state->string_input_buffer()); |
4885 buffer->Reset(s); | 4860 buffer->Reset(s); |
4886 unibrow::uchar chars[Converter::kMaxWidth]; | 4861 unibrow::uchar chars[Converter::kMaxWidth]; |
4887 // We can assume that the string is not empty | 4862 // We can assume that the string is not empty |
4888 uc32 current = buffer->GetNext(); | 4863 uc32 current = buffer->GetNext(); |
4889 for (int i = 0; i < length;) { | 4864 for (int i = 0; i < length;) { |
4890 bool has_next = buffer->has_more(); | 4865 bool has_next = buffer->has_more(); |
4891 uc32 next = has_next ? buffer->GetNext() : 0; | 4866 uc32 next = has_next ? buffer->GetNext() : 0; |
4892 int char_length = mapping->get(current, next, chars); | 4867 int char_length = mapping->get(current, next, chars); |
4893 if (char_length == 0) { | 4868 if (char_length == 0) { |
4894 // The case conversion of this character is the character itself. | 4869 // The case conversion of this character is the character itself. |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5000 } | 4975 } |
5001 return changed; | 4976 return changed; |
5002 } | 4977 } |
5003 }; | 4978 }; |
5004 | 4979 |
5005 } // namespace | 4980 } // namespace |
5006 | 4981 |
5007 | 4982 |
5008 template <typename ConvertTraits> | 4983 template <typename ConvertTraits> |
5009 static Object* ConvertCase( | 4984 static Object* ConvertCase( |
5010 Arguments args, | 4985 RuntimeState* state, Arguments args, |
5011 unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) { | 4986 unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) { |
5012 NoHandleAllocation ha; | 4987 NoHandleAllocation ha; |
5013 CONVERT_CHECKED(String, s, args[0]); | 4988 CONVERT_CHECKED(String, s, args[0]); |
5014 s->TryFlatten(); | 4989 s->TryFlatten(); |
5015 | 4990 |
5016 const int length = s->length(); | 4991 const int length = s->length(); |
5017 // Assume that the string is not empty; we need this assumption later | 4992 // Assume that the string is not empty; we need this assumption later |
5018 if (length == 0) return s; | 4993 if (length == 0) return s; |
5019 | 4994 |
5020 // Simpler handling of ascii strings. | 4995 // Simpler handling of ascii strings. |
5021 // | 4996 // |
5022 // NOTE: This assumes that the upper/lower case of an ascii | 4997 // NOTE: This assumes that the upper/lower case of an ascii |
5023 // character is also ascii. This is currently the case, but it | 4998 // character is also ascii. This is currently the case, but it |
5024 // might break in the future if we implement more context and locale | 4999 // might break in the future if we implement more context and locale |
5025 // dependent upper/lower conversions. | 5000 // dependent upper/lower conversions. |
5026 SeqAsciiString* seq_ascii = TryGetSeqAsciiString(s); | 5001 SeqAsciiString* seq_ascii = TryGetSeqAsciiString(s); |
5027 if (seq_ascii != NULL) { | 5002 if (seq_ascii != NULL) { |
5028 Object* o = HEAP->AllocateRawAsciiString(length); | 5003 Object* o = HEAP->AllocateRawAsciiString(length); |
5029 if (o->IsFailure()) return o; | 5004 if (o->IsFailure()) return o; |
5030 SeqAsciiString* result = SeqAsciiString::cast(o); | 5005 SeqAsciiString* result = SeqAsciiString::cast(o); |
5031 bool has_changed_character = ConvertTraits::ConvertAscii( | 5006 bool has_changed_character = ConvertTraits::ConvertAscii( |
5032 result->GetChars(), seq_ascii->GetChars(), length); | 5007 result->GetChars(), seq_ascii->GetChars(), length); |
5033 return has_changed_character ? result : s; | 5008 return has_changed_character ? result : s; |
5034 } | 5009 } |
5035 | 5010 |
5036 Object* answer = ConvertCaseHelper(s, length, length, mapping); | 5011 Object* answer = ConvertCaseHelper(state, s, length, length, mapping); |
5037 if (answer->IsSmi()) { | 5012 if (answer->IsSmi()) { |
5038 // Retry with correct length. | 5013 // Retry with correct length. |
5039 answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping); | 5014 answer = ConvertCaseHelper(state, s, Smi::cast(answer)->value(), length, |
| 5015 mapping); |
5040 } | 5016 } |
5041 return answer; // This may be a failure. | 5017 return answer; // This may be a failure. |
5042 } | 5018 } |
5043 | 5019 |
5044 | 5020 |
5045 static Object* Runtime_StringToLowerCase(Arguments args) { | 5021 static Object* Runtime_StringToLowerCase(Arguments args) { |
5046 return ConvertCase<ToLowerTraits>(args, &to_lower_mapping); | 5022 RuntimeState* state = Isolate::Current()->runtime_state(); |
| 5023 return ConvertCase<ToLowerTraits>(state, args, state->to_lower_mapping()); |
5047 } | 5024 } |
5048 | 5025 |
5049 | 5026 |
5050 static Object* Runtime_StringToUpperCase(Arguments args) { | 5027 static Object* Runtime_StringToUpperCase(Arguments args) { |
5051 return ConvertCase<ToUpperTraits>(args, &to_upper_mapping); | 5028 RuntimeState* state = Isolate::Current()->runtime_state(); |
| 5029 return ConvertCase<ToUpperTraits>(state, args, state->to_upper_mapping()); |
5052 } | 5030 } |
5053 | 5031 |
5054 | 5032 |
5055 static inline bool IsTrimWhiteSpace(unibrow::uchar c) { | 5033 static inline bool IsTrimWhiteSpace(unibrow::uchar c) { |
5056 return unibrow::WhiteSpace::Is(c) || c == 0x200b; | 5034 return unibrow::WhiteSpace::Is(c) || c == 0x200b; |
5057 } | 5035 } |
5058 | 5036 |
5059 | 5037 |
5060 static Object* Runtime_StringTrim(Arguments args) { | 5038 static Object* Runtime_StringTrim(Arguments args) { |
5061 NoHandleAllocation ha; | 5039 NoHandleAllocation ha; |
(...skipping 17 matching lines...) Expand all Loading... |
5079 if (trimRight) { | 5057 if (trimRight) { |
5080 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) { | 5058 while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) { |
5081 right--; | 5059 right--; |
5082 } | 5060 } |
5083 } | 5061 } |
5084 return s->SubString(left, right); | 5062 return s->SubString(left, right); |
5085 } | 5063 } |
5086 | 5064 |
5087 | 5065 |
5088 template <typename schar, typename pchar> | 5066 template <typename schar, typename pchar> |
5089 void FindStringIndices(Vector<const schar> subject, | 5067 void FindStringIndices(RuntimeState* state, |
| 5068 Vector<const schar> subject, |
5090 Vector<const pchar> pattern, | 5069 Vector<const pchar> pattern, |
5091 ZoneList<int>* indices, | 5070 ZoneList<int>* indices, |
5092 unsigned int limit) { | 5071 unsigned int limit) { |
5093 ASSERT(limit > 0); | 5072 ASSERT(limit > 0); |
5094 // Collect indices of pattern in subject, and the end-of-string index. | 5073 // Collect indices of pattern in subject, and the end-of-string index. |
5095 // Stop after finding at most limit values. | 5074 // Stop after finding at most limit values. |
5096 StringSearchStrategy strategy = | 5075 StringSearchStrategy strategy = |
5097 InitializeStringSearch(pattern, sizeof(schar) == 1); | 5076 InitializeStringSearch(state, pattern, sizeof(schar) == 1); |
5098 switch (strategy) { | 5077 switch (strategy) { |
5099 case SEARCH_FAIL: return; | 5078 case SEARCH_FAIL: return; |
5100 case SEARCH_SHORT: { | 5079 case SEARCH_SHORT: { |
5101 int pattern_length = pattern.length(); | 5080 int pattern_length = pattern.length(); |
5102 int index = 0; | 5081 int index = 0; |
5103 while (limit > 0) { | 5082 while (limit > 0) { |
5104 index = SimpleIndexOf(subject, pattern, index); | 5083 index = SimpleIndexOf(subject, pattern, index); |
5105 if (index < 0) return; | 5084 if (index < 0) return; |
5106 indices->Add(index); | 5085 indices->Add(index); |
5107 index += pattern_length; | 5086 index += pattern_length; |
5108 limit--; | 5087 limit--; |
5109 } | 5088 } |
5110 return; | 5089 return; |
5111 } | 5090 } |
5112 case SEARCH_LONG: { | 5091 case SEARCH_LONG: { |
5113 int pattern_length = pattern.length(); | 5092 int pattern_length = pattern.length(); |
5114 int index = 0; | 5093 int index = 0; |
5115 while (limit > 0) { | 5094 while (limit > 0) { |
5116 index = ComplexIndexOf(subject, pattern, index); | 5095 index = ComplexIndexOf(state, subject, pattern, index); |
5117 if (index < 0) return; | 5096 if (index < 0) return; |
5118 indices->Add(index); | 5097 indices->Add(index); |
5119 index += pattern_length; | 5098 index += pattern_length; |
5120 limit--; | 5099 limit--; |
5121 } | 5100 } |
5122 return; | 5101 return; |
5123 } | 5102 } |
5124 default: | 5103 default: |
5125 UNREACHABLE(); | 5104 UNREACHABLE(); |
5126 return; | 5105 return; |
(...skipping 13 matching lines...) Expand all Loading... |
5140 if (index < 0) return; | 5119 if (index < 0) return; |
5141 indices->Add(index); | 5120 indices->Add(index); |
5142 index++; | 5121 index++; |
5143 limit--; | 5122 limit--; |
5144 } | 5123 } |
5145 } | 5124 } |
5146 | 5125 |
5147 | 5126 |
5148 static Object* Runtime_StringSplit(Arguments args) { | 5127 static Object* Runtime_StringSplit(Arguments args) { |
5149 ASSERT(args.length() == 3); | 5128 ASSERT(args.length() == 3); |
| 5129 Isolate* isolate = Isolate::Current(); |
5150 HandleScope handle_scope; | 5130 HandleScope handle_scope; |
5151 CONVERT_ARG_CHECKED(String, subject, 0); | 5131 CONVERT_ARG_CHECKED(String, subject, 0); |
5152 CONVERT_ARG_CHECKED(String, pattern, 1); | 5132 CONVERT_ARG_CHECKED(String, pattern, 1); |
5153 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]); | 5133 CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]); |
5154 | 5134 |
5155 int subject_length = subject->length(); | 5135 int subject_length = subject->length(); |
5156 int pattern_length = pattern->length(); | 5136 int pattern_length = pattern->length(); |
5157 RUNTIME_ASSERT(pattern_length > 0); | 5137 RUNTIME_ASSERT(pattern_length > 0); |
5158 | 5138 |
5159 // The limit can be very large (0xffffffffu), but since the pattern | 5139 // The limit can be very large (0xffffffffu), but since the pattern |
5160 // isn't empty, we can never create more parts than ~half the length | 5140 // isn't empty, we can never create more parts than ~half the length |
5161 // of the subject. | 5141 // of the subject. |
5162 | 5142 |
5163 if (!subject->IsFlat()) FlattenString(subject); | 5143 if (!subject->IsFlat()) FlattenString(subject); |
5164 | 5144 |
5165 static const int kMaxInitialListCapacity = 16; | 5145 static const int kMaxInitialListCapacity = 16; |
5166 | 5146 |
5167 ZoneScope scope(DELETE_ON_EXIT); | 5147 ZoneScope scope(DELETE_ON_EXIT); |
5168 | 5148 |
5169 // Find (up to limit) indices of separator and end-of-string in subject | 5149 // Find (up to limit) indices of separator and end-of-string in subject |
5170 int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit); | 5150 int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit); |
5171 ZoneList<int> indices(initial_capacity); | 5151 ZoneList<int> indices(initial_capacity); |
5172 if (pattern_length == 1) { | 5152 if (pattern_length == 1) { |
5173 // Special case, go directly to fast single-character split. | 5153 // Special case, go directly to fast single-character split. |
5174 AssertNoAllocation nogc; | 5154 AssertNoAllocation nogc; |
5175 uc16 pattern_char = pattern->Get(0); | 5155 uc16 pattern_char = pattern->Get(0); |
5176 if (subject->IsTwoByteRepresentation()) { | 5156 if (subject->IsTwoByteRepresentation()) { |
5177 FindCharIndices(subject->ToUC16Vector(), pattern_char, | 5157 FindCharIndices(subject->ToUC16Vector(), |
| 5158 pattern_char, |
5178 &indices, | 5159 &indices, |
5179 limit); | 5160 limit); |
5180 } else if (pattern_char <= String::kMaxAsciiCharCode) { | 5161 } else if (pattern_char <= String::kMaxAsciiCharCode) { |
5181 FindCharIndices(subject->ToAsciiVector(), | 5162 FindCharIndices(subject->ToAsciiVector(), |
5182 static_cast<char>(pattern_char), | 5163 static_cast<char>(pattern_char), |
5183 &indices, | 5164 &indices, |
5184 limit); | 5165 limit); |
5185 } | 5166 } |
5186 } else { | 5167 } else { |
5187 if (!pattern->IsFlat()) FlattenString(pattern); | 5168 if (!pattern->IsFlat()) FlattenString(pattern); |
5188 AssertNoAllocation nogc; | 5169 AssertNoAllocation nogc; |
5189 if (subject->IsAsciiRepresentation()) { | 5170 if (subject->IsAsciiRepresentation()) { |
5190 Vector<const char> subject_vector = subject->ToAsciiVector(); | 5171 Vector<const char> subject_vector = subject->ToAsciiVector(); |
5191 if (pattern->IsAsciiRepresentation()) { | 5172 if (pattern->IsAsciiRepresentation()) { |
5192 FindStringIndices(subject_vector, | 5173 FindStringIndices(isolate->runtime_state(), |
| 5174 subject_vector, |
5193 pattern->ToAsciiVector(), | 5175 pattern->ToAsciiVector(), |
5194 &indices, | 5176 &indices, |
5195 limit); | 5177 limit); |
5196 } else { | 5178 } else { |
5197 FindStringIndices(subject_vector, | 5179 FindStringIndices(isolate->runtime_state(), |
| 5180 subject_vector, |
5198 pattern->ToUC16Vector(), | 5181 pattern->ToUC16Vector(), |
5199 &indices, | 5182 &indices, |
5200 limit); | 5183 limit); |
5201 } | 5184 } |
5202 } else { | 5185 } else { |
5203 Vector<const uc16> subject_vector = subject->ToUC16Vector(); | 5186 Vector<const uc16> subject_vector = subject->ToUC16Vector(); |
5204 if (pattern->IsAsciiRepresentation()) { | 5187 if (pattern->IsAsciiRepresentation()) { |
5205 FindStringIndices(subject_vector, | 5188 FindStringIndices(isolate->runtime_state(), |
| 5189 subject_vector, |
5206 pattern->ToAsciiVector(), | 5190 pattern->ToAsciiVector(), |
5207 &indices, | 5191 &indices, |
5208 limit); | 5192 limit); |
5209 } else { | 5193 } else { |
5210 FindStringIndices(subject_vector, | 5194 FindStringIndices(isolate->runtime_state(), |
| 5195 subject_vector, |
5211 pattern->ToUC16Vector(), | 5196 pattern->ToUC16Vector(), |
5212 &indices, | 5197 &indices, |
5213 limit); | 5198 limit); |
5214 } | 5199 } |
5215 } | 5200 } |
5216 } | 5201 } |
5217 if (static_cast<uint32_t>(indices.length()) < limit) { | 5202 if (static_cast<uint32_t>(indices.length()) < limit) { |
5218 indices.Add(subject_length); | 5203 indices.Add(subject_length); |
5219 } | 5204 } |
5220 // The list indices now contains the end of each part to create. | 5205 // The list indices now contains the end of each part to create. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5318 ASSERT(String::cast(elements->get(i))->length() == 1); | 5303 ASSERT(String::cast(elements->get(i))->length() == 1); |
5319 } | 5304 } |
5320 #endif | 5305 #endif |
5321 | 5306 |
5322 return *Factory::NewJSArrayWithElements(elements); | 5307 return *Factory::NewJSArrayWithElements(elements); |
5323 } | 5308 } |
5324 | 5309 |
5325 | 5310 |
5326 bool Runtime::IsUpperCaseChar(uint16_t ch) { | 5311 bool Runtime::IsUpperCaseChar(uint16_t ch) { |
5327 unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth]; | 5312 unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth]; |
5328 int char_length = to_upper_mapping.get(ch, 0, chars); | 5313 int char_length = Isolate::Current()->runtime_state()->to_upper_mapping()-> |
| 5314 get(ch, 0, chars); |
5329 return char_length == 0; | 5315 return char_length == 0; |
5330 } | 5316 } |
5331 | 5317 |
5332 | 5318 |
5333 static Object* Runtime_NumberToString(Arguments args) { | 5319 static Object* Runtime_NumberToString(Arguments args) { |
5334 NoHandleAllocation ha; | 5320 NoHandleAllocation ha; |
5335 ASSERT(args.length() == 1); | 5321 ASSERT(args.length() == 1); |
5336 | 5322 |
5337 Object* number = args[0]; | 5323 Object* number = args[0]; |
5338 RUNTIME_ASSERT(number->IsNumber()); | 5324 RUNTIME_ASSERT(number->IsNumber()); |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5770 return Smi::FromInt(GREATER); | 5756 return Smi::FromInt(GREATER); |
5771 } | 5757 } |
5772 | 5758 |
5773 | 5759 |
5774 // Compare two Smis as if they were converted to strings and then | 5760 // Compare two Smis as if they were converted to strings and then |
5775 // compared lexicographically. | 5761 // compared lexicographically. |
5776 static Object* Runtime_SmiLexicographicCompare(Arguments args) { | 5762 static Object* Runtime_SmiLexicographicCompare(Arguments args) { |
5777 NoHandleAllocation ha; | 5763 NoHandleAllocation ha; |
5778 ASSERT(args.length() == 2); | 5764 ASSERT(args.length() == 2); |
5779 | 5765 |
5780 // Arrays for the individual characters of the two Smis. Smis are | |
5781 // 31 bit integers and 10 decimal digits are therefore enough. | |
5782 static int x_elms[10]; | |
5783 static int y_elms[10]; | |
5784 | |
5785 // Extract the integer values from the Smis. | 5766 // Extract the integer values from the Smis. |
5786 CONVERT_CHECKED(Smi, x, args[0]); | 5767 CONVERT_CHECKED(Smi, x, args[0]); |
5787 CONVERT_CHECKED(Smi, y, args[1]); | 5768 CONVERT_CHECKED(Smi, y, args[1]); |
5788 int x_value = x->value(); | 5769 int x_value = x->value(); |
5789 int y_value = y->value(); | 5770 int y_value = y->value(); |
5790 | 5771 |
5791 // If the integers are equal so are the string representations. | 5772 // If the integers are equal so are the string representations. |
5792 if (x_value == y_value) return Smi::FromInt(EQUAL); | 5773 if (x_value == y_value) return Smi::FromInt(EQUAL); |
5793 | 5774 |
5794 // If one of the integers are zero the normal integer order is the | 5775 // If one of the integers are zero the normal integer order is the |
5795 // same as the lexicographic order of the string representations. | 5776 // same as the lexicographic order of the string representations. |
5796 if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value); | 5777 if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value); |
5797 | 5778 |
5798 // If only one of the integers is negative the negative number is | 5779 // If only one of the integers is negative the negative number is |
5799 // smallest because the char code of '-' is less than the char code | 5780 // smallest because the char code of '-' is less than the char code |
5800 // of any digit. Otherwise, we make both values positive. | 5781 // of any digit. Otherwise, we make both values positive. |
5801 if (x_value < 0 || y_value < 0) { | 5782 if (x_value < 0 || y_value < 0) { |
5802 if (y_value >= 0) return Smi::FromInt(LESS); | 5783 if (y_value >= 0) return Smi::FromInt(LESS); |
5803 if (x_value >= 0) return Smi::FromInt(GREATER); | 5784 if (x_value >= 0) return Smi::FromInt(GREATER); |
5804 x_value = -x_value; | 5785 x_value = -x_value; |
5805 y_value = -y_value; | 5786 y_value = -y_value; |
5806 } | 5787 } |
5807 | 5788 |
| 5789 Isolate* isolate = Isolate::Current(); |
| 5790 // Arrays for the individual characters of the two Smis. Smis are |
| 5791 // 31 bit integers and 10 decimal digits are therefore enough. |
| 5792 int* x_elms = isolate->runtime_state()->smi_lexicographic_compare_x_elms(); |
| 5793 int* y_elms = isolate->runtime_state()->smi_lexicographic_compare_y_elms(); |
| 5794 |
| 5795 |
5808 // Convert the integers to arrays of their decimal digits. | 5796 // Convert the integers to arrays of their decimal digits. |
5809 int x_index = 0; | 5797 int x_index = 0; |
5810 int y_index = 0; | 5798 int y_index = 0; |
5811 while (x_value > 0) { | 5799 while (x_value > 0) { |
5812 x_elms[x_index++] = x_value % 10; | 5800 x_elms[x_index++] = x_value % 10; |
5813 x_value /= 10; | 5801 x_value /= 10; |
5814 } | 5802 } |
5815 while (y_value > 0) { | 5803 while (y_value > 0) { |
5816 y_elms[y_index++] = y_value % 10; | 5804 y_elms[y_index++] = y_value % 10; |
5817 y_value /= 10; | 5805 y_value /= 10; |
5818 } | 5806 } |
5819 | 5807 |
5820 // Loop through the arrays of decimal digits finding the first place | 5808 // Loop through the arrays of decimal digits finding the first place |
5821 // where they differ. | 5809 // where they differ. |
5822 while (--x_index >= 0 && --y_index >= 0) { | 5810 while (--x_index >= 0 && --y_index >= 0) { |
5823 int diff = x_elms[x_index] - y_elms[y_index]; | 5811 int diff = x_elms[x_index] - y_elms[y_index]; |
5824 if (diff != 0) return Smi::FromInt(diff); | 5812 if (diff != 0) return Smi::FromInt(diff); |
5825 } | 5813 } |
5826 | 5814 |
5827 // If one array is a suffix of the other array, the longest array is | 5815 // If one array is a suffix of the other array, the longest array is |
5828 // the representation of the largest of the Smis in the | 5816 // the representation of the largest of the Smis in the |
5829 // lexicographic ordering. | 5817 // lexicographic ordering. |
5830 return Smi::FromInt(x_index - y_index); | 5818 return Smi::FromInt(x_index - y_index); |
5831 } | 5819 } |
5832 | 5820 |
5833 | 5821 |
5834 static Object* StringInputBufferCompare(String* x, String* y) { | 5822 static Object* StringInputBufferCompare(RuntimeState* state, String* x, |
5835 static StringInputBuffer bufx; | 5823 String* y) { |
5836 static StringInputBuffer bufy; | 5824 StringInputBuffer& bufx = *state->string_input_buffer_compare_bufx(); |
| 5825 StringInputBuffer& bufy = *state->string_input_buffer_compare_bufy(); |
5837 bufx.Reset(x); | 5826 bufx.Reset(x); |
5838 bufy.Reset(y); | 5827 bufy.Reset(y); |
5839 while (bufx.has_more() && bufy.has_more()) { | 5828 while (bufx.has_more() && bufy.has_more()) { |
5840 int d = bufx.GetNext() - bufy.GetNext(); | 5829 int d = bufx.GetNext() - bufy.GetNext(); |
5841 if (d < 0) return Smi::FromInt(LESS); | 5830 if (d < 0) return Smi::FromInt(LESS); |
5842 else if (d > 0) return Smi::FromInt(GREATER); | 5831 else if (d > 0) return Smi::FromInt(GREATER); |
5843 } | 5832 } |
5844 | 5833 |
5845 // x is (non-trivial) prefix of y: | 5834 // x is (non-trivial) prefix of y: |
5846 if (bufy.has_more()) return Smi::FromInt(LESS); | 5835 if (bufy.has_more()) return Smi::FromInt(LESS); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5879 Vector<const uc16> y_chars = y->ToUC16Vector(); | 5868 Vector<const uc16> y_chars = y->ToUC16Vector(); |
5880 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); | 5869 r = CompareChars(x_chars.start(), y_chars.start(), prefix_length); |
5881 } | 5870 } |
5882 } | 5871 } |
5883 Object* result; | 5872 Object* result; |
5884 if (r == 0) { | 5873 if (r == 0) { |
5885 result = equal_prefix_result; | 5874 result = equal_prefix_result; |
5886 } else { | 5875 } else { |
5887 result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER); | 5876 result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER); |
5888 } | 5877 } |
5889 ASSERT(result == StringInputBufferCompare(x, y)); | 5878 ASSERT(result == StringInputBufferCompare(Isolate::Current()->runtime_state(), |
| 5879 x, y)); |
5890 return result; | 5880 return result; |
5891 } | 5881 } |
5892 | 5882 |
5893 | 5883 |
5894 static Object* Runtime_StringCompare(Arguments args) { | 5884 static Object* Runtime_StringCompare(Arguments args) { |
5895 NoHandleAllocation ha; | 5885 NoHandleAllocation ha; |
5896 ASSERT(args.length() == 2); | 5886 ASSERT(args.length() == 2); |
5897 | 5887 |
5898 CONVERT_CHECKED(String, x, args[0]); | 5888 CONVERT_CHECKED(String, x, args[0]); |
5899 CONVERT_CHECKED(String, y, args[1]); | 5889 CONVERT_CHECKED(String, y, args[1]); |
(...skipping 12 matching lines...) Expand all Loading... |
5912 int d = x->Get(0) - y->Get(0); | 5902 int d = x->Get(0) - y->Get(0); |
5913 if (d < 0) return Smi::FromInt(LESS); | 5903 if (d < 0) return Smi::FromInt(LESS); |
5914 else if (d > 0) return Smi::FromInt(GREATER); | 5904 else if (d > 0) return Smi::FromInt(GREATER); |
5915 | 5905 |
5916 Object* obj = HEAP->PrepareForCompare(x); | 5906 Object* obj = HEAP->PrepareForCompare(x); |
5917 if (obj->IsFailure()) return obj; | 5907 if (obj->IsFailure()) return obj; |
5918 obj = HEAP->PrepareForCompare(y); | 5908 obj = HEAP->PrepareForCompare(y); |
5919 if (obj->IsFailure()) return obj; | 5909 if (obj->IsFailure()) return obj; |
5920 | 5910 |
5921 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y) | 5911 return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y) |
5922 : StringInputBufferCompare(x, y); | 5912 : StringInputBufferCompare(Isolate::Current()->runtime_state(), x, y); |
5923 } | 5913 } |
5924 | 5914 |
5925 | 5915 |
5926 static Object* Runtime_Math_acos(Arguments args) { | 5916 static Object* Runtime_Math_acos(Arguments args) { |
5927 NoHandleAllocation ha; | 5917 NoHandleAllocation ha; |
5928 ASSERT(args.length() == 1); | 5918 ASSERT(args.length() == 1); |
5929 Counters::math_acos.Increment(); | 5919 Counters::math_acos.Increment(); |
5930 | 5920 |
5931 CONVERT_DOUBLE_CHECKED(x, args[0]); | 5921 CONVERT_DOUBLE_CHECKED(x, args[0]); |
5932 Isolate* const isolate = Isolate::Current(); | 5922 Isolate* const isolate = Isolate::Current(); |
(...skipping 16 matching lines...) Expand all Loading... |
5949 NoHandleAllocation ha; | 5939 NoHandleAllocation ha; |
5950 ASSERT(args.length() == 1); | 5940 ASSERT(args.length() == 1); |
5951 Counters::math_atan.Increment(); | 5941 Counters::math_atan.Increment(); |
5952 | 5942 |
5953 CONVERT_DOUBLE_CHECKED(x, args[0]); | 5943 CONVERT_DOUBLE_CHECKED(x, args[0]); |
5954 Isolate* const isolate = Isolate::Current(); | 5944 Isolate* const isolate = Isolate::Current(); |
5955 return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x); | 5945 return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x); |
5956 } | 5946 } |
5957 | 5947 |
5958 | 5948 |
| 5949 static const double kPiDividedBy4 = 0.78539816339744830962; |
| 5950 |
| 5951 |
5959 static Object* Runtime_Math_atan2(Arguments args) { | 5952 static Object* Runtime_Math_atan2(Arguments args) { |
5960 NoHandleAllocation ha; | 5953 NoHandleAllocation ha; |
5961 ASSERT(args.length() == 2); | 5954 ASSERT(args.length() == 2); |
5962 Counters::math_atan2.Increment(); | 5955 Counters::math_atan2.Increment(); |
5963 | 5956 |
5964 CONVERT_DOUBLE_CHECKED(x, args[0]); | 5957 CONVERT_DOUBLE_CHECKED(x, args[0]); |
5965 CONVERT_DOUBLE_CHECKED(y, args[1]); | 5958 CONVERT_DOUBLE_CHECKED(y, args[1]); |
5966 double result; | 5959 double result; |
5967 if (isinf(x) && isinf(y)) { | 5960 if (isinf(x) && isinf(y)) { |
5968 // Make sure that the result in case of two infinite arguments | 5961 // Make sure that the result in case of two infinite arguments |
5969 // is a multiple of Pi / 4. The sign of the result is determined | 5962 // is a multiple of Pi / 4. The sign of the result is determined |
5970 // by the first argument (x) and the sign of the second argument | 5963 // by the first argument (x) and the sign of the second argument |
5971 // determines the multiplier: one or three. | 5964 // determines the multiplier: one or three. |
5972 static double kPiDividedBy4 = 0.78539816339744830962; | |
5973 int multiplier = (x < 0) ? -1 : 1; | 5965 int multiplier = (x < 0) ? -1 : 1; |
5974 if (y < 0) multiplier *= 3; | 5966 if (y < 0) multiplier *= 3; |
5975 result = multiplier * kPiDividedBy4; | 5967 result = multiplier * kPiDividedBy4; |
5976 } else { | 5968 } else { |
5977 result = atan2(x, y); | 5969 result = atan2(x, y); |
5978 } | 5970 } |
5979 return HEAP->AllocateHeapNumber(result); | 5971 return HEAP->AllocateHeapNumber(result); |
5980 } | 5972 } |
5981 | 5973 |
5982 | 5974 |
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6597 | 6589 |
6598 static Code* ComputeConstructStub(Handle<JSFunction> function) { | 6590 static Code* ComputeConstructStub(Handle<JSFunction> function) { |
6599 Handle<Object> prototype = Factory::null_value(); | 6591 Handle<Object> prototype = Factory::null_value(); |
6600 if (function->has_instance_prototype()) { | 6592 if (function->has_instance_prototype()) { |
6601 prototype = Handle<Object>(function->instance_prototype()); | 6593 prototype = Handle<Object>(function->instance_prototype()); |
6602 } | 6594 } |
6603 if (function->shared()->CanGenerateInlineConstructor(*prototype)) { | 6595 if (function->shared()->CanGenerateInlineConstructor(*prototype)) { |
6604 ConstructStubCompiler compiler; | 6596 ConstructStubCompiler compiler; |
6605 Object* code = compiler.CompileConstructStub(function->shared()); | 6597 Object* code = compiler.CompileConstructStub(function->shared()); |
6606 if (code->IsFailure()) { | 6598 if (code->IsFailure()) { |
6607 return Builtins::builtin(Builtins::JSConstructStubGeneric); | 6599 return Isolate::Current()->builtins()->builtin( |
| 6600 Builtins::JSConstructStubGeneric); |
6608 } | 6601 } |
6609 return Code::cast(code); | 6602 return Code::cast(code); |
6610 } | 6603 } |
6611 | 6604 |
6612 return function->shared()->construct_stub(); | 6605 return function->shared()->construct_stub(); |
6613 } | 6606 } |
6614 | 6607 |
6615 | 6608 |
6616 static Object* Runtime_NewObject(Arguments args) { | 6609 static Object* Runtime_NewObject(Arguments args) { |
6617 HandleScope scope; | 6610 HandleScope scope; |
(...skipping 2740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9358 AssertNoAllocation no_gc; | 9351 AssertNoAllocation no_gc; |
9359 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); | 9352 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); |
9360 for (int i = 0; i < length; i++) { | 9353 for (int i = 0; i < length; i++) { |
9361 array->set(i, frame->GetParameter(i), mode); | 9354 array->set(i, frame->GetParameter(i), mode); |
9362 } | 9355 } |
9363 arguments->set_elements(*array); | 9356 arguments->set_elements(*array); |
9364 return arguments; | 9357 return arguments; |
9365 } | 9358 } |
9366 | 9359 |
9367 | 9360 |
| 9361 static const char* source_str = |
| 9362 "(function(arguments,__source__){return eval(__source__);})"; |
| 9363 static const int source_str_length = StrLength(source_str); |
| 9364 |
| 9365 |
9368 // Evaluate a piece of JavaScript in the context of a stack frame for | 9366 // Evaluate a piece of JavaScript in the context of a stack frame for |
9369 // debugging. This is accomplished by creating a new context which in its | 9367 // debugging. This is accomplished by creating a new context which in its |
9370 // extension part has all the parameters and locals of the function on the | 9368 // extension part has all the parameters and locals of the function on the |
9371 // stack frame. A function which calls eval with the code to evaluate is then | 9369 // stack frame. A function which calls eval with the code to evaluate is then |
9372 // compiled in this context and called in this context. As this context | 9370 // compiled in this context and called in this context. As this context |
9373 // replaces the context of the function on the stack frame a new (empty) | 9371 // replaces the context of the function on the stack frame a new (empty) |
9374 // function is created as well to be used as the closure for the context. | 9372 // function is created as well to be used as the closure for the context. |
9375 // This function and the context acts as replacements for the function on the | 9373 // This function and the context acts as replacements for the function on the |
9376 // stack frame presenting the same view of the values of parameters and | 9374 // stack frame presenting the same view of the values of parameters and |
9377 // local variables as if the piece of JavaScript was evaluated at the point | 9375 // local variables as if the piece of JavaScript was evaluated at the point |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9435 // Copy any with contexts present and chain them in front of this context. | 9433 // Copy any with contexts present and chain them in front of this context. |
9436 Handle<Context> frame_context(Context::cast(frame->context())); | 9434 Handle<Context> frame_context(Context::cast(frame->context())); |
9437 Handle<Context> function_context(frame_context->fcontext()); | 9435 Handle<Context> function_context(frame_context->fcontext()); |
9438 context = CopyWithContextChain(frame_context, context); | 9436 context = CopyWithContextChain(frame_context, context); |
9439 | 9437 |
9440 // Wrap the evaluation statement in a new function compiled in the newly | 9438 // Wrap the evaluation statement in a new function compiled in the newly |
9441 // created context. The function has one parameter which has to be called | 9439 // created context. The function has one parameter which has to be called |
9442 // 'arguments'. This it to have access to what would have been 'arguments' in | 9440 // 'arguments'. This it to have access to what would have been 'arguments' in |
9443 // the function being debugged. | 9441 // the function being debugged. |
9444 // function(arguments,__source__) {return eval(__source__);} | 9442 // function(arguments,__source__) {return eval(__source__);} |
9445 static const char* source_str = | 9443 ASSERT(source_str_length == StrLength(source_str)); |
9446 "(function(arguments,__source__){return eval(__source__);})"; | 9444 |
9447 static const int source_str_length = StrLength(source_str); | |
9448 Handle<String> function_source = | 9445 Handle<String> function_source = |
9449 Factory::NewStringFromAscii(Vector<const char>(source_str, | 9446 Factory::NewStringFromAscii(Vector<const char>(source_str, |
9450 source_str_length)); | 9447 source_str_length)); |
9451 Handle<SharedFunctionInfo> shared = | 9448 Handle<SharedFunctionInfo> shared = |
9452 Compiler::CompileEval(function_source, | 9449 Compiler::CompileEval(function_source, |
9453 context, | 9450 context, |
9454 context->IsGlobalContext(), | 9451 context->IsGlobalContext(), |
9455 Compiler::DONT_VALIDATE_JSON); | 9452 Compiler::DONT_VALIDATE_JSON); |
9456 if (shared.is_null()) return Failure::Exception(); | 9453 if (shared.is_null()) return Failure::Exception(); |
9457 Handle<JSFunction> compiled_function = | 9454 Handle<JSFunction> compiled_function = |
(...skipping 926 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10384 } | 10381 } |
10385 | 10382 |
10386 | 10383 |
10387 // ---------------------------------------------------------------------------- | 10384 // ---------------------------------------------------------------------------- |
10388 // Implementation of Runtime | 10385 // Implementation of Runtime |
10389 | 10386 |
10390 #define F(name, nargs, ressize) \ | 10387 #define F(name, nargs, ressize) \ |
10391 { #name, FUNCTION_ADDR(Runtime_##name), nargs, \ | 10388 { #name, FUNCTION_ADDR(Runtime_##name), nargs, \ |
10392 static_cast<int>(Runtime::k##name), ressize }, | 10389 static_cast<int>(Runtime::k##name), ressize }, |
10393 | 10390 |
10394 static Runtime::Function Runtime_functions[] = { | 10391 static const Runtime::Function Runtime_functions[] = { |
10395 RUNTIME_FUNCTION_LIST(F) | 10392 RUNTIME_FUNCTION_LIST(F) |
10396 { NULL, NULL, 0, -1, 0 } | 10393 { NULL, NULL, 0, -1, 0 } |
10397 }; | 10394 }; |
10398 | 10395 |
10399 #undef F | 10396 #undef F |
10400 | 10397 |
10401 | 10398 |
10402 Runtime::Function* Runtime::FunctionForId(FunctionId fid) { | 10399 const Runtime::Function* Runtime::FunctionForId(FunctionId fid) { |
10403 ASSERT(0 <= fid && fid < kNofFunctions); | 10400 ASSERT(0 <= fid && fid < kNofFunctions); |
10404 return &Runtime_functions[fid]; | 10401 return &Runtime_functions[fid]; |
10405 } | 10402 } |
10406 | 10403 |
10407 | 10404 |
10408 Runtime::Function* Runtime::FunctionForName(const char* name) { | 10405 const Runtime::Function* Runtime::FunctionForName(const char* name) { |
10409 for (Function* f = Runtime_functions; f->name != NULL; f++) { | 10406 for (const Function* f = Runtime_functions; f->name != NULL; f++) { |
10410 if (strcmp(f->name, name) == 0) { | 10407 if (strcmp(f->name, name) == 0) { |
10411 return f; | 10408 return f; |
10412 } | 10409 } |
10413 } | 10410 } |
10414 return NULL; | 10411 return NULL; |
10415 } | 10412 } |
10416 | 10413 |
10417 | 10414 |
10418 void Runtime::PerformGC(Object* result) { | 10415 void Runtime::PerformGC(Object* result) { |
10419 Failure* failure = Failure::cast(result); | 10416 Failure* failure = Failure::cast(result); |
10420 if (failure->IsRetryAfterGC()) { | 10417 if (failure->IsRetryAfterGC()) { |
10421 // Try to do a garbage collection; ignore it if it fails. The C | 10418 // Try to do a garbage collection; ignore it if it fails. The C |
10422 // entry stub will throw an out-of-memory exception in that case. | 10419 // entry stub will throw an out-of-memory exception in that case. |
10423 HEAP->CollectGarbage(failure->requested(), failure->allocation_space()); | 10420 HEAP->CollectGarbage(failure->requested(), failure->allocation_space()); |
10424 } else { | 10421 } else { |
10425 // Handle last resort GC and make sure to allow future allocations | 10422 // Handle last resort GC and make sure to allow future allocations |
10426 // to grow the heap without causing GCs (if possible). | 10423 // to grow the heap without causing GCs (if possible). |
10427 Counters::gc_last_resort_from_js.Increment(); | 10424 Counters::gc_last_resort_from_js.Increment(); |
10428 HEAP->CollectAllGarbage(false); | 10425 HEAP->CollectAllGarbage(false); |
10429 } | 10426 } |
10430 } | 10427 } |
10431 | 10428 |
10432 | 10429 |
| 10430 InlineRuntimeFunctionsTable::InlineRuntimeFunctionsTable() { |
| 10431 // List of special runtime calls which are generated inline. For some of these |
| 10432 // functions the code will be generated inline, and for others a call to a |
| 10433 // code stub will be inlined. |
| 10434 int lut_index = 0; |
| 10435 #define SETUP_RUNTIME_ENTRIES(Name, argc, resize) \ |
| 10436 entries_[lut_index].method = &CodeGenerator::Generate##Name; \ |
| 10437 entries_[lut_index].name = "_" #Name; \ |
| 10438 entries_[lut_index++].nargs = argc; |
| 10439 INLINE_RUNTIME_FUNCTION_LIST(SETUP_RUNTIME_ENTRIES); |
| 10440 #undef SETUP_RUNTIME_ENTRIES |
| 10441 } |
| 10442 |
| 10443 |
10433 } } // namespace v8::internal | 10444 } } // namespace v8::internal |
OLD | NEW |