Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Side by Side Diff: src/runtime.cc

Issue 2840018: [Isolates] Moved more compilation-related globals (builtins, runtime, &c.)... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/isolates/
Patch Set: rebase Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« src/runtime.h ('K') | « src/runtime.h ('k') | src/stub-cache.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698