Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2007-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2007-2008 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 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 413 }; | 413 }; |
| 414 | 414 |
| 415 | 415 |
| 416 int TestResource::dispose_count = 0; | 416 int TestResource::dispose_count = 0; |
| 417 | 417 |
| 418 | 418 |
| 419 class TestAsciiResource: public String::ExternalAsciiStringResource { | 419 class TestAsciiResource: public String::ExternalAsciiStringResource { |
| 420 public: | 420 public: |
| 421 static int dispose_count; | 421 static int dispose_count; |
| 422 | 422 |
| 423 explicit TestAsciiResource(char* data) | 423 explicit TestAsciiResource(const char* data) |
| 424 : data_(data), | 424 : data_(data), |
| 425 length_(strlen(data)) { } | 425 length_(strlen(data)) { } |
| 426 | 426 |
| 427 ~TestAsciiResource() { | 427 ~TestAsciiResource() { |
| 428 i::DeleteArray(data_); | 428 i::DeleteArray(data_); |
| 429 ++dispose_count; | 429 ++dispose_count; |
| 430 } | 430 } |
| 431 | 431 |
| 432 const char* data() const { | 432 const char* data() const { |
| 433 return data_; | 433 return data_; |
| 434 } | 434 } |
| 435 | 435 |
| 436 size_t length() const { | 436 size_t length() const { |
| 437 return length_; | 437 return length_; |
| 438 } | 438 } |
| 439 private: | 439 private: |
| 440 char* data_; | 440 const char* data_; |
| 441 size_t length_; | 441 size_t length_; |
| 442 }; | 442 }; |
| 443 | 443 |
| 444 | 444 |
| 445 int TestAsciiResource::dispose_count = 0; | 445 int TestAsciiResource::dispose_count = 0; |
| 446 | 446 |
| 447 | 447 |
| 448 THREADED_TEST(ScriptUsingStringResource) { | 448 THREADED_TEST(ScriptUsingStringResource) { |
| 449 TestResource::dispose_count = 0; | 449 TestResource::dispose_count = 0; |
| 450 const char* c_source = "1 + 2 * 3"; | 450 const char* c_source = "1 + 2 * 3"; |
| (...skipping 5695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6146 CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta"))); | 6146 CHECK_EQ(v8::Integer::New(123), clone->Get(v8_str("beta"))); |
| 6147 CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma"))); | 6147 CHECK_EQ(v8_str("cloneme"), clone->Get(v8_str("gamma"))); |
| 6148 | 6148 |
| 6149 // Set a property on the clone, verify each object. | 6149 // Set a property on the clone, verify each object. |
| 6150 clone->Set(v8_str("beta"), v8::Integer::New(456)); | 6150 clone->Set(v8_str("beta"), v8::Integer::New(456)); |
| 6151 CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta"))); | 6151 CHECK_EQ(v8::Integer::New(123), obj->Get(v8_str("beta"))); |
| 6152 CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta"))); | 6152 CHECK_EQ(v8::Integer::New(456), clone->Get(v8_str("beta"))); |
| 6153 } | 6153 } |
| 6154 | 6154 |
| 6155 | 6155 |
| 6156 class AsciiVectorResource : public v8::String::ExternalAsciiStringResource { | |
| 6157 public: | |
| 6158 explicit AsciiVectorResource(i::Vector<const char> vector) | |
| 6159 : data_(vector) {} | |
| 6160 virtual ~AsciiVectorResource() {} | |
| 6161 virtual size_t length() const { return data_.length(); } | |
| 6162 virtual const char* data() const { return data_.start(); } | |
| 6163 private: | |
| 6164 i::Vector<const char> data_; | |
| 6165 }; | |
| 6166 | |
| 6167 | |
| 6168 class UC16VectorResource : public v8::String::ExternalStringResource { | |
| 6169 public: | |
| 6170 explicit UC16VectorResource(i::Vector<const i::uc16> vector) | |
| 6171 : data_(vector) {} | |
| 6172 virtual ~UC16VectorResource() {} | |
| 6173 virtual size_t length() const { return data_.length(); } | |
| 6174 virtual const i::uc16* data() const { return data_.start(); } | |
| 6175 private: | |
| 6176 i::Vector<const i::uc16> data_; | |
| 6177 }; | |
| 6178 | |
| 6179 | |
| 6180 static void MorphAString(i::String* string, | |
| 6181 AsciiVectorResource* ascii_resource, | |
| 6182 UC16VectorResource* uc16_resource) { | |
| 6183 CHECK(i::StringShape(string).IsExternal()); | |
| 6184 if (string->IsAsciiRepresentation()) { | |
| 6185 // Check old map is not symbol or long. | |
| 6186 CHECK(string->map() == i::Heap::short_external_ascii_string_map() || | |
| 6187 string->map() == i::Heap::medium_external_ascii_string_map()); | |
| 6188 // Morph external string to be TwoByte string. | |
| 6189 if (string->length() <= i::String::kMaxShortStringSize) { | |
| 6190 string->set_map(i::Heap::short_external_string_map()); | |
| 6191 } else { | |
| 6192 string->set_map(i::Heap::medium_external_string_map()); | |
| 6193 } | |
| 6194 i::ExternalTwoByteString* morphed = | |
| 6195 i::ExternalTwoByteString::cast(string); | |
| 6196 morphed->set_resource(uc16_resource); | |
| 6197 } else { | |
| 6198 // Check old map is not symbol or long. | |
| 6199 CHECK(string->map() == i::Heap::short_external_string_map() || | |
| 6200 string->map() == i::Heap::medium_external_string_map()); | |
| 6201 // Morph external string to be ASCII string. | |
| 6202 if (string->length() <= i::String::kMaxShortStringSize) { | |
| 6203 string->set_map(i::Heap::short_external_ascii_string_map()); | |
| 6204 } else { | |
| 6205 string->set_map(i::Heap::medium_external_ascii_string_map()); | |
| 6206 } | |
| 6207 i::ExternalAsciiString* morphed = | |
| 6208 i::ExternalAsciiString::cast(string); | |
| 6209 morphed->set_resource(ascii_resource); | |
| 6210 } | |
| 6211 } | |
| 6212 | |
| 6213 | |
| 6214 THREADED_TEST(MorphCompositeStringTest) { | |
| 6215 const char* c_string = "Now is the time for all good men" | |
| 6216 " to come to the aid of the party"; | |
| 6217 uint16_t* two_byte_string = AsciiToTwoByteString(c_string); | |
| 6218 { | |
| 6219 v8::HandleScope scope; | |
| 6220 LocalContext env; | |
| 6221 AsciiVectorResource ascii_resource(i::Vector<const char>(c_string, strlen(c_ string))); | |
| 6222 UC16VectorResource uc16_resource(i::Vector<const uint16_t>(two_byte_string, strlen(c_string))); | |
| 6223 | |
| 6224 Local<String> lhs(v8::Utils::ToLocal(i::Factory::NewExternalStringFromAscii( &ascii_resource))); | |
| 6225 Local<String> rhs(v8::Utils::ToLocal(i::Factory::NewExternalStringFromAscii( &ascii_resource))); | |
| 6226 | |
| 6227 env->Global()->Set(v8_str("lhs"), lhs); | |
| 6228 env->Global()->Set(v8_str("rhs"), rhs); | |
| 6229 | |
| 6230 CompileRun( | |
| 6231 "var cons = lhs + rhs;" | |
| 6232 "var slice = lhs.substring(1, lhs.length - 1);" | |
| 6233 "var slice_on_cons = (lhs + rhs).substring(1, lhs.length *2 - 1);"); | |
| 6234 | |
| 6235 MorphAString(*v8::Utils::OpenHandle(*lhs), &ascii_resource, &uc16_resource); | |
| 6236 MorphAString(*v8::Utils::OpenHandle(*rhs), &ascii_resource, &uc16_resource); | |
| 6237 | |
| 6238 // Now do some stuff to make sure the strings are flattened, etc. | |
| 6239 CompileRun( | |
| 6240 "/[^a-z]/.test(cons);" | |
| 6241 "/[^a-z]/.test(slice);" | |
| 6242 "/[^a-z]/.test(slice_on_cons);"); | |
|
Lasse Reichstein
2009/05/01 09:47:01
Perhaps add a comment stating what is being tested
| |
| 6243 const char* expected_cons = | |
| 6244 "Now is the time for all good men to come to the aid of the party" | |
| 6245 "Now is the time for all good men to come to the aid of the party"; | |
| 6246 const char* expected_slice = | |
| 6247 "ow is the time for all good men to come to the aid of the part"; | |
| 6248 const char* expected_slice_on_cons = | |
| 6249 "ow is the time for all good men to come to the aid of the party" | |
| 6250 "Now is the time for all good men to come to the aid of the part"; | |
| 6251 CHECK_EQ(String::New(expected_cons), | |
| 6252 env->Global()->Get(v8_str("cons"))); | |
| 6253 CHECK_EQ(String::New(expected_slice), | |
| 6254 env->Global()->Get(v8_str("slice"))); | |
| 6255 CHECK_EQ(String::New(expected_slice_on_cons), | |
| 6256 env->Global()->Get(v8_str("slice_on_cons"))); | |
| 6257 } | |
| 6258 } | |
| 6259 | |
| 6260 | |
| 6156 class RegExpStringModificationTest { | 6261 class RegExpStringModificationTest { |
| 6157 public: | 6262 public: |
| 6158 RegExpStringModificationTest() | 6263 RegExpStringModificationTest() |
| 6159 : block_(i::OS::CreateSemaphore(0)), | 6264 : block_(i::OS::CreateSemaphore(0)), |
| 6160 morphs_(0), | 6265 morphs_(0), |
| 6161 morphs_during_regexp_(0), | 6266 morphs_during_regexp_(0), |
| 6162 ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)), | 6267 ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)), |
| 6163 uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {} | 6268 uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {} |
| 6164 ~RegExpStringModificationTest() { delete block_; } | 6269 ~RegExpStringModificationTest() { delete block_; } |
| 6165 void RunTest() { | 6270 void RunTest() { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 6190 { | 6295 { |
| 6191 v8::Unlocker unlock; | 6296 v8::Unlocker unlock; |
| 6192 morph_thread.Join(); | 6297 morph_thread.Join(); |
| 6193 } | 6298 } |
| 6194 v8::Locker::StopPreemption(); | 6299 v8::Locker::StopPreemption(); |
| 6195 CHECK(regexp_success_); | 6300 CHECK(regexp_success_); |
| 6196 CHECK(morph_success_); | 6301 CHECK(morph_success_); |
| 6197 } | 6302 } |
| 6198 private: | 6303 private: |
| 6199 | 6304 |
| 6200 class AsciiVectorResource : public v8::String::ExternalAsciiStringResource { | |
| 6201 public: | |
| 6202 explicit AsciiVectorResource(i::Vector<const char> vector) | |
| 6203 : data_(vector) {} | |
| 6204 virtual ~AsciiVectorResource() {} | |
| 6205 virtual size_t length() const { return data_.length(); } | |
| 6206 virtual const char* data() const { return data_.start(); } | |
| 6207 private: | |
| 6208 i::Vector<const char> data_; | |
| 6209 }; | |
| 6210 class UC16VectorResource : public v8::String::ExternalStringResource { | |
| 6211 public: | |
| 6212 explicit UC16VectorResource(i::Vector<const i::uc16> vector) | |
| 6213 : data_(vector) {} | |
| 6214 virtual ~UC16VectorResource() {} | |
| 6215 virtual size_t length() const { return data_.length(); } | |
| 6216 virtual const i::uc16* data() const { return data_.start(); } | |
| 6217 private: | |
| 6218 i::Vector<const i::uc16> data_; | |
| 6219 }; | |
| 6220 // Number of string modifications required. | 6305 // Number of string modifications required. |
| 6221 static const int kRequiredModifications = 5; | 6306 static const int kRequiredModifications = 5; |
| 6222 static const int kMaxModifications = 100; | 6307 static const int kMaxModifications = 100; |
| 6223 | 6308 |
| 6224 class MorphThread : public i::Thread { | 6309 class MorphThread : public i::Thread { |
| 6225 public: | 6310 public: |
| 6226 explicit MorphThread(RegExpStringModificationTest* test) | 6311 explicit MorphThread(RegExpStringModificationTest* test) |
| 6227 : test_(test) {} | 6312 : test_(test) {} |
| 6228 virtual void Run() { | 6313 virtual void Run() { |
| 6229 test_->MorphString(); | 6314 test_->MorphString(); |
| 6230 } | 6315 } |
| 6231 private: | 6316 private: |
| 6232 RegExpStringModificationTest* test_; | 6317 RegExpStringModificationTest* test_; |
| 6233 }; | 6318 }; |
| 6234 | 6319 |
| 6235 void MorphString() { | 6320 void MorphString() { |
| 6236 block_->Wait(); | 6321 block_->Wait(); |
| 6237 while (morphs_during_regexp_ < kRequiredModifications && | 6322 while (morphs_during_regexp_ < kRequiredModifications && |
| 6238 morphs_ < kMaxModifications) { | 6323 morphs_ < kMaxModifications) { |
| 6239 { | 6324 { |
| 6240 v8::Locker lock; | 6325 v8::Locker lock; |
| 6241 // Swap string between ascii and two-byte representation. | 6326 // Swap string between ascii and two-byte representation. |
| 6242 i::String* string = *input_; | 6327 i::String* string = *input_; |
| 6243 CHECK(i::StringShape(string).IsExternal()); | 6328 MorphAString(string, &ascii_resource_, &uc16_resource_); |
| 6244 if (i::StringShape(string).IsAsciiRepresentation()) { | |
| 6245 // Morph external string to be TwoByte string. | |
| 6246 i::ExternalAsciiString* ext_string = | |
| 6247 i::ExternalAsciiString::cast(string); | |
| 6248 i::ExternalTwoByteString* morphed = | |
| 6249 reinterpret_cast<i::ExternalTwoByteString*>(ext_string); | |
| 6250 morphed->map()->set_instance_type(i::SHORT_EXTERNAL_STRING_TYPE); | |
| 6251 morphed->set_resource(&uc16_resource_); | |
| 6252 } else { | |
| 6253 // Morph external string to be ASCII string. | |
| 6254 i::ExternalTwoByteString* ext_string = | |
| 6255 i::ExternalTwoByteString::cast(string); | |
| 6256 i::ExternalAsciiString* morphed = | |
| 6257 reinterpret_cast<i::ExternalAsciiString*>(ext_string); | |
| 6258 morphed->map()->set_instance_type( | |
| 6259 i::SHORT_EXTERNAL_ASCII_STRING_TYPE); | |
| 6260 morphed->set_resource(&ascii_resource_); | |
| 6261 } | |
| 6262 morphs_++; | 6329 morphs_++; |
| 6263 } | 6330 } |
| 6264 i::OS::Sleep(1); | 6331 i::OS::Sleep(1); |
| 6265 } | 6332 } |
| 6266 morph_success_ = true; | 6333 morph_success_ = true; |
| 6267 } | 6334 } |
| 6268 | 6335 |
| 6269 void LongRunningRegExp() { | 6336 void LongRunningRegExp() { |
| 6270 block_->Signal(); // Enable morphing thread on next preemption. | 6337 block_->Signal(); // Enable morphing thread on next preemption. |
| 6271 while (morphs_during_regexp_ < kRequiredModifications && | 6338 while (morphs_during_regexp_ < kRequiredModifications && |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6451 // the property | 6518 // the property |
| 6452 pass_on_get = false; | 6519 pass_on_get = false; |
| 6453 CHECK_EQ(3, global->Get(some_property)->Int32Value()); | 6520 CHECK_EQ(3, global->Get(some_property)->Int32Value()); |
| 6454 CHECK_EQ(1, force_set_set_count); | 6521 CHECK_EQ(1, force_set_set_count); |
| 6455 CHECK_EQ(5, force_set_get_count); | 6522 CHECK_EQ(5, force_set_get_count); |
| 6456 // The interceptor should also work for other properties | 6523 // The interceptor should also work for other properties |
| 6457 CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value()); | 6524 CHECK_EQ(3, global->Get(v8::String::New("b"))->Int32Value()); |
| 6458 CHECK_EQ(1, force_set_set_count); | 6525 CHECK_EQ(1, force_set_set_count); |
| 6459 CHECK_EQ(6, force_set_get_count); | 6526 CHECK_EQ(6, force_set_get_count); |
| 6460 } | 6527 } |
| OLD | NEW |