| 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 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 // Create a sliced string that will land in old pointer space. | 730 // Create a sliced string that will land in old pointer space. |
| 731 Local<String> slice = Local<String>::Cast(CompileRun( | 731 Local<String> slice = Local<String>::Cast(CompileRun( |
| 732 "slice('abcdefghijklmnopqrstuvwxyz');")); | 732 "slice('abcdefghijklmnopqrstuvwxyz');")); |
| 733 | 733 |
| 734 // Trigger GCs so that the newly allocated string moves to old gen. | 734 // Trigger GCs so that the newly allocated string moves to old gen. |
| 735 SimulateFullSpace(CcTest::heap()->old_pointer_space()); | 735 SimulateFullSpace(CcTest::heap()->old_pointer_space()); |
| 736 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now | 736 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in survivor space now |
| 737 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now | 737 CcTest::heap()->CollectGarbage(i::NEW_SPACE); // in old gen now |
| 738 | 738 |
| 739 // Turn into external string with unaligned resource data. | 739 // Turn into external string with unaligned resource data. |
| 740 int dispose_count = 0; | |
| 741 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz"; | 740 const char* c_cons = "_abcdefghijklmnopqrstuvwxyz"; |
| 742 bool success = cons->MakeExternal( | 741 bool success = cons->MakeExternal( |
| 743 new TestAsciiResource(i::StrDup(c_cons), &dispose_count, 1)); | 742 new TestAsciiResource(i::StrDup(c_cons), NULL, 1)); |
| 744 CHECK(success); | 743 CHECK(success); |
| 745 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz"; | 744 const char* c_slice = "_bcdefghijklmnopqrstuvwxyz"; |
| 746 success = slice->MakeExternal( | 745 success = slice->MakeExternal( |
| 747 new TestAsciiResource(i::StrDup(c_slice), &dispose_count, 1)); | 746 new TestAsciiResource(i::StrDup(c_slice), NULL, 1)); |
| 748 CHECK(success); | 747 CHECK(success); |
| 749 | 748 |
| 750 // Trigger GCs and force evacuation. | 749 // Trigger GCs and force evacuation. |
| 751 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); | 750 CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags); |
| 752 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask); | 751 CcTest::heap()->CollectAllGarbage(i::Heap::kReduceMemoryFootprintMask); |
| 753 } | 752 } |
| 754 | 753 |
| 755 | 754 |
| 756 THREADED_TEST(UsingExternalString) { | 755 THREADED_TEST(UsingExternalString) { |
| 757 i::Factory* factory = CcTest::i_isolate()->factory(); | 756 i::Factory* factory = CcTest::i_isolate()->factory(); |
| (...skipping 6282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7040 v8::RegisterExtension(new Extension("B", "", 1, bDeps)); | 7039 v8::RegisterExtension(new Extension("B", "", 1, bDeps)); |
| 7041 last_location = NULL; | 7040 last_location = NULL; |
| 7042 v8::ExtensionConfiguration config(1, bDeps); | 7041 v8::ExtensionConfiguration config(1, bDeps); |
| 7043 v8::Handle<Context> context = | 7042 v8::Handle<Context> context = |
| 7044 Context::New(CcTest::isolate(), &config); | 7043 Context::New(CcTest::isolate(), &config); |
| 7045 CHECK(context.IsEmpty()); | 7044 CHECK(context.IsEmpty()); |
| 7046 CHECK_NE(last_location, NULL); | 7045 CHECK_NE(last_location, NULL); |
| 7047 } | 7046 } |
| 7048 | 7047 |
| 7049 | 7048 |
| 7050 static const char* js_code_causing_huge_string_flattening = | |
| 7051 "var str = 'X';" | |
| 7052 "for (var i = 0; i < 30; i++) {" | |
| 7053 " str = str + str;" | |
| 7054 "}" | |
| 7055 "str.match(/X/);"; | |
| 7056 | |
| 7057 | |
| 7058 TEST(RegexpOutOfMemory) { | |
| 7059 // Execute a script that causes out of memory when flattening a string. | |
| 7060 v8::HandleScope scope(CcTest::isolate()); | |
| 7061 v8::V8::SetFatalErrorHandler(OOMCallback); | |
| 7062 LocalContext context; | |
| 7063 Local<Script> script = Script::Compile(String::NewFromUtf8( | |
| 7064 CcTest::isolate(), js_code_causing_huge_string_flattening)); | |
| 7065 last_location = NULL; | |
| 7066 script->Run(); | |
| 7067 | |
| 7068 CHECK(false); // Should not return. | |
| 7069 } | |
| 7070 | |
| 7071 | |
| 7072 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message, | 7049 static void MissingScriptInfoMessageListener(v8::Handle<v8::Message> message, |
| 7073 v8::Handle<Value> data) { | 7050 v8::Handle<Value> data) { |
| 7074 CHECK(message->GetScriptResourceName()->IsUndefined()); | 7051 CHECK(message->GetScriptResourceName()->IsUndefined()); |
| 7075 CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName()); | 7052 CHECK_EQ(v8::Undefined(CcTest::isolate()), message->GetScriptResourceName()); |
| 7076 message->GetLineNumber(); | 7053 message->GetLineNumber(); |
| 7077 message->GetSourceLine(); | 7054 message->GetSourceLine(); |
| 7078 } | 7055 } |
| 7079 | 7056 |
| 7080 | 7057 |
| 7081 THREADED_TEST(ErrorWithMissingScriptInfo) { | 7058 THREADED_TEST(ErrorWithMissingScriptInfo) { |
| 7082 LocalContext context; | 7059 LocalContext context; |
| 7083 v8::HandleScope scope(context->GetIsolate()); | 7060 v8::HandleScope scope(context->GetIsolate()); |
| 7084 v8::V8::AddMessageListener(MissingScriptInfoMessageListener); | 7061 v8::V8::AddMessageListener(MissingScriptInfoMessageListener); |
| 7085 Script::Compile(v8_str("throw Error()"))->Run(); | 7062 Script::Compile(v8_str("throw Error()"))->Run(); |
| 7086 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener); | 7063 v8::V8::RemoveMessageListeners(MissingScriptInfoMessageListener); |
| 7087 } | 7064 } |
| 7088 | 7065 |
| 7089 | 7066 |
| 7090 int global_index = 0; | |
| 7091 | |
| 7092 template<typename T> | |
| 7093 class Snorkel { | |
| 7094 public: | |
| 7095 explicit Snorkel(v8::Persistent<T>* handle) : handle_(handle) { | |
| 7096 index_ = global_index++; | |
| 7097 } | |
| 7098 v8::Persistent<T>* handle_; | |
| 7099 int index_; | |
| 7100 }; | |
| 7101 | |
| 7102 class Whammy { | |
| 7103 public: | |
| 7104 explicit Whammy(v8::Isolate* isolate) : cursor_(0), isolate_(isolate) { } | |
| 7105 ~Whammy() { script_.Reset(); } | |
| 7106 v8::Handle<Script> getScript() { | |
| 7107 if (script_.IsEmpty()) script_.Reset(isolate_, v8_compile("({}).blammo")); | |
| 7108 return Local<Script>::New(isolate_, script_); | |
| 7109 } | |
| 7110 | |
| 7111 public: | |
| 7112 static const int kObjectCount = 256; | |
| 7113 int cursor_; | |
| 7114 v8::Isolate* isolate_; | |
| 7115 v8::Persistent<v8::Object> objects_[kObjectCount]; | |
| 7116 v8::Persistent<Script> script_; | |
| 7117 }; | |
| 7118 | |
| 7119 static void HandleWeakReference( | |
| 7120 const v8::WeakCallbackData<v8::Value, Snorkel<v8::Value> >& data) { | |
| 7121 data.GetParameter()->handle_->ClearWeak(); | |
| 7122 delete data.GetParameter(); | |
| 7123 } | |
| 7124 | |
| 7125 void WhammyPropertyGetter(Local<String> name, | |
| 7126 const v8::PropertyCallbackInfo<v8::Value>& info) { | |
| 7127 Whammy* whammy = | |
| 7128 static_cast<Whammy*>(v8::Handle<v8::External>::Cast(info.Data())->Value()); | |
| 7129 | |
| 7130 v8::Persistent<v8::Object>& prev = whammy->objects_[whammy->cursor_]; | |
| 7131 | |
| 7132 v8::Handle<v8::Object> obj = v8::Object::New(info.GetIsolate()); | |
| 7133 if (!prev.IsEmpty()) { | |
| 7134 v8::Local<v8::Object>::New(info.GetIsolate(), prev) | |
| 7135 ->Set(v8_str("next"), obj); | |
| 7136 prev.SetWeak<Value, Snorkel<Value> >(new Snorkel<Value>(&prev.As<Value>()), | |
| 7137 &HandleWeakReference); | |
| 7138 } | |
| 7139 whammy->objects_[whammy->cursor_].Reset(info.GetIsolate(), obj); | |
| 7140 whammy->cursor_ = (whammy->cursor_ + 1) % Whammy::kObjectCount; | |
| 7141 info.GetReturnValue().Set(whammy->getScript()->Run()); | |
| 7142 } | |
| 7143 | |
| 7144 | |
| 7145 TEST(WeakReference) { | |
| 7146 i::FLAG_expose_gc = true; | |
| 7147 v8::Isolate* isolate = CcTest::isolate(); | |
| 7148 v8::HandleScope handle_scope(isolate); | |
| 7149 v8::Handle<v8::ObjectTemplate> templ= v8::ObjectTemplate::New(isolate); | |
| 7150 Whammy* whammy = new Whammy(CcTest::isolate()); | |
| 7151 templ->SetNamedPropertyHandler(WhammyPropertyGetter, | |
| 7152 0, 0, 0, 0, | |
| 7153 v8::External::New(CcTest::isolate(), whammy)); | |
| 7154 const char* extension_list[] = { "v8/gc" }; | |
| 7155 v8::ExtensionConfiguration extensions(1, extension_list); | |
| 7156 v8::Handle<Context> context = | |
| 7157 Context::New(CcTest::isolate(), &extensions); | |
| 7158 Context::Scope context_scope(context); | |
| 7159 | |
| 7160 v8::Handle<v8::Object> interceptor = templ->NewInstance(); | |
| 7161 context->Global()->Set(v8_str("whammy"), interceptor); | |
| 7162 const char* code = | |
| 7163 "var last;" | |
| 7164 "for (var i = 0; i < 10000; i++) {" | |
| 7165 " var obj = whammy.length;" | |
| 7166 " if (last) last.next = obj;" | |
| 7167 " last = obj;" | |
| 7168 "}" | |
| 7169 "gc();" | |
| 7170 "4"; | |
| 7171 v8::Handle<Value> result = CompileRun(code); | |
| 7172 CHECK_EQ(4.0, result->NumberValue()); | |
| 7173 delete whammy; | |
| 7174 } | |
| 7175 | |
| 7176 | |
| 7177 struct FlagAndPersistent { | 7067 struct FlagAndPersistent { |
| 7178 bool flag; | 7068 bool flag; |
| 7179 v8::Persistent<v8::Object> handle; | 7069 v8::Persistent<v8::Object> handle; |
| 7180 }; | 7070 }; |
| 7181 | 7071 |
| 7182 | 7072 |
| 7183 static void DisposeAndSetFlag( | 7073 static void DisposeAndSetFlag( |
| 7184 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) { | 7074 const v8::WeakCallbackData<v8::Object, FlagAndPersistent>& data) { |
| 7185 data.GetParameter()->handle.Reset(); | 7075 data.GetParameter()->handle.Reset(); |
| 7186 data.GetParameter()->flag = true; | 7076 data.GetParameter()->flag = true; |
| (...skipping 7741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14928 v8::ScriptData* deserialized_sd = | 14818 v8::ScriptData* deserialized_sd = |
| 14929 v8::ScriptData::New(serialized_data, serialized_data_length); | 14819 v8::ScriptData::New(serialized_data, serialized_data_length); |
| 14930 | 14820 |
| 14931 // Verify that the original is the same as the deserialized. | 14821 // Verify that the original is the same as the deserialized. |
| 14932 CHECK_EQ(sd->Length(), deserialized_sd->Length()); | 14822 CHECK_EQ(sd->Length(), deserialized_sd->Length()); |
| 14933 CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length())); | 14823 CHECK_EQ(0, memcmp(sd->Data(), deserialized_sd->Data(), sd->Length())); |
| 14934 CHECK_EQ(sd->HasError(), deserialized_sd->HasError()); | 14824 CHECK_EQ(sd->HasError(), deserialized_sd->HasError()); |
| 14935 | 14825 |
| 14936 delete sd; | 14826 delete sd; |
| 14937 delete deserialized_sd; | 14827 delete deserialized_sd; |
| 14828 i::DeleteArray(serialized_data); |
| 14938 } | 14829 } |
| 14939 | 14830 |
| 14940 | 14831 |
| 14941 // Attempts to deserialize bad data. | 14832 // Attempts to deserialize bad data. |
| 14942 TEST(PreCompileDeserializationError) { | 14833 TEST(PreCompileDeserializationError) { |
| 14943 v8::V8::Initialize(); | 14834 v8::V8::Initialize(); |
| 14944 const char* data = "DONT CARE"; | 14835 const char* data = "DONT CARE"; |
| 14945 int invalid_size = 3; | 14836 int invalid_size = 3; |
| 14946 v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size); | 14837 v8::ScriptData* sd = v8::ScriptData::New(data, invalid_size); |
| 14947 | 14838 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 14976 v8::TryCatch try_catch; | 14867 v8::TryCatch try_catch; |
| 14977 | 14868 |
| 14978 Local<String> source = String::NewFromUtf8(isolate, script); | 14869 Local<String> source = String::NewFromUtf8(isolate, script); |
| 14979 Local<Script> compiled_script = Script::New(source, NULL, sd); | 14870 Local<Script> compiled_script = Script::New(source, NULL, sd); |
| 14980 CHECK(try_catch.HasCaught()); | 14871 CHECK(try_catch.HasCaught()); |
| 14981 String::Utf8Value exception_value(try_catch.Message()->Get()); | 14872 String::Utf8Value exception_value(try_catch.Message()->Get()); |
| 14982 CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar", | 14873 CHECK_EQ("Uncaught SyntaxError: Invalid preparser data for function bar", |
| 14983 *exception_value); | 14874 *exception_value); |
| 14984 | 14875 |
| 14985 try_catch.Reset(); | 14876 try_catch.Reset(); |
| 14877 delete sd; |
| 14986 | 14878 |
| 14987 // Overwrite function bar's start position with 200. The function entry | 14879 // Overwrite function bar's start position with 200. The function entry |
| 14988 // will not be found when searching for it by position and we should fall | 14880 // will not be found when searching for it by position and we should fall |
| 14989 // back on eager compilation. | 14881 // back on eager compilation. |
| 14990 sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8( | 14882 sd = v8::ScriptData::PreCompile(v8::String::NewFromUtf8( |
| 14991 isolate, script, v8::String::kNormalString, i::StrLength(script))); | 14883 isolate, script, v8::String::kNormalString, i::StrLength(script))); |
| 14992 sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data())); | 14884 sd_data = reinterpret_cast<unsigned*>(const_cast<char*>(sd->Data())); |
| 14993 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] = | 14885 sd_data[kHeaderSize + 1 * kFunctionEntrySize + kFunctionEntryStartOffset] = |
| 14994 200; | 14886 200; |
| 14995 compiled_script = Script::New(source, NULL, sd); | 14887 compiled_script = Script::New(source, NULL, sd); |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15291 i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content))); | 15183 i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content))); |
| 15292 | 15184 |
| 15293 v8::TryCatch try_catch; | 15185 v8::TryCatch try_catch; |
| 15294 timeout_thread.Start(); | 15186 timeout_thread.Start(); |
| 15295 | 15187 |
| 15296 CompileRun("/((a*)*)*b/.exec(a)"); | 15188 CompileRun("/((a*)*)*b/.exec(a)"); |
| 15297 CHECK(try_catch.HasTerminated()); | 15189 CHECK(try_catch.HasTerminated()); |
| 15298 | 15190 |
| 15299 timeout_thread.Join(); | 15191 timeout_thread.Join(); |
| 15300 | 15192 |
| 15301 delete regexp_interruption_data.string_resource; | |
| 15302 regexp_interruption_data.string.Reset(); | 15193 regexp_interruption_data.string.Reset(); |
| 15194 i::DeleteArray(uc16_content); |
| 15303 } | 15195 } |
| 15304 | 15196 |
| 15305 #endif // V8_INTERPRETED_REGEXP | 15197 #endif // V8_INTERPRETED_REGEXP |
| 15306 | 15198 |
| 15307 | 15199 |
| 15308 // Test that we cannot set a property on the global object if there | 15200 // Test that we cannot set a property on the global object if there |
| 15309 // is a read-only property in the prototype chain. | 15201 // is a read-only property in the prototype chain. |
| 15310 TEST(ReadOnlyPropertyInGlobalProto) { | 15202 TEST(ReadOnlyPropertyInGlobalProto) { |
| 15311 i::FLAG_es5_readonly = true; | 15203 i::FLAG_es5_readonly = true; |
| 15312 v8::Isolate* isolate = CcTest::isolate(); | 15204 v8::Isolate* isolate = CcTest::isolate(); |
| (...skipping 2544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 17857 CHECK(found_resource_[i]); | 17749 CHECK(found_resource_[i]); |
| 17858 } | 17750 } |
| 17859 } | 17751 } |
| 17860 | 17752 |
| 17861 private: | 17753 private: |
| 17862 v8::String::ExternalStringResource* resource_[4]; | 17754 v8::String::ExternalStringResource* resource_[4]; |
| 17863 bool found_resource_[4]; | 17755 bool found_resource_[4]; |
| 17864 }; | 17756 }; |
| 17865 | 17757 |
| 17866 | 17758 |
| 17759 TEST(ExternalizeOldSpaceTwoByteCons) { |
| 17760 LocalContext env; |
| 17761 v8::HandleScope scope(env->GetIsolate()); |
| 17762 v8::Local<v8::String> cons = |
| 17763 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(); |
| 17764 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString()); |
| 17765 CcTest::heap()->CollectAllAvailableGarbage(); |
| 17766 CHECK(CcTest::heap()->old_pointer_space()->Contains( |
| 17767 *v8::Utils::OpenHandle(*cons))); |
| 17768 |
| 17769 TestResource* resource = new TestResource( |
| 17770 AsciiToTwoByteString("Romeo Montague Juliet Capulet")); |
| 17771 cons->MakeExternal(resource); |
| 17772 |
| 17773 CHECK(cons->IsExternal()); |
| 17774 CHECK_EQ(resource, cons->GetExternalStringResource()); |
| 17775 String::Encoding encoding; |
| 17776 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding)); |
| 17777 CHECK_EQ(String::TWO_BYTE_ENCODING, encoding); |
| 17778 } |
| 17779 |
| 17780 |
| 17781 TEST(ExternalizeOldSpaceOneByteCons) { |
| 17782 LocalContext env; |
| 17783 v8::HandleScope scope(env->GetIsolate()); |
| 17784 v8::Local<v8::String> cons = |
| 17785 CompileRun("'Romeo Montague ' + 'Juliet Capulet'")->ToString(); |
| 17786 CHECK(v8::Utils::OpenHandle(*cons)->IsConsString()); |
| 17787 CcTest::heap()->CollectAllAvailableGarbage(); |
| 17788 CHECK(CcTest::heap()->old_pointer_space()->Contains( |
| 17789 *v8::Utils::OpenHandle(*cons))); |
| 17790 |
| 17791 TestAsciiResource* resource = |
| 17792 new TestAsciiResource(i::StrDup("Romeo Montague Juliet Capulet")); |
| 17793 cons->MakeExternal(resource); |
| 17794 |
| 17795 CHECK(cons->IsExternalAscii()); |
| 17796 CHECK_EQ(resource, cons->GetExternalAsciiStringResource()); |
| 17797 String::Encoding encoding; |
| 17798 CHECK_EQ(resource, cons->GetExternalStringResourceBase(&encoding)); |
| 17799 CHECK_EQ(String::ONE_BYTE_ENCODING, encoding); |
| 17800 } |
| 17801 |
| 17802 |
| 17867 TEST(VisitExternalStrings) { | 17803 TEST(VisitExternalStrings) { |
| 17868 LocalContext env; | 17804 LocalContext env; |
| 17869 v8::HandleScope scope(env->GetIsolate()); | 17805 v8::HandleScope scope(env->GetIsolate()); |
| 17870 const char* string = "Some string"; | 17806 const char* string = "Some string"; |
| 17871 uint16_t* two_byte_string = AsciiToTwoByteString(string); | 17807 uint16_t* two_byte_string = AsciiToTwoByteString(string); |
| 17872 TestResource* resource[4]; | 17808 TestResource* resource[4]; |
| 17873 resource[0] = new TestResource(two_byte_string); | 17809 resource[0] = new TestResource(two_byte_string); |
| 17874 v8::Local<v8::String> string0 = | 17810 v8::Local<v8::String> string0 = |
| 17875 v8::String::NewExternal(env->GetIsolate(), resource[0]); | 17811 v8::String::NewExternal(env->GetIsolate(), resource[0]); |
| 17876 resource[1] = new TestResource(two_byte_string, NULL, false); | 17812 resource[1] = new TestResource(two_byte_string, NULL, false); |
| (...skipping 1230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 19107 v8::V8::SetFatalErrorHandler(StoringErrorCallback); | 19043 v8::V8::SetFatalErrorHandler(StoringErrorCallback); |
| 19108 last_location = last_message = NULL; | 19044 last_location = last_message = NULL; |
| 19109 isolate->Dispose(); | 19045 isolate->Dispose(); |
| 19110 CHECK_EQ(last_location, NULL); | 19046 CHECK_EQ(last_location, NULL); |
| 19111 CHECK_EQ(last_message, NULL); | 19047 CHECK_EQ(last_message, NULL); |
| 19112 } | 19048 } |
| 19113 | 19049 |
| 19114 | 19050 |
| 19115 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) { | 19051 UNINITIALIZED_TEST(DisposeIsolateWhenInUse) { |
| 19116 v8::Isolate* isolate = v8::Isolate::New(); | 19052 v8::Isolate* isolate = v8::Isolate::New(); |
| 19117 CHECK(isolate); | 19053 { |
| 19118 isolate->Enter(); | 19054 v8::Isolate::Scope i_scope(isolate); |
| 19119 v8::HandleScope scope(isolate); | 19055 v8::HandleScope scope(isolate); |
| 19120 LocalContext context(isolate); | 19056 LocalContext context(isolate); |
| 19121 // Run something in this isolate. | 19057 // Run something in this isolate. |
| 19122 ExpectTrue("true"); | 19058 ExpectTrue("true"); |
| 19123 v8::V8::SetFatalErrorHandler(StoringErrorCallback); | 19059 v8::V8::SetFatalErrorHandler(StoringErrorCallback); |
| 19124 last_location = last_message = NULL; | 19060 last_location = last_message = NULL; |
| 19125 // Still entered, should fail. | 19061 // Still entered, should fail. |
| 19062 isolate->Dispose(); |
| 19063 CHECK_NE(last_location, NULL); |
| 19064 CHECK_NE(last_message, NULL); |
| 19065 } |
| 19126 isolate->Dispose(); | 19066 isolate->Dispose(); |
| 19127 CHECK_NE(last_location, NULL); | |
| 19128 CHECK_NE(last_message, NULL); | |
| 19129 } | 19067 } |
| 19130 | 19068 |
| 19131 | 19069 |
| 19132 TEST(RunTwoIsolatesOnSingleThread) { | 19070 TEST(RunTwoIsolatesOnSingleThread) { |
| 19133 // Run isolate 1. | 19071 // Run isolate 1. |
| 19134 v8::Isolate* isolate1 = v8::Isolate::New(); | 19072 v8::Isolate* isolate1 = v8::Isolate::New(); |
| 19135 isolate1->Enter(); | 19073 isolate1->Enter(); |
| 19136 v8::Persistent<v8::Context> context1; | 19074 v8::Persistent<v8::Context> context1; |
| 19137 { | 19075 { |
| 19138 v8::HandleScope scope(isolate1); | 19076 v8::HandleScope scope(isolate1); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 19333 } | 19271 } |
| 19334 { | 19272 { |
| 19335 v8::Isolate::Scope isolate_scope(isolate); | 19273 v8::Isolate::Scope isolate_scope(isolate); |
| 19336 v8::HandleScope handle_scope(isolate); | 19274 v8::HandleScope handle_scope(isolate); |
| 19337 context = v8::Context::New(isolate); | 19275 context = v8::Context::New(isolate); |
| 19338 v8::Context::Scope context_scope(context); | 19276 v8::Context::Scope context_scope(context); |
| 19339 Local<Value> v = CompileRun("22"); | 19277 Local<Value> v = CompileRun("22"); |
| 19340 CHECK(v->IsNumber()); | 19278 CHECK(v->IsNumber()); |
| 19341 CHECK_EQ(22, static_cast<int>(v->NumberValue())); | 19279 CHECK_EQ(22, static_cast<int>(v->NumberValue())); |
| 19342 } | 19280 } |
| 19281 isolate->Dispose(); |
| 19343 } | 19282 } |
| 19344 | 19283 |
| 19345 class InitDefaultIsolateThread : public v8::internal::Thread { | 19284 class InitDefaultIsolateThread : public v8::internal::Thread { |
| 19346 public: | 19285 public: |
| 19347 enum TestCase { | 19286 enum TestCase { |
| 19348 IgnoreOOM, | 19287 IgnoreOOM, |
| 19349 SetResourceConstraints, | 19288 SetResourceConstraints, |
| 19350 SetFatalHandler, | 19289 SetFatalHandler, |
| 19351 SetCounterFunction, | 19290 SetCounterFunction, |
| 19352 SetCreateHistogramFunction, | 19291 SetCreateHistogramFunction, |
| (...skipping 2510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21863 static Local<Object> receiver; | 21802 static Local<Object> receiver; |
| 21864 static Local<Object> holder; | 21803 static Local<Object> holder; |
| 21865 static Local<Object> callee; | 21804 static Local<Object> callee; |
| 21866 static int count; | 21805 static int count; |
| 21867 | 21806 |
| 21868 static void OptimizationCallback( | 21807 static void OptimizationCallback( |
| 21869 const v8::FunctionCallbackInfo<v8::Value>& info) { | 21808 const v8::FunctionCallbackInfo<v8::Value>& info) { |
| 21870 CHECK(callee == info.Callee()); | 21809 CHECK(callee == info.Callee()); |
| 21871 CHECK(data == info.Data()); | 21810 CHECK(data == info.Data()); |
| 21872 CHECK(receiver == info.This()); | 21811 CHECK(receiver == info.This()); |
| 21812 if (info.Length() == 1) { |
| 21813 CHECK_EQ(v8_num(1), info[0]); |
| 21814 } |
| 21873 CHECK(holder == info.Holder()); | 21815 CHECK(holder == info.Holder()); |
| 21874 count++; | 21816 count++; |
| 21875 } | 21817 } |
| 21876 | 21818 |
| 21819 // TODO(dcarney): move this to v8.h |
| 21820 static void SetAccessorProperty(Local<Object> object, |
| 21821 Local<String> name, |
| 21822 Local<Function> getter, |
| 21823 Local<Function> setter = Local<Function>()) { |
| 21824 i::Isolate* isolate = CcTest::i_isolate(); |
| 21825 v8::AccessControl settings = v8::DEFAULT; |
| 21826 v8::PropertyAttribute attribute = v8::None; |
| 21827 i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter); |
| 21828 i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true); |
| 21829 if (setter_i.is_null()) setter_i = isolate->factory()->null_value(); |
| 21830 i::JSObject::DefineAccessor(v8::Utils::OpenHandle(*object), |
| 21831 v8::Utils::OpenHandle(*name), |
| 21832 getter_i, |
| 21833 setter_i, |
| 21834 static_cast<PropertyAttributes>(attribute), |
| 21835 settings); |
| 21836 } |
| 21837 |
| 21877 public: | 21838 public: |
| 21878 void Run(bool use_signature, bool global) { | 21839 void Run(bool use_signature, bool global) { |
| 21879 v8::Isolate* isolate = CcTest::isolate(); | 21840 v8::Isolate* isolate = CcTest::isolate(); |
| 21880 v8::HandleScope scope(isolate); | 21841 v8::HandleScope scope(isolate); |
| 21881 // Build a template for signature checks. | 21842 // Build a template for signature checks. |
| 21882 Local<v8::ObjectTemplate> signature_template; | 21843 Local<v8::ObjectTemplate> signature_template; |
| 21883 Local<v8::Signature> signature; | 21844 Local<v8::Signature> signature; |
| 21884 { | 21845 { |
| 21885 Local<v8::FunctionTemplate> parent_template = | 21846 Local<v8::FunctionTemplate> parent_template = |
| 21886 FunctionTemplate::New(isolate); | 21847 FunctionTemplate::New(isolate); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 21903 // Get the holder objects. | 21864 // Get the holder objects. |
| 21904 Local<Object> inner_global = | 21865 Local<Object> inner_global = |
| 21905 Local<Object>::Cast(context->Global()->GetPrototype()); | 21866 Local<Object>::Cast(context->Global()->GetPrototype()); |
| 21906 Local<Object> function_holder = | 21867 Local<Object> function_holder = |
| 21907 Local<Object>::Cast(function_receiver->GetPrototype()); | 21868 Local<Object>::Cast(function_receiver->GetPrototype()); |
| 21908 // Install function on hidden prototype object. | 21869 // Install function on hidden prototype object. |
| 21909 data = Object::New(isolate); | 21870 data = Object::New(isolate); |
| 21910 Local<FunctionTemplate> function_template = FunctionTemplate::New( | 21871 Local<FunctionTemplate> function_template = FunctionTemplate::New( |
| 21911 isolate, OptimizationCallback, data, signature); | 21872 isolate, OptimizationCallback, data, signature); |
| 21912 Local<Function> function = function_template->GetFunction(); | 21873 Local<Function> function = function_template->GetFunction(); |
| 21913 Local<Object>::Cast( | 21874 Local<Object> global_holder = Local<Object>::Cast( |
| 21914 inner_global->GetPrototype())->Set(v8_str("global_f"), function); | 21875 inner_global->GetPrototype()); |
| 21876 global_holder->Set(v8_str("g_f"), function); |
| 21877 SetAccessorProperty(global_holder, v8_str("g_acc"), function, function); |
| 21915 function_holder->Set(v8_str("f"), function); | 21878 function_holder->Set(v8_str("f"), function); |
| 21879 SetAccessorProperty(function_holder, v8_str("acc"), function, function); |
| 21916 // Initialize expected values. | 21880 // Initialize expected values. |
| 21917 callee = function; | 21881 callee = function; |
| 21918 count = 0; | 21882 count = 0; |
| 21919 if (global) { | 21883 if (global) { |
| 21920 receiver = context->Global(); | 21884 receiver = context->Global(); |
| 21921 holder = inner_global; | 21885 holder = inner_global; |
| 21922 } else { | 21886 } else { |
| 21923 holder = function_receiver; | 21887 holder = function_receiver; |
| 21924 // If not using a signature, add something else to the prototype chain | 21888 // If not using a signature, add something else to the prototype chain |
| 21925 // to test the case that holder != receiver | 21889 // to test the case that holder != receiver |
| 21926 if (!use_signature) { | 21890 if (!use_signature) { |
| 21927 receiver = Local<Object>::Cast(CompileRun( | 21891 receiver = Local<Object>::Cast(CompileRun( |
| 21928 "var receiver_subclass = {};\n" | 21892 "var receiver_subclass = {};\n" |
| 21929 "receiver_subclass.__proto__ = function_receiver;\n" | 21893 "receiver_subclass.__proto__ = function_receiver;\n" |
| 21930 "receiver_subclass")); | 21894 "receiver_subclass")); |
| 21931 } else { | 21895 } else { |
| 21932 receiver = Local<Object>::Cast(CompileRun( | 21896 receiver = Local<Object>::Cast(CompileRun( |
| 21933 "var receiver_subclass = function_receiver;\n" | 21897 "var receiver_subclass = function_receiver;\n" |
| 21934 "receiver_subclass")); | 21898 "receiver_subclass")); |
| 21935 } | 21899 } |
| 21936 } | 21900 } |
| 21937 // With no signature, the holder is not set. | 21901 // With no signature, the holder is not set. |
| 21938 if (!use_signature) holder = receiver; | 21902 if (!use_signature) holder = receiver; |
| 21939 // build wrap_function | 21903 // build wrap_function |
| 21940 int key = (use_signature ? 1 : 0) + 2 * (global ? 1 : 0); | 21904 int key = (use_signature ? 1 : 0) + 2 * (global ? 1 : 0); |
| 21941 i::ScopedVector<char> wrap_function(100); | 21905 i::ScopedVector<char> wrap_function(200); |
| 21942 if (global) { | 21906 if (global) { |
| 21943 i::OS::SNPrintF( | 21907 i::OS::SNPrintF( |
| 21944 wrap_function, | 21908 wrap_function, |
| 21945 "function wrap_%d() { var f = global_f; return f(); }\n", | 21909 "function wrap_f_%d() { var f = g_f; return f(); }\n" |
| 21946 key); | 21910 "function wrap_get_%d() { return this.g_acc; }\n" |
| 21911 "function wrap_set_%d() { this.g_acc = 1; }\n", |
| 21912 key, key, key); |
| 21947 } else { | 21913 } else { |
| 21948 i::OS::SNPrintF( | 21914 i::OS::SNPrintF( |
| 21949 wrap_function, | 21915 wrap_function, |
| 21950 "function wrap_%d() { return receiver_subclass.f(); }\n", | 21916 "function wrap_f_%d() { return receiver_subclass.f(); }\n" |
| 21951 key); | 21917 "function wrap_get_%d() { return receiver_subclass.acc; }\n" |
| 21918 "function wrap_set_%d() { receiver_subclass.acc = 1; }\n", |
| 21919 key, key, key); |
| 21952 } | 21920 } |
| 21953 // build source string | 21921 // build source string |
| 21954 i::ScopedVector<char> source(500); | 21922 i::ScopedVector<char> source(500); |
| 21955 i::OS::SNPrintF( | 21923 i::OS::SNPrintF( |
| 21956 source, | 21924 source, |
| 21957 "%s\n" // wrap_function | 21925 "%s\n" // wrap functions |
| 21958 "function wrap2() { wrap_%d(); }\n" | 21926 "function wrap_f() { wrap_f_%d(); }\n" |
| 21959 "wrap2();\n" | 21927 "function wrap_get() { wrap_get_%d(); }\n" |
| 21960 "wrap2();\n" | 21928 "function wrap_set() { wrap_set_%d(); }\n" |
| 21961 "%%OptimizeFunctionOnNextCall(wrap_%d);\n" | 21929 "\n" |
| 21962 "wrap2();\n", | 21930 "wrap_f();\n" |
| 21963 wrap_function.start(), key, key); | 21931 "wrap_f();\n" |
| 21932 "%%OptimizeFunctionOnNextCall(wrap_f_%d);\n" |
| 21933 "wrap_f();\n" |
| 21934 "\n" |
| 21935 "wrap_get();\n" |
| 21936 "wrap_get();\n" |
| 21937 "%%OptimizeFunctionOnNextCall(wrap_get_%d);\n" |
| 21938 "wrap_get();\n" |
| 21939 "\n" |
| 21940 "wrap_set();\n" |
| 21941 "wrap_set();\n" |
| 21942 "%%OptimizeFunctionOnNextCall(wrap_set_%d);\n" |
| 21943 "wrap_set();\n", |
| 21944 wrap_function.start(), key, key, key, key, key, key); |
| 21964 v8::TryCatch try_catch; | 21945 v8::TryCatch try_catch; |
| 21965 CompileRun(source.start()); | 21946 CompileRun(source.start()); |
| 21966 ASSERT(!try_catch.HasCaught()); | 21947 ASSERT(!try_catch.HasCaught()); |
| 21967 CHECK_EQ(3, count); | 21948 CHECK_EQ(9, count); |
| 21968 } | 21949 } |
| 21969 }; | 21950 }; |
| 21970 | 21951 |
| 21971 | 21952 |
| 21972 Local<Object> ApiCallOptimizationChecker::data; | 21953 Local<Object> ApiCallOptimizationChecker::data; |
| 21973 Local<Object> ApiCallOptimizationChecker::receiver; | 21954 Local<Object> ApiCallOptimizationChecker::receiver; |
| 21974 Local<Object> ApiCallOptimizationChecker::holder; | 21955 Local<Object> ApiCallOptimizationChecker::holder; |
| 21975 Local<Object> ApiCallOptimizationChecker::callee; | 21956 Local<Object> ApiCallOptimizationChecker::callee; |
| 21976 int ApiCallOptimizationChecker::count = 0; | 21957 int ApiCallOptimizationChecker::count = 0; |
| 21977 | 21958 |
| 21978 | 21959 |
| 21979 TEST(TestFunctionCallOptimization) { | 21960 TEST(TestFunctionCallOptimization) { |
| 21980 i::FLAG_allow_natives_syntax = true; | 21961 i::FLAG_allow_natives_syntax = true; |
| 21981 ApiCallOptimizationChecker checker; | 21962 ApiCallOptimizationChecker checker; |
| 21982 checker.Run(true, true); | 21963 checker.Run(true, true); |
| 21983 checker.Run(false, true); | 21964 checker.Run(false, true); |
| 21984 checker.Run(true, false); | 21965 checker.Run(true, false); |
| 21985 checker.Run(false, false); | 21966 checker.Run(false, false); |
| 21986 } | 21967 } |
| OLD | NEW |