| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 20 matching lines...) Expand all Loading... |
| 31 // should be possible without getting errors due to too deep recursion. | 31 // should be possible without getting errors due to too deep recursion. |
| 32 | 32 |
| 33 #include <stdlib.h> | 33 #include <stdlib.h> |
| 34 | 34 |
| 35 #include "v8.h" | 35 #include "v8.h" |
| 36 | 36 |
| 37 #include "api.h" | 37 #include "api.h" |
| 38 #include "factory.h" | 38 #include "factory.h" |
| 39 #include "objects.h" | 39 #include "objects.h" |
| 40 #include "cctest.h" | 40 #include "cctest.h" |
| 41 #include "zone-inl.h" | |
| 42 | 41 |
| 43 // Adapted from http://en.wikipedia.org/wiki/Multiply-with-carry | 42 // Adapted from http://en.wikipedia.org/wiki/Multiply-with-carry |
| 44 class MyRandomNumberGenerator { | 43 class MyRandomNumberGenerator { |
| 45 public: | 44 public: |
| 46 MyRandomNumberGenerator() { | 45 MyRandomNumberGenerator() { |
| 47 init(); | 46 init(); |
| 48 } | 47 } |
| 49 | 48 |
| 50 void init(uint32_t seed = 0x5688c73e) { | 49 void init(uint32_t seed = 0x5688c73e) { |
| 51 static const uint32_t phi = 0x9e3779b9; | 50 static const uint32_t phi = 0x9e3779b9; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 }; | 92 }; |
| 94 | 93 |
| 95 | 94 |
| 96 using namespace v8::internal; | 95 using namespace v8::internal; |
| 97 | 96 |
| 98 | 97 |
| 99 static const int DEEP_DEPTH = 8 * 1024; | 98 static const int DEEP_DEPTH = 8 * 1024; |
| 100 static const int SUPER_DEEP_DEPTH = 80 * 1024; | 99 static const int SUPER_DEEP_DEPTH = 80 * 1024; |
| 101 | 100 |
| 102 | 101 |
| 103 class Resource: public v8::String::ExternalStringResource, | 102 class Resource: public v8::String::ExternalStringResource { |
| 104 public ZoneObject { | |
| 105 public: | 103 public: |
| 106 explicit Resource(Vector<const uc16> string): data_(string.start()) { | 104 Resource(const uc16* data, size_t length): data_(data), length_(length) {} |
| 107 length_ = string.length(); | 105 ~Resource() { i::DeleteArray(data_); } |
| 108 } | |
| 109 virtual const uint16_t* data() const { return data_; } | 106 virtual const uint16_t* data() const { return data_; } |
| 110 virtual size_t length() const { return length_; } | 107 virtual size_t length() const { return length_; } |
| 111 | 108 |
| 112 private: | 109 private: |
| 113 const uc16* data_; | 110 const uc16* data_; |
| 114 size_t length_; | 111 size_t length_; |
| 115 }; | 112 }; |
| 116 | 113 |
| 117 | 114 |
| 118 class AsciiResource: public v8::String::ExternalAsciiStringResource, | 115 class AsciiResource: public v8::String::ExternalAsciiStringResource { |
| 119 public ZoneObject { | |
| 120 public: | 116 public: |
| 121 explicit AsciiResource(Vector<const char> string): data_(string.start()) { | 117 AsciiResource(const char* data, size_t length) |
| 122 length_ = string.length(); | 118 : data_(data), length_(length) {} |
| 123 } | 119 ~AsciiResource() { i::DeleteArray(data_); } |
| 124 virtual const char* data() const { return data_; } | 120 virtual const char* data() const { return data_; } |
| 125 virtual size_t length() const { return length_; } | 121 virtual size_t length() const { return length_; } |
| 126 | 122 |
| 127 private: | 123 private: |
| 128 const char* data_; | 124 const char* data_; |
| 129 size_t length_; | 125 size_t length_; |
| 130 }; | 126 }; |
| 131 | 127 |
| 132 | 128 |
| 133 static void InitializeBuildingBlocks(Handle<String>* building_blocks, | 129 static void InitializeBuildingBlocks(Handle<String>* building_blocks, |
| 134 int bb_length, | 130 int bb_length, |
| 135 bool long_blocks, | 131 bool long_blocks, |
| 136 MyRandomNumberGenerator* rng, | 132 MyRandomNumberGenerator* rng) { |
| 137 Zone* zone) { | |
| 138 // A list of pointers that we don't have any interest in cleaning up. | 133 // A list of pointers that we don't have any interest in cleaning up. |
| 139 // If they are reachable from a root then leak detection won't complain. | 134 // If they are reachable from a root then leak detection won't complain. |
| 140 Isolate* isolate = CcTest::i_isolate(); | 135 Isolate* isolate = CcTest::i_isolate(); |
| 141 Factory* factory = isolate->factory(); | 136 Factory* factory = isolate->factory(); |
| 142 for (int i = 0; i < bb_length; i++) { | 137 for (int i = 0; i < bb_length; i++) { |
| 143 int len = rng->next(16); | 138 int len = rng->next(16); |
| 144 int slice_head_chars = 0; | 139 int slice_head_chars = 0; |
| 145 int slice_tail_chars = 0; | 140 int slice_tail_chars = 0; |
| 146 int slice_depth = 0; | 141 int slice_depth = 0; |
| 147 for (int j = 0; j < 3; j++) { | 142 for (int j = 0; j < 3; j++) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 buf[j] = rng->next(0x80); | 177 buf[j] = rng->next(0x80); |
| 183 } | 178 } |
| 184 building_blocks[i] = | 179 building_blocks[i] = |
| 185 factory->NewStringFromAscii(Vector<const char>(buf, len)); | 180 factory->NewStringFromAscii(Vector<const char>(buf, len)); |
| 186 for (int j = 0; j < len; j++) { | 181 for (int j = 0; j < len; j++) { |
| 187 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); | 182 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); |
| 188 } | 183 } |
| 189 break; | 184 break; |
| 190 } | 185 } |
| 191 case 2: { | 186 case 2: { |
| 192 uc16* buf = zone->NewArray<uc16>(len); | 187 uc16* buf = NewArray<uc16>(len); |
| 193 for (int j = 0; j < len; j++) { | 188 for (int j = 0; j < len; j++) { |
| 194 buf[j] = rng->next(0x10000); | 189 buf[j] = rng->next(0x10000); |
| 195 } | 190 } |
| 196 Resource* resource = new(zone) Resource(Vector<const uc16>(buf, len)); | 191 Resource* resource = new Resource(buf, len); |
| 197 building_blocks[i] = factory->NewExternalStringFromTwoByte(resource); | 192 building_blocks[i] = |
| 193 v8::Utils::OpenHandle( |
| 194 *v8::String::NewExternal(CcTest::isolate(), resource)); |
| 198 for (int j = 0; j < len; j++) { | 195 for (int j = 0; j < len; j++) { |
| 199 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); | 196 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); |
| 200 } | 197 } |
| 201 break; | 198 break; |
| 202 } | 199 } |
| 203 case 3: { | 200 case 3: { |
| 204 char* buf = zone->NewArray<char>(len); | 201 char* buf = NewArray<char>(len); |
| 205 for (int j = 0; j < len; j++) { | 202 for (int j = 0; j < len; j++) { |
| 206 buf[j] = rng->next(0x80); | 203 buf[j] = rng->next(0x80); |
| 207 } | 204 } |
| 208 AsciiResource* resource = | 205 AsciiResource* resource = new AsciiResource(buf, len); |
| 209 new(zone) AsciiResource(Vector<const char>(buf, len)); | 206 building_blocks[i] = |
| 210 building_blocks[i] = factory->NewExternalStringFromAscii(resource); | 207 v8::Utils::OpenHandle( |
| 208 *v8::String::NewExternal(CcTest::isolate(), resource)); |
| 211 for (int j = 0; j < len; j++) { | 209 for (int j = 0; j < len; j++) { |
| 212 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); | 210 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); |
| 213 } | 211 } |
| 214 break; | 212 break; |
| 215 } | 213 } |
| 216 } | 214 } |
| 217 for (int j = slice_depth; j > 0; j--) { | 215 for (int j = slice_depth; j > 0; j--) { |
| 218 building_blocks[i] = factory->NewSubString( | 216 building_blocks[i] = factory->NewSubString( |
| 219 building_blocks[i], | 217 building_blocks[i], |
| 220 slice_head_chars, | 218 slice_head_chars, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 CHECK(this->empty_leaves_ == that.empty_leaves_); | 254 CHECK(this->empty_leaves_ == that.empty_leaves_); |
| 257 CHECK(this->chars_ == that.chars_); | 255 CHECK(this->chars_ == that.chars_); |
| 258 CHECK(this->left_traversals_ == that.left_traversals_); | 256 CHECK(this->left_traversals_ == that.left_traversals_); |
| 259 CHECK(this->right_traversals_ == that.right_traversals_); | 257 CHECK(this->right_traversals_ == that.right_traversals_); |
| 260 } | 258 } |
| 261 | 259 |
| 262 | 260 |
| 263 class ConsStringGenerationData { | 261 class ConsStringGenerationData { |
| 264 public: | 262 public: |
| 265 static const int kNumberOfBuildingBlocks = 256; | 263 static const int kNumberOfBuildingBlocks = 256; |
| 266 ConsStringGenerationData(bool long_blocks, Zone* zone); | 264 explicit ConsStringGenerationData(bool long_blocks); |
| 267 void Reset(); | 265 void Reset(); |
| 268 inline Handle<String> block(int offset); | 266 inline Handle<String> block(int offset); |
| 269 inline Handle<String> block(uint32_t offset); | 267 inline Handle<String> block(uint32_t offset); |
| 270 // Input variables. | 268 // Input variables. |
| 271 double early_termination_threshold_; | 269 double early_termination_threshold_; |
| 272 double leftness_; | 270 double leftness_; |
| 273 double rightness_; | 271 double rightness_; |
| 274 double empty_leaf_threshold_; | 272 double empty_leaf_threshold_; |
| 275 unsigned max_leaves_; | 273 unsigned max_leaves_; |
| 276 // Cached data. | 274 // Cached data. |
| 277 Handle<String> building_blocks_[kNumberOfBuildingBlocks]; | 275 Handle<String> building_blocks_[kNumberOfBuildingBlocks]; |
| 278 String* empty_string_; | 276 String* empty_string_; |
| 279 MyRandomNumberGenerator rng_; | 277 MyRandomNumberGenerator rng_; |
| 280 // Stats. | 278 // Stats. |
| 281 ConsStringStats stats_; | 279 ConsStringStats stats_; |
| 282 unsigned early_terminations_; | 280 unsigned early_terminations_; |
| 283 private: | 281 private: |
| 284 DISALLOW_COPY_AND_ASSIGN(ConsStringGenerationData); | 282 DISALLOW_COPY_AND_ASSIGN(ConsStringGenerationData); |
| 285 }; | 283 }; |
| 286 | 284 |
| 287 | 285 |
| 288 ConsStringGenerationData::ConsStringGenerationData(bool long_blocks, | 286 ConsStringGenerationData::ConsStringGenerationData(bool long_blocks) { |
| 289 Zone* zone) { | |
| 290 rng_.init(); | 287 rng_.init(); |
| 291 InitializeBuildingBlocks( | 288 InitializeBuildingBlocks( |
| 292 building_blocks_, kNumberOfBuildingBlocks, long_blocks, &rng_, zone); | 289 building_blocks_, kNumberOfBuildingBlocks, long_blocks, &rng_); |
| 293 empty_string_ = CcTest::heap()->empty_string(); | 290 empty_string_ = CcTest::heap()->empty_string(); |
| 294 Reset(); | 291 Reset(); |
| 295 } | 292 } |
| 296 | 293 |
| 297 | 294 |
| 298 Handle<String> ConsStringGenerationData::block(uint32_t offset) { | 295 Handle<String> ConsStringGenerationData::block(uint32_t offset) { |
| 299 return building_blocks_[offset % kNumberOfBuildingBlocks ]; | 296 return building_blocks_[offset % kNumberOfBuildingBlocks ]; |
| 300 } | 297 } |
| 301 | 298 |
| 302 | 299 |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 } | 561 } |
| 565 s1->Get(s1->length() - 1); | 562 s1->Get(s1->length() - 1); |
| 566 s2->Get(s2->length() - 1); | 563 s2->Get(s2->length() - 1); |
| 567 } | 564 } |
| 568 | 565 |
| 569 | 566 |
| 570 TEST(Traverse) { | 567 TEST(Traverse) { |
| 571 printf("TestTraverse\n"); | 568 printf("TestTraverse\n"); |
| 572 CcTest::InitializeVM(); | 569 CcTest::InitializeVM(); |
| 573 v8::HandleScope scope(CcTest::isolate()); | 570 v8::HandleScope scope(CcTest::isolate()); |
| 574 Zone zone(CcTest::i_isolate()); | 571 ConsStringGenerationData data(false); |
| 575 ConsStringGenerationData data(false, &zone); | |
| 576 Handle<String> flat = ConstructBalanced(&data); | 572 Handle<String> flat = ConstructBalanced(&data); |
| 577 FlattenString(flat); | 573 FlattenString(flat); |
| 578 Handle<String> left_asymmetric = ConstructLeft(&data, DEEP_DEPTH); | 574 Handle<String> left_asymmetric = ConstructLeft(&data, DEEP_DEPTH); |
| 579 Handle<String> right_asymmetric = ConstructRight(&data, DEEP_DEPTH); | 575 Handle<String> right_asymmetric = ConstructRight(&data, DEEP_DEPTH); |
| 580 Handle<String> symmetric = ConstructBalanced(&data); | 576 Handle<String> symmetric = ConstructBalanced(&data); |
| 581 printf("1\n"); | 577 printf("1\n"); |
| 582 Traverse(flat, symmetric); | 578 Traverse(flat, symmetric); |
| 583 printf("2\n"); | 579 printf("2\n"); |
| 584 Traverse(flat, left_asymmetric); | 580 Traverse(flat, left_asymmetric); |
| 585 printf("3\n"); | 581 printf("3\n"); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 "early_terminations", data.early_terminations_); | 650 "early_terminations", data.early_terminations_); |
| 655 #endif | 651 #endif |
| 656 } | 652 } |
| 657 | 653 |
| 658 | 654 |
| 659 template<typename BuildString> | 655 template<typename BuildString> |
| 660 void TestStringCharacterStream(BuildString build, int test_cases) { | 656 void TestStringCharacterStream(BuildString build, int test_cases) { |
| 661 CcTest::InitializeVM(); | 657 CcTest::InitializeVM(); |
| 662 Isolate* isolate = CcTest::i_isolate(); | 658 Isolate* isolate = CcTest::i_isolate(); |
| 663 HandleScope outer_scope(isolate); | 659 HandleScope outer_scope(isolate); |
| 664 Zone zone(isolate); | 660 ConsStringGenerationData data(true); |
| 665 ConsStringGenerationData data(true, &zone); | |
| 666 for (int i = 0; i < test_cases; i++) { | 661 for (int i = 0; i < test_cases; i++) { |
| 667 printf("%d\n", i); | 662 printf("%d\n", i); |
| 668 HandleScope inner_scope(isolate); | 663 HandleScope inner_scope(isolate); |
| 669 AlwaysAllocateScope always_allocate; | 664 AlwaysAllocateScope always_allocate; |
| 670 // Build flat version of cons string. | 665 // Build flat version of cons string. |
| 671 Handle<String> flat_string = build(i, &data); | 666 Handle<String> flat_string = build(i, &data); |
| 672 ConsStringStats flat_string_stats; | 667 ConsStringStats flat_string_stats; |
| 673 AccumulateStats(flat_string, &flat_string_stats); | 668 AccumulateStats(flat_string, &flat_string_stats); |
| 674 // Flatten string. | 669 // Flatten string. |
| 675 FlattenString(flat_string); | 670 FlattenString(flat_string); |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 924 for (int j = 0; j < lengths[i]; j++) | 919 for (int j = 0; j < lengths[i]; j++) |
| 925 CHECK_EQ(as_utf8[j], static_cast<unsigned char>(buffer[j])); | 920 CHECK_EQ(as_utf8[j], static_cast<unsigned char>(buffer[j])); |
| 926 // Check that the rest of the buffer hasn't been touched | 921 // Check that the rest of the buffer hasn't been touched |
| 927 for (int j = lengths[i]; j < 11; j++) | 922 for (int j = lengths[i]; j < 11; j++) |
| 928 CHECK_EQ(kNoChar, buffer[j]); | 923 CHECK_EQ(kNoChar, buffer[j]); |
| 929 } | 924 } |
| 930 } | 925 } |
| 931 | 926 |
| 932 | 927 |
| 933 TEST(ExternalShortStringAdd) { | 928 TEST(ExternalShortStringAdd) { |
| 934 Isolate* isolate = CcTest::i_isolate(); | |
| 935 Zone zone(isolate); | |
| 936 | |
| 937 LocalContext context; | 929 LocalContext context; |
| 938 v8::HandleScope handle_scope(CcTest::isolate()); | 930 v8::HandleScope handle_scope(CcTest::isolate()); |
| 939 | 931 |
| 940 // Make sure we cover all always-flat lengths and at least one above. | 932 // Make sure we cover all always-flat lengths and at least one above. |
| 941 static const int kMaxLength = 20; | 933 static const int kMaxLength = 20; |
| 942 CHECK_GT(kMaxLength, i::ConsString::kMinLength); | 934 CHECK_GT(kMaxLength, i::ConsString::kMinLength); |
| 943 | 935 |
| 944 // Allocate two JavaScript arrays for holding short strings. | 936 // Allocate two JavaScript arrays for holding short strings. |
| 945 v8::Handle<v8::Array> ascii_external_strings = | 937 v8::Handle<v8::Array> ascii_external_strings = |
| 946 v8::Array::New(CcTest::isolate(), kMaxLength + 1); | 938 v8::Array::New(CcTest::isolate(), kMaxLength + 1); |
| 947 v8::Handle<v8::Array> non_ascii_external_strings = | 939 v8::Handle<v8::Array> non_ascii_external_strings = |
| 948 v8::Array::New(CcTest::isolate(), kMaxLength + 1); | 940 v8::Array::New(CcTest::isolate(), kMaxLength + 1); |
| 949 | 941 |
| 950 // Generate short ascii and non-ascii external strings. | 942 // Generate short ascii and non-ascii external strings. |
| 951 for (int i = 0; i <= kMaxLength; i++) { | 943 for (int i = 0; i <= kMaxLength; i++) { |
| 952 char* ascii = zone.NewArray<char>(i + 1); | 944 char* ascii = NewArray<char>(i + 1); |
| 953 for (int j = 0; j < i; j++) { | 945 for (int j = 0; j < i; j++) { |
| 954 ascii[j] = 'a'; | 946 ascii[j] = 'a'; |
| 955 } | 947 } |
| 956 // Terminating '\0' is left out on purpose. It is not required for external | 948 // Terminating '\0' is left out on purpose. It is not required for external |
| 957 // string data. | 949 // string data. |
| 958 AsciiResource* ascii_resource = | 950 AsciiResource* ascii_resource = new AsciiResource(ascii, i); |
| 959 new(&zone) AsciiResource(Vector<const char>(ascii, i)); | |
| 960 v8::Local<v8::String> ascii_external_string = | 951 v8::Local<v8::String> ascii_external_string = |
| 961 v8::String::NewExternal(CcTest::isolate(), ascii_resource); | 952 v8::String::NewExternal(CcTest::isolate(), ascii_resource); |
| 962 | 953 |
| 963 ascii_external_strings->Set(v8::Integer::New(CcTest::isolate(), i), | 954 ascii_external_strings->Set(v8::Integer::New(CcTest::isolate(), i), |
| 964 ascii_external_string); | 955 ascii_external_string); |
| 965 uc16* non_ascii = zone.NewArray<uc16>(i + 1); | 956 uc16* non_ascii = NewArray<uc16>(i + 1); |
| 966 for (int j = 0; j < i; j++) { | 957 for (int j = 0; j < i; j++) { |
| 967 non_ascii[j] = 0x1234; | 958 non_ascii[j] = 0x1234; |
| 968 } | 959 } |
| 969 // Terminating '\0' is left out on purpose. It is not required for external | 960 // Terminating '\0' is left out on purpose. It is not required for external |
| 970 // string data. | 961 // string data. |
| 971 Resource* resource = new(&zone) Resource(Vector<const uc16>(non_ascii, i)); | 962 Resource* resource = new Resource(non_ascii, i); |
| 972 v8::Local<v8::String> non_ascii_external_string = | 963 v8::Local<v8::String> non_ascii_external_string = |
| 973 v8::String::NewExternal(CcTest::isolate(), resource); | 964 v8::String::NewExternal(CcTest::isolate(), resource); |
| 974 non_ascii_external_strings->Set(v8::Integer::New(CcTest::isolate(), i), | 965 non_ascii_external_strings->Set(v8::Integer::New(CcTest::isolate(), i), |
| 975 non_ascii_external_string); | 966 non_ascii_external_string); |
| 976 } | 967 } |
| 977 | 968 |
| 978 // Add the arrays with the short external strings in the global object. | 969 // Add the arrays with the short external strings in the global object. |
| 979 v8::Handle<v8::Object> global = context->Global(); | 970 v8::Handle<v8::Object> global = context->Global(); |
| 980 global->Set(v8_str("external_ascii"), ascii_external_strings); | 971 global->Set(v8_str("external_ascii"), ascii_external_strings); |
| 981 global->Set(v8_str("external_non_ascii"), non_ascii_external_strings); | 972 global->Set(v8_str("external_non_ascii"), non_ascii_external_strings); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1015 " }" | 1006 " }" |
| 1016 " return 0;" | 1007 " return 0;" |
| 1017 "};" | 1008 "};" |
| 1018 "test()"; | 1009 "test()"; |
| 1019 CHECK_EQ(0, CompileRun(source)->Int32Value()); | 1010 CHECK_EQ(0, CompileRun(source)->Int32Value()); |
| 1020 } | 1011 } |
| 1021 | 1012 |
| 1022 | 1013 |
| 1023 TEST(JSONStringifySliceMadeExternal) { | 1014 TEST(JSONStringifySliceMadeExternal) { |
| 1024 CcTest::InitializeVM(); | 1015 CcTest::InitializeVM(); |
| 1025 Isolate* isolate = CcTest::i_isolate(); | |
| 1026 Zone zone(isolate); | |
| 1027 // Create a sliced string from a one-byte string. The latter is turned | 1016 // Create a sliced string from a one-byte string. The latter is turned |
| 1028 // into a two-byte external string. Check that JSON.stringify works. | 1017 // into a two-byte external string. Check that JSON.stringify works. |
| 1029 v8::HandleScope handle_scope(CcTest::isolate()); | 1018 v8::HandleScope handle_scope(CcTest::isolate()); |
| 1030 v8::Handle<v8::String> underlying = | 1019 v8::Handle<v8::String> underlying = |
| 1031 CompileRun("var underlying = 'abcdefghijklmnopqrstuvwxyz';" | 1020 CompileRun("var underlying = 'abcdefghijklmnopqrstuvwxyz';" |
| 1032 "underlying")->ToString(); | 1021 "underlying")->ToString(); |
| 1033 v8::Handle<v8::String> slice = | 1022 v8::Handle<v8::String> slice = |
| 1034 CompileRun("var slice = underlying.slice(1);" | 1023 CompileRun("var slice = underlying.slice(1);" |
| 1035 "slice")->ToString(); | 1024 "slice")->ToString(); |
| 1036 CHECK(v8::Utils::OpenHandle(*slice)->IsSlicedString()); | 1025 CHECK(v8::Utils::OpenHandle(*slice)->IsSlicedString()); |
| 1037 CHECK(v8::Utils::OpenHandle(*underlying)->IsSeqOneByteString()); | 1026 CHECK(v8::Utils::OpenHandle(*underlying)->IsSeqOneByteString()); |
| 1038 | 1027 |
| 1039 int length = underlying->Length(); | 1028 int length = underlying->Length(); |
| 1040 uc16* two_byte = zone.NewArray<uc16>(length + 1); | 1029 uc16* two_byte = NewArray<uc16>(length + 1); |
| 1041 underlying->Write(two_byte); | 1030 underlying->Write(two_byte); |
| 1042 Resource* resource = | 1031 Resource* resource = new Resource(two_byte, length); |
| 1043 new(&zone) Resource(Vector<const uc16>(two_byte, length)); | |
| 1044 CHECK(underlying->MakeExternal(resource)); | 1032 CHECK(underlying->MakeExternal(resource)); |
| 1045 CHECK(v8::Utils::OpenHandle(*slice)->IsSlicedString()); | 1033 CHECK(v8::Utils::OpenHandle(*slice)->IsSlicedString()); |
| 1046 CHECK(v8::Utils::OpenHandle(*underlying)->IsExternalTwoByteString()); | 1034 CHECK(v8::Utils::OpenHandle(*underlying)->IsExternalTwoByteString()); |
| 1047 | 1035 |
| 1048 CHECK_EQ("\"bcdefghijklmnopqrstuvwxyz\"", | 1036 CHECK_EQ("\"bcdefghijklmnopqrstuvwxyz\"", |
| 1049 *v8::String::Utf8Value(CompileRun("JSON.stringify(slice)"))); | 1037 *v8::String::Utf8Value(CompileRun("JSON.stringify(slice)"))); |
| 1050 } | 1038 } |
| 1051 | 1039 |
| 1052 | 1040 |
| 1053 TEST(CachedHashOverflow) { | 1041 TEST(CachedHashOverflow) { |
| 1054 CcTest::InitializeVM(); | 1042 CcTest::InitializeVM(); |
| 1055 // We incorrectly allowed strings to be tagged as array indices even if their | 1043 // We incorrectly allowed strings to be tagged as array indices even if their |
| 1056 // values didn't fit in the hash field. | 1044 // values didn't fit in the hash field. |
| 1057 // See http://code.google.com/p/v8/issues/detail?id=728 | 1045 // See http://code.google.com/p/v8/issues/detail?id=728 |
| 1058 Isolate* isolate = CcTest::i_isolate(); | 1046 Isolate* isolate = CcTest::i_isolate(); |
| 1059 Zone zone(isolate); | |
| 1060 | 1047 |
| 1061 v8::HandleScope handle_scope(CcTest::isolate()); | 1048 v8::HandleScope handle_scope(CcTest::isolate()); |
| 1062 // Lines must be executed sequentially. Combining them into one script | 1049 // Lines must be executed sequentially. Combining them into one script |
| 1063 // makes the bug go away. | 1050 // makes the bug go away. |
| 1064 const char* lines[] = { | 1051 const char* lines[] = { |
| 1065 "var x = [];", | 1052 "var x = [];", |
| 1066 "x[4] = 42;", | 1053 "x[4] = 42;", |
| 1067 "var s = \"1073741828\";", | 1054 "var s = \"1073741828\";", |
| 1068 "x[s];", | 1055 "x[s];", |
| 1069 "x[s] = 37;", | 1056 "x[s] = 37;", |
| (...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1382 CheckCanonicalEquivalence(c, test); | 1369 CheckCanonicalEquivalence(c, test); |
| 1383 continue; | 1370 continue; |
| 1384 } | 1371 } |
| 1385 if (upper != c && lower != c) { | 1372 if (upper != c && lower != c) { |
| 1386 CheckCanonicalEquivalence(c, test); | 1373 CheckCanonicalEquivalence(c, test); |
| 1387 continue; | 1374 continue; |
| 1388 } | 1375 } |
| 1389 CHECK_EQ(Min(upper, lower), test); | 1376 CHECK_EQ(Min(upper, lower), test); |
| 1390 } | 1377 } |
| 1391 } | 1378 } |
| OLD | NEW |