OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 | 2 |
3 #include <stdlib.h> | 3 #include <stdlib.h> |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "compilation-cache.h" | |
8 #include "execution.h" | 7 #include "execution.h" |
9 #include "factory.h" | 8 #include "factory.h" |
10 #include "macro-assembler.h" | 9 #include "macro-assembler.h" |
11 #include "global-handles.h" | 10 #include "global-handles.h" |
12 #include "cctest.h" | 11 #include "cctest.h" |
13 | 12 |
14 using namespace v8::internal; | 13 using namespace v8::internal; |
15 | 14 |
16 static v8::Persistent<v8::Context> env; | 15 static v8::Persistent<v8::Context> env; |
17 | 16 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 // nan oddball checks | 150 // nan oddball checks |
152 CHECK(HEAP->nan_value()->IsNumber()); | 151 CHECK(HEAP->nan_value()->IsNumber()); |
153 CHECK(isnan(HEAP->nan_value()->Number())); | 152 CHECK(isnan(HEAP->nan_value()->Number())); |
154 | 153 |
155 Handle<String> s = FACTORY->NewStringFromAscii(CStrVector("fisk hest ")); | 154 Handle<String> s = FACTORY->NewStringFromAscii(CStrVector("fisk hest ")); |
156 CHECK(s->IsString()); | 155 CHECK(s->IsString()); |
157 CHECK_EQ(10, s->length()); | 156 CHECK_EQ(10, s->length()); |
158 | 157 |
159 String* object_symbol = String::cast(HEAP->Object_symbol()); | 158 String* object_symbol = String::cast(HEAP->Object_symbol()); |
160 CHECK( | 159 CHECK( |
161 Isolate::Current()->context()->global_object()->HasLocalProperty( | 160 Isolate::Current()->context()->global()->HasLocalProperty(object_symbol)); |
162 object_symbol)); | |
163 | 161 |
164 // Check ToString for oddballs | 162 // Check ToString for oddballs |
165 CheckOddball(HEAP->true_value(), "true"); | 163 CheckOddball(HEAP->true_value(), "true"); |
166 CheckOddball(HEAP->false_value(), "false"); | 164 CheckOddball(HEAP->false_value(), "false"); |
167 CheckOddball(HEAP->null_value(), "null"); | 165 CheckOddball(HEAP->null_value(), "null"); |
168 CheckOddball(HEAP->undefined_value(), "undefined"); | 166 CheckOddball(HEAP->undefined_value(), "undefined"); |
169 | 167 |
170 // Check ToString for Smis | 168 // Check ToString for Smis |
171 CheckSmi(0, "0"); | 169 CheckSmi(0, "0"); |
172 CheckSmi(42, "42"); | 170 CheckSmi(42, "42"); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 Handle<String> obj_name = FACTORY->LookupAsciiSymbol("theObject"); | 206 Handle<String> obj_name = FACTORY->LookupAsciiSymbol("theObject"); |
209 | 207 |
210 { | 208 { |
211 v8::HandleScope inner_scope; | 209 v8::HandleScope inner_scope; |
212 // Allocate a function and keep it in global object's property. | 210 // Allocate a function and keep it in global object's property. |
213 Handle<JSFunction> function = | 211 Handle<JSFunction> function = |
214 FACTORY->NewFunction(name, FACTORY->undefined_value()); | 212 FACTORY->NewFunction(name, FACTORY->undefined_value()); |
215 Handle<Map> initial_map = | 213 Handle<Map> initial_map = |
216 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); | 214 FACTORY->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); |
217 function->set_initial_map(*initial_map); | 215 function->set_initial_map(*initial_map); |
218 Isolate::Current()->context()->global_object()->SetProperty( | 216 Isolate::Current()->context()->global()->SetProperty( |
219 *name, *function, NONE, kNonStrictMode)->ToObjectChecked(); | 217 *name, *function, NONE, kNonStrictMode)->ToObjectChecked(); |
220 // Allocate an object. Unrooted after leaving the scope. | 218 // Allocate an object. Unrooted after leaving the scope. |
221 Handle<JSObject> obj = FACTORY->NewJSObject(function); | 219 Handle<JSObject> obj = FACTORY->NewJSObject(function); |
222 obj->SetProperty( | 220 obj->SetProperty( |
223 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); | 221 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); |
224 obj->SetProperty( | 222 obj->SetProperty( |
225 *prop_namex, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked(); | 223 *prop_namex, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked(); |
226 | 224 |
227 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); | 225 CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); |
228 CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex)); | 226 CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex)); |
229 } | 227 } |
230 | 228 |
231 HEAP->CollectGarbage(NEW_SPACE); | 229 HEAP->CollectGarbage(NEW_SPACE); |
232 | 230 |
233 // Function should be alive. | 231 // Function should be alive. |
234 CHECK(Isolate::Current()->context()->global_object()-> | 232 CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*name)); |
235 HasLocalProperty(*name)); | |
236 // Check function is retained. | 233 // Check function is retained. |
237 Object* func_value = Isolate::Current()->context()->global_object()-> | 234 Object* func_value = Isolate::Current()->context()->global()-> |
238 GetProperty(*name)->ToObjectChecked(); | 235 GetProperty(*name)->ToObjectChecked(); |
239 CHECK(func_value->IsJSFunction()); | 236 CHECK(func_value->IsJSFunction()); |
240 Handle<JSFunction> function(JSFunction::cast(func_value)); | 237 Handle<JSFunction> function(JSFunction::cast(func_value)); |
241 | 238 |
242 { | 239 { |
243 HandleScope inner_scope; | 240 HandleScope inner_scope; |
244 // Allocate another object, make it reachable from global. | 241 // Allocate another object, make it reachable from global. |
245 Handle<JSObject> obj = FACTORY->NewJSObject(function); | 242 Handle<JSObject> obj = FACTORY->NewJSObject(function); |
246 Isolate::Current()->context()->global_object()->SetProperty( | 243 Isolate::Current()->context()->global()->SetProperty( |
247 *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked(); | 244 *obj_name, *obj, NONE, kNonStrictMode)->ToObjectChecked(); |
248 obj->SetProperty( | 245 obj->SetProperty( |
249 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); | 246 *prop_name, Smi::FromInt(23), NONE, kNonStrictMode)->ToObjectChecked(); |
250 } | 247 } |
251 | 248 |
252 // After gc, it should survive. | 249 // After gc, it should survive. |
253 HEAP->CollectGarbage(NEW_SPACE); | 250 HEAP->CollectGarbage(NEW_SPACE); |
254 | 251 |
255 CHECK(Isolate::Current()->context()->global_object()-> | 252 CHECK(Isolate::Current()->context()->global()->HasLocalProperty(*obj_name)); |
256 HasLocalProperty(*obj_name)); | 253 CHECK(Isolate::Current()->context()->global()-> |
257 CHECK(Isolate::Current()->context()->global_object()-> | |
258 GetProperty(*obj_name)->ToObjectChecked()->IsJSObject()); | 254 GetProperty(*obj_name)->ToObjectChecked()->IsJSObject()); |
259 Object* obj = Isolate::Current()->context()->global_object()-> | 255 Object* obj = Isolate::Current()->context()->global()-> |
260 GetProperty(*obj_name)->ToObjectChecked(); | 256 GetProperty(*obj_name)->ToObjectChecked(); |
261 JSObject* js_obj = JSObject::cast(obj); | 257 JSObject* js_obj = JSObject::cast(obj); |
262 CHECK_EQ(Smi::FromInt(23), js_obj->GetProperty(*prop_name)); | 258 CHECK_EQ(Smi::FromInt(23), js_obj->GetProperty(*prop_name)); |
263 } | 259 } |
264 | 260 |
265 | 261 |
266 static void VerifyStringAllocation(const char* string) { | 262 static void VerifyStringAllocation(const char* string) { |
267 v8::HandleScope scope; | 263 v8::HandleScope scope; |
268 Handle<String> s = FACTORY->NewStringFromUtf8(CStrVector(string)); | 264 Handle<String> s = FACTORY->NewStringFromUtf8(CStrVector(string)); |
269 CHECK_EQ(StrLength(string), s->length()); | 265 CHECK_EQ(StrLength(string), s->length()); |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 *prop_name, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked(); | 556 *prop_name, Smi::FromInt(24), NONE, kNonStrictMode)->ToObjectChecked(); |
561 CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name)); | 557 CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name)); |
562 } | 558 } |
563 | 559 |
564 | 560 |
565 TEST(ObjectProperties) { | 561 TEST(ObjectProperties) { |
566 InitializeVM(); | 562 InitializeVM(); |
567 | 563 |
568 v8::HandleScope sc; | 564 v8::HandleScope sc; |
569 String* object_symbol = String::cast(HEAP->Object_symbol()); | 565 String* object_symbol = String::cast(HEAP->Object_symbol()); |
570 Object* raw_object = Isolate::Current()->context()->global_object()-> | 566 Object* raw_object = Isolate::Current()->context()->global()-> |
571 GetProperty(object_symbol)->ToObjectChecked(); | 567 GetProperty(object_symbol)->ToObjectChecked(); |
572 JSFunction* object_function = JSFunction::cast(raw_object); | 568 JSFunction* object_function = JSFunction::cast(raw_object); |
573 Handle<JSFunction> constructor(object_function); | 569 Handle<JSFunction> constructor(object_function); |
574 Handle<JSObject> obj = FACTORY->NewJSObject(constructor); | 570 Handle<JSObject> obj = FACTORY->NewJSObject(constructor); |
575 Handle<String> first = FACTORY->LookupAsciiSymbol("first"); | 571 Handle<String> first = FACTORY->LookupAsciiSymbol("first"); |
576 Handle<String> second = FACTORY->LookupAsciiSymbol("second"); | 572 Handle<String> second = FACTORY->LookupAsciiSymbol("second"); |
577 | 573 |
578 // check for empty | 574 // check for empty |
579 CHECK(!obj->HasLocalProperty(*first)); | 575 CHECK(!obj->HasLocalProperty(*first)); |
580 | 576 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 // Check the map has changed | 653 // Check the map has changed |
658 CHECK(*initial_map != obj->map()); | 654 CHECK(*initial_map != obj->map()); |
659 } | 655 } |
660 | 656 |
661 | 657 |
662 TEST(JSArray) { | 658 TEST(JSArray) { |
663 InitializeVM(); | 659 InitializeVM(); |
664 | 660 |
665 v8::HandleScope sc; | 661 v8::HandleScope sc; |
666 Handle<String> name = FACTORY->LookupAsciiSymbol("Array"); | 662 Handle<String> name = FACTORY->LookupAsciiSymbol("Array"); |
667 Object* raw_object = Isolate::Current()->context()->global_object()-> | 663 Object* raw_object = Isolate::Current()->context()->global()-> |
668 GetProperty(*name)->ToObjectChecked(); | 664 GetProperty(*name)->ToObjectChecked(); |
669 Handle<JSFunction> function = Handle<JSFunction>( | 665 Handle<JSFunction> function = Handle<JSFunction>( |
670 JSFunction::cast(raw_object)); | 666 JSFunction::cast(raw_object)); |
671 | 667 |
672 // Allocate the object. | 668 // Allocate the object. |
673 Handle<JSObject> object = FACTORY->NewJSObject(function); | 669 Handle<JSObject> object = FACTORY->NewJSObject(function); |
674 Handle<JSArray> array = Handle<JSArray>::cast(object); | 670 Handle<JSArray> array = Handle<JSArray>::cast(object); |
675 // We just initialized the VM, no heap allocation failure yet. | 671 // We just initialized the VM, no heap allocation failure yet. |
676 array->Initialize(0)->ToObjectChecked(); | 672 array->Initialize(0)->ToObjectChecked(); |
677 | 673 |
(...skipping 26 matching lines...) Expand all Loading... |
704 CHECK_EQ(array->GetElement(int_length), *name); | 700 CHECK_EQ(array->GetElement(int_length), *name); |
705 CHECK_EQ(array->GetElement(0), *name); | 701 CHECK_EQ(array->GetElement(0), *name); |
706 } | 702 } |
707 | 703 |
708 | 704 |
709 TEST(JSObjectCopy) { | 705 TEST(JSObjectCopy) { |
710 InitializeVM(); | 706 InitializeVM(); |
711 | 707 |
712 v8::HandleScope sc; | 708 v8::HandleScope sc; |
713 String* object_symbol = String::cast(HEAP->Object_symbol()); | 709 String* object_symbol = String::cast(HEAP->Object_symbol()); |
714 Object* raw_object = Isolate::Current()->context()->global_object()-> | 710 Object* raw_object = Isolate::Current()->context()->global()-> |
715 GetProperty(object_symbol)->ToObjectChecked(); | 711 GetProperty(object_symbol)->ToObjectChecked(); |
716 JSFunction* object_function = JSFunction::cast(raw_object); | 712 JSFunction* object_function = JSFunction::cast(raw_object); |
717 Handle<JSFunction> constructor(object_function); | 713 Handle<JSFunction> constructor(object_function); |
718 Handle<JSObject> obj = FACTORY->NewJSObject(constructor); | 714 Handle<JSObject> obj = FACTORY->NewJSObject(constructor); |
719 Handle<String> first = FACTORY->LookupAsciiSymbol("first"); | 715 Handle<String> first = FACTORY->LookupAsciiSymbol("first"); |
720 Handle<String> second = FACTORY->LookupAsciiSymbol("second"); | 716 Handle<String> second = FACTORY->LookupAsciiSymbol("second"); |
721 | 717 |
722 obj->SetProperty( | 718 obj->SetProperty( |
723 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); | 719 *first, Smi::FromInt(1), NONE, kNonStrictMode)->ToObjectChecked(); |
724 obj->SetProperty( | 720 obj->SetProperty( |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 869 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
874 | 870 |
875 v8::HandleScope scope; | 871 v8::HandleScope scope; |
876 | 872 |
877 // The plan: create JSObject which references objects in new space. | 873 // The plan: create JSObject which references objects in new space. |
878 // Then clone this object (forcing it to go into old space) and check | 874 // Then clone this object (forcing it to go into old space) and check |
879 // that region dirty marks are updated correctly. | 875 // that region dirty marks are updated correctly. |
880 | 876 |
881 // Step 1: prepare a map for the object. We add 1 inobject property to it. | 877 // Step 1: prepare a map for the object. We add 1 inobject property to it. |
882 Handle<JSFunction> object_ctor( | 878 Handle<JSFunction> object_ctor( |
883 Isolate::Current()->native_context()->object_function()); | 879 Isolate::Current()->global_context()->object_function()); |
884 CHECK(object_ctor->has_initial_map()); | 880 CHECK(object_ctor->has_initial_map()); |
885 Handle<Map> object_map(object_ctor->initial_map()); | 881 Handle<Map> object_map(object_ctor->initial_map()); |
886 // Create a map with single inobject property. | 882 // Create a map with single inobject property. |
887 Handle<Map> my_map = FACTORY->CopyMap(object_map, 1); | 883 Handle<Map> my_map = FACTORY->CopyMap(object_map, 1); |
888 int n_properties = my_map->inobject_properties(); | 884 int n_properties = my_map->inobject_properties(); |
889 CHECK_GT(n_properties, 0); | 885 CHECK_GT(n_properties, 0); |
890 | 886 |
891 int object_size = my_map->instance_size(); | 887 int object_size = my_map->instance_size(); |
892 | 888 |
893 // Step 2: allocate a lot of objects so to almost fill new space: we need | 889 // Step 2: allocate a lot of objects so to almost fill new space: we need |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
953 "};" | 949 "};" |
954 "foo()"; | 950 "foo()"; |
955 Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo"); | 951 Handle<String> foo_name = FACTORY->LookupAsciiSymbol("foo"); |
956 | 952 |
957 // This compile will add the code to the compilation cache. | 953 // This compile will add the code to the compilation cache. |
958 { v8::HandleScope scope; | 954 { v8::HandleScope scope; |
959 CompileRun(source); | 955 CompileRun(source); |
960 } | 956 } |
961 | 957 |
962 // Check function is compiled. | 958 // Check function is compiled. |
963 Object* func_value = Isolate::Current()->context()->global_object()-> | 959 Object* func_value = Isolate::Current()->context()->global()-> |
964 GetProperty(*foo_name)->ToObjectChecked(); | 960 GetProperty(*foo_name)->ToObjectChecked(); |
965 CHECK(func_value->IsJSFunction()); | 961 CHECK(func_value->IsJSFunction()); |
966 Handle<JSFunction> function(JSFunction::cast(func_value)); | 962 Handle<JSFunction> function(JSFunction::cast(func_value)); |
967 CHECK(function->shared()->is_compiled()); | 963 CHECK(function->shared()->is_compiled()); |
968 | 964 |
969 // TODO(1609) Currently incremental marker does not support code flushing. | 965 // TODO(1609) Currently incremental marker does not support code flushing. |
970 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 966 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
971 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 967 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
972 | 968 |
973 CHECK(function->shared()->is_compiled()); | 969 CHECK(function->shared()->is_compiled()); |
974 | 970 |
975 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 971 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
976 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 972 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
977 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 973 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
978 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 974 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
979 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 975 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
980 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); | 976 HEAP->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); |
981 | 977 |
982 // foo should no longer be in the compilation cache | 978 // foo should no longer be in the compilation cache |
983 CHECK(!function->shared()->is_compiled() || function->IsOptimized()); | 979 CHECK(!function->shared()->is_compiled() || function->IsOptimized()); |
984 CHECK(!function->is_compiled() || function->IsOptimized()); | 980 CHECK(!function->is_compiled() || function->IsOptimized()); |
985 // Call foo to get it recompiled. | 981 // Call foo to get it recompiled. |
986 CompileRun("foo()"); | 982 CompileRun("foo()"); |
987 CHECK(function->shared()->is_compiled()); | 983 CHECK(function->shared()->is_compiled()); |
988 CHECK(function->is_compiled()); | 984 CHECK(function->is_compiled()); |
989 } | 985 } |
990 | 986 |
991 | 987 |
992 // Count the number of native contexts in the weak list of native contexts. | 988 // Count the number of global contexts in the weak list of global contexts. |
993 int CountNativeContexts() { | 989 int CountGlobalContexts() { |
994 int count = 0; | 990 int count = 0; |
995 Object* object = HEAP->native_contexts_list(); | 991 Object* object = HEAP->global_contexts_list(); |
996 while (!object->IsUndefined()) { | 992 while (!object->IsUndefined()) { |
997 count++; | 993 count++; |
998 object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK); | 994 object = Context::cast(object)->get(Context::NEXT_CONTEXT_LINK); |
999 } | 995 } |
1000 return count; | 996 return count; |
1001 } | 997 } |
1002 | 998 |
1003 | 999 |
1004 // Count the number of user functions in the weak list of optimized | 1000 // Count the number of user functions in the weak list of optimized |
1005 // functions attached to a native context. | 1001 // functions attached to a global context. |
1006 static int CountOptimizedUserFunctions(v8::Handle<v8::Context> context) { | 1002 static int CountOptimizedUserFunctions(v8::Handle<v8::Context> context) { |
1007 int count = 0; | 1003 int count = 0; |
1008 Handle<Context> icontext = v8::Utils::OpenHandle(*context); | 1004 Handle<Context> icontext = v8::Utils::OpenHandle(*context); |
1009 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST); | 1005 Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST); |
1010 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) { | 1006 while (object->IsJSFunction() && !JSFunction::cast(object)->IsBuiltin()) { |
1011 count++; | 1007 count++; |
1012 object = JSFunction::cast(object)->next_function_link(); | 1008 object = JSFunction::cast(object)->next_function_link(); |
1013 } | 1009 } |
1014 return count; | 1010 return count; |
1015 } | 1011 } |
1016 | 1012 |
1017 | 1013 |
1018 TEST(TestInternalWeakLists) { | 1014 TEST(TestInternalWeakLists) { |
1019 v8::V8::Initialize(); | 1015 v8::V8::Initialize(); |
1020 | 1016 |
1021 static const int kNumTestContexts = 10; | 1017 static const int kNumTestContexts = 10; |
1022 | 1018 |
1023 v8::HandleScope scope; | 1019 v8::HandleScope scope; |
1024 v8::Persistent<v8::Context> ctx[kNumTestContexts]; | 1020 v8::Persistent<v8::Context> ctx[kNumTestContexts]; |
1025 | 1021 |
1026 CHECK_EQ(0, CountNativeContexts()); | 1022 CHECK_EQ(0, CountGlobalContexts()); |
1027 | 1023 |
1028 // Create a number of global contests which gets linked together. | 1024 // Create a number of global contests which gets linked together. |
1029 for (int i = 0; i < kNumTestContexts; i++) { | 1025 for (int i = 0; i < kNumTestContexts; i++) { |
1030 ctx[i] = v8::Context::New(); | 1026 ctx[i] = v8::Context::New(); |
1031 | 1027 |
1032 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); | 1028 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); |
1033 | 1029 |
1034 CHECK_EQ(i + 1, CountNativeContexts()); | 1030 CHECK_EQ(i + 1, CountGlobalContexts()); |
1035 | 1031 |
1036 ctx[i]->Enter(); | 1032 ctx[i]->Enter(); |
1037 | 1033 |
1038 // Create a handle scope so no function objects get stuch in the outer | 1034 // Create a handle scope so no function objects get stuch in the outer |
1039 // handle scope | 1035 // handle scope |
1040 v8::HandleScope scope; | 1036 v8::HandleScope scope; |
1041 const char* source = "function f1() { };" | 1037 const char* source = "function f1() { };" |
1042 "function f2() { };" | 1038 "function f2() { };" |
1043 "function f3() { };" | 1039 "function f3() { };" |
1044 "function f4() { };" | 1040 "function f4() { };" |
(...skipping 14 matching lines...) Expand all Loading... |
1059 // Remove function f1, and | 1055 // Remove function f1, and |
1060 CompileRun("f1=null"); | 1056 CompileRun("f1=null"); |
1061 | 1057 |
1062 // Scavenge treats these references as strong. | 1058 // Scavenge treats these references as strong. |
1063 for (int j = 0; j < 10; j++) { | 1059 for (int j = 0; j < 10; j++) { |
1064 HEAP->PerformScavenge(); | 1060 HEAP->PerformScavenge(); |
1065 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); | 1061 CHECK_EQ(opt ? 5 : 0, CountOptimizedUserFunctions(ctx[i])); |
1066 } | 1062 } |
1067 | 1063 |
1068 // Mark compact handles the weak references. | 1064 // Mark compact handles the weak references. |
1069 ISOLATE->compilation_cache()->Clear(); | |
1070 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1065 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
1071 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1066 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); |
1072 | 1067 |
1073 // Get rid of f3 and f5 in the same way. | 1068 // Get rid of f3 and f5 in the same way. |
1074 CompileRun("f3=null"); | 1069 CompileRun("f3=null"); |
1075 for (int j = 0; j < 10; j++) { | 1070 for (int j = 0; j < 10; j++) { |
1076 HEAP->PerformScavenge(); | 1071 HEAP->PerformScavenge(); |
1077 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); | 1072 CHECK_EQ(opt ? 4 : 0, CountOptimizedUserFunctions(ctx[i])); |
1078 } | 1073 } |
1079 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1074 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
1080 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1075 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); |
1081 CompileRun("f5=null"); | 1076 CompileRun("f5=null"); |
1082 for (int j = 0; j < 10; j++) { | 1077 for (int j = 0; j < 10; j++) { |
1083 HEAP->PerformScavenge(); | 1078 HEAP->PerformScavenge(); |
1084 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); | 1079 CHECK_EQ(opt ? 3 : 0, CountOptimizedUserFunctions(ctx[i])); |
1085 } | 1080 } |
1086 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1081 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
1087 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); | 1082 CHECK_EQ(opt ? 2 : 0, CountOptimizedUserFunctions(ctx[i])); |
1088 | 1083 |
1089 ctx[i]->Exit(); | 1084 ctx[i]->Exit(); |
1090 } | 1085 } |
1091 | 1086 |
1092 // Force compilation cache cleanup. | 1087 // Force compilation cache cleanup. |
1093 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1088 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
1094 | 1089 |
1095 // Dispose the native contexts one by one. | 1090 // Dispose the global contexts one by one. |
1096 for (int i = 0; i < kNumTestContexts; i++) { | 1091 for (int i = 0; i < kNumTestContexts; i++) { |
1097 ctx[i].Dispose(); | 1092 ctx[i].Dispose(); |
1098 ctx[i].Clear(); | 1093 ctx[i].Clear(); |
1099 | 1094 |
1100 // Scavenge treats these references as strong. | 1095 // Scavenge treats these references as strong. |
1101 for (int j = 0; j < 10; j++) { | 1096 for (int j = 0; j < 10; j++) { |
1102 HEAP->PerformScavenge(); | 1097 HEAP->PerformScavenge(); |
1103 CHECK_EQ(kNumTestContexts - i, CountNativeContexts()); | 1098 CHECK_EQ(kNumTestContexts - i, CountGlobalContexts()); |
1104 } | 1099 } |
1105 | 1100 |
1106 // Mark compact handles the weak references. | 1101 // Mark compact handles the weak references. |
1107 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1102 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
1108 CHECK_EQ(kNumTestContexts - i - 1, CountNativeContexts()); | 1103 CHECK_EQ(kNumTestContexts - i - 1, CountGlobalContexts()); |
1109 } | 1104 } |
1110 | 1105 |
1111 CHECK_EQ(0, CountNativeContexts()); | 1106 CHECK_EQ(0, CountGlobalContexts()); |
1112 } | 1107 } |
1113 | 1108 |
1114 | 1109 |
1115 // Count the number of native contexts in the weak list of native contexts | 1110 // Count the number of global contexts in the weak list of global contexts |
1116 // causing a GC after the specified number of elements. | 1111 // causing a GC after the specified number of elements. |
1117 static int CountNativeContextsWithGC(int n) { | 1112 static int CountGlobalContextsWithGC(int n) { |
1118 int count = 0; | 1113 int count = 0; |
1119 Handle<Object> object(HEAP->native_contexts_list()); | 1114 Handle<Object> object(HEAP->global_contexts_list()); |
1120 while (!object->IsUndefined()) { | 1115 while (!object->IsUndefined()) { |
1121 count++; | 1116 count++; |
1122 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1117 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
1123 object = | 1118 object = |
1124 Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK)); | 1119 Handle<Object>(Context::cast(*object)->get(Context::NEXT_CONTEXT_LINK)); |
1125 } | 1120 } |
1126 return count; | 1121 return count; |
1127 } | 1122 } |
1128 | 1123 |
1129 | 1124 |
1130 // Count the number of user functions in the weak list of optimized | 1125 // Count the number of user functions in the weak list of optimized |
1131 // functions attached to a native context causing a GC after the | 1126 // functions attached to a global context causing a GC after the |
1132 // specified number of elements. | 1127 // specified number of elements. |
1133 static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context, | 1128 static int CountOptimizedUserFunctionsWithGC(v8::Handle<v8::Context> context, |
1134 int n) { | 1129 int n) { |
1135 int count = 0; | 1130 int count = 0; |
1136 Handle<Context> icontext = v8::Utils::OpenHandle(*context); | 1131 Handle<Context> icontext = v8::Utils::OpenHandle(*context); |
1137 Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST)); | 1132 Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST)); |
1138 while (object->IsJSFunction() && | 1133 while (object->IsJSFunction() && |
1139 !Handle<JSFunction>::cast(object)->IsBuiltin()) { | 1134 !Handle<JSFunction>::cast(object)->IsBuiltin()) { |
1140 count++; | 1135 count++; |
1141 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 1136 if (count == n) HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
1142 object = Handle<Object>( | 1137 object = Handle<Object>( |
1143 Object::cast(JSFunction::cast(*object)->next_function_link())); | 1138 Object::cast(JSFunction::cast(*object)->next_function_link())); |
1144 } | 1139 } |
1145 return count; | 1140 return count; |
1146 } | 1141 } |
1147 | 1142 |
1148 | 1143 |
1149 TEST(TestInternalWeakListsTraverseWithGC) { | 1144 TEST(TestInternalWeakListsTraverseWithGC) { |
1150 v8::V8::Initialize(); | 1145 v8::V8::Initialize(); |
1151 | 1146 |
1152 static const int kNumTestContexts = 10; | 1147 static const int kNumTestContexts = 10; |
1153 | 1148 |
1154 v8::HandleScope scope; | 1149 v8::HandleScope scope; |
1155 v8::Persistent<v8::Context> ctx[kNumTestContexts]; | 1150 v8::Persistent<v8::Context> ctx[kNumTestContexts]; |
1156 | 1151 |
1157 CHECK_EQ(0, CountNativeContexts()); | 1152 CHECK_EQ(0, CountGlobalContexts()); |
1158 | 1153 |
1159 // Create an number of contexts and check the length of the weak list both | 1154 // Create an number of contexts and check the length of the weak list both |
1160 // with and without GCs while iterating the list. | 1155 // with and without GCs while iterating the list. |
1161 for (int i = 0; i < kNumTestContexts; i++) { | 1156 for (int i = 0; i < kNumTestContexts; i++) { |
1162 ctx[i] = v8::Context::New(); | 1157 ctx[i] = v8::Context::New(); |
1163 CHECK_EQ(i + 1, CountNativeContexts()); | 1158 CHECK_EQ(i + 1, CountGlobalContexts()); |
1164 CHECK_EQ(i + 1, CountNativeContextsWithGC(i / 2 + 1)); | 1159 CHECK_EQ(i + 1, CountGlobalContextsWithGC(i / 2 + 1)); |
1165 } | 1160 } |
1166 | 1161 |
1167 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); | 1162 bool opt = (FLAG_always_opt && i::V8::UseCrankshaft()); |
1168 | 1163 |
1169 // Compile a number of functions the length of the weak list of optimized | 1164 // Compile a number of functions the length of the weak list of optimized |
1170 // functions both with and without GCs while iterating the list. | 1165 // functions both with and without GCs while iterating the list. |
1171 ctx[0]->Enter(); | 1166 ctx[0]->Enter(); |
1172 const char* source = "function f1() { };" | 1167 const char* source = "function f1() { };" |
1173 "function f2() { };" | 1168 "function f2() { };" |
1174 "function f3() { };" | 1169 "function f3() { };" |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1364 HeapIterator iterator; | 1359 HeapIterator iterator; |
1365 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 1360 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
1366 if (obj->IsGlobalObject()) count++; | 1361 if (obj->IsGlobalObject()) count++; |
1367 } | 1362 } |
1368 return count; | 1363 return count; |
1369 } | 1364 } |
1370 | 1365 |
1371 | 1366 |
1372 // Test that we don't embed maps from foreign contexts into | 1367 // Test that we don't embed maps from foreign contexts into |
1373 // optimized code. | 1368 // optimized code. |
1374 TEST(LeakNativeContextViaMap) { | 1369 TEST(LeakGlobalContextViaMap) { |
1375 i::FLAG_allow_natives_syntax = true; | 1370 i::FLAG_allow_natives_syntax = true; |
1376 v8::HandleScope outer_scope; | 1371 v8::HandleScope outer_scope; |
1377 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1372 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
1378 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1373 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
1379 ctx1->Enter(); | 1374 ctx1->Enter(); |
1380 | 1375 |
1381 HEAP->CollectAllAvailableGarbage(); | 1376 HEAP->CollectAllAvailableGarbage(); |
1382 CHECK_EQ(4, NumberOfGlobalObjects()); | 1377 CHECK_EQ(4, NumberOfGlobalObjects()); |
1383 | 1378 |
1384 { | 1379 { |
1385 v8::HandleScope inner_scope; | 1380 v8::HandleScope inner_scope; |
1386 CompileRun("var v = {x: 42}"); | 1381 CompileRun("var v = {x: 42}"); |
1387 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); | 1382 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); |
1388 ctx2->Enter(); | 1383 ctx2->Enter(); |
1389 ctx2->Global()->Set(v8_str("o"), v); | 1384 ctx2->Global()->Set(v8_str("o"), v); |
1390 v8::Local<v8::Value> res = CompileRun( | 1385 v8::Local<v8::Value> res = CompileRun( |
1391 "function f() { return o.x; }" | 1386 "function f() { return o.x; }" |
1392 "for (var i = 0; i < 10; ++i) f();" | 1387 "for (var i = 0; i < 10; ++i) f();" |
1393 "%OptimizeFunctionOnNextCall(f);" | 1388 "%OptimizeFunctionOnNextCall(f);" |
1394 "f();"); | 1389 "f();"); |
1395 CHECK_EQ(42, res->Int32Value()); | 1390 CHECK_EQ(42, res->Int32Value()); |
1396 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1391 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
1397 ctx2->Exit(); | 1392 ctx2->Exit(); |
1398 ctx1->Exit(); | 1393 ctx1->Exit(); |
1399 ctx1.Dispose(); | 1394 ctx1.Dispose(); |
1400 v8::V8::ContextDisposedNotification(); | |
1401 } | 1395 } |
1402 HEAP->CollectAllAvailableGarbage(); | 1396 HEAP->CollectAllAvailableGarbage(); |
1403 CHECK_EQ(2, NumberOfGlobalObjects()); | 1397 CHECK_EQ(2, NumberOfGlobalObjects()); |
1404 ctx2.Dispose(); | 1398 ctx2.Dispose(); |
1405 HEAP->CollectAllAvailableGarbage(); | 1399 HEAP->CollectAllAvailableGarbage(); |
1406 CHECK_EQ(0, NumberOfGlobalObjects()); | 1400 CHECK_EQ(0, NumberOfGlobalObjects()); |
1407 } | 1401 } |
1408 | 1402 |
1409 | 1403 |
1410 // Test that we don't embed functions from foreign contexts into | 1404 // Test that we don't embed functions from foreign contexts into |
1411 // optimized code. | 1405 // optimized code. |
1412 TEST(LeakNativeContextViaFunction) { | 1406 TEST(LeakGlobalContextViaFunction) { |
1413 i::FLAG_allow_natives_syntax = true; | 1407 i::FLAG_allow_natives_syntax = true; |
1414 v8::HandleScope outer_scope; | 1408 v8::HandleScope outer_scope; |
1415 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1409 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
1416 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1410 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
1417 ctx1->Enter(); | 1411 ctx1->Enter(); |
1418 | 1412 |
1419 HEAP->CollectAllAvailableGarbage(); | 1413 HEAP->CollectAllAvailableGarbage(); |
1420 CHECK_EQ(4, NumberOfGlobalObjects()); | 1414 CHECK_EQ(4, NumberOfGlobalObjects()); |
1421 | 1415 |
1422 { | 1416 { |
1423 v8::HandleScope inner_scope; | 1417 v8::HandleScope inner_scope; |
1424 CompileRun("var v = function() { return 42; }"); | 1418 CompileRun("var v = function() { return 42; }"); |
1425 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); | 1419 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); |
1426 ctx2->Enter(); | 1420 ctx2->Enter(); |
1427 ctx2->Global()->Set(v8_str("o"), v); | 1421 ctx2->Global()->Set(v8_str("o"), v); |
1428 v8::Local<v8::Value> res = CompileRun( | 1422 v8::Local<v8::Value> res = CompileRun( |
1429 "function f(x) { return x(); }" | 1423 "function f(x) { return x(); }" |
1430 "for (var i = 0; i < 10; ++i) f(o);" | 1424 "for (var i = 0; i < 10; ++i) f(o);" |
1431 "%OptimizeFunctionOnNextCall(f);" | 1425 "%OptimizeFunctionOnNextCall(f);" |
1432 "f(o);"); | 1426 "f(o);"); |
1433 CHECK_EQ(42, res->Int32Value()); | 1427 CHECK_EQ(42, res->Int32Value()); |
1434 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1428 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
1435 ctx2->Exit(); | 1429 ctx2->Exit(); |
1436 ctx1->Exit(); | 1430 ctx1->Exit(); |
1437 ctx1.Dispose(); | 1431 ctx1.Dispose(); |
1438 v8::V8::ContextDisposedNotification(); | |
1439 } | 1432 } |
1440 HEAP->CollectAllAvailableGarbage(); | 1433 HEAP->CollectAllAvailableGarbage(); |
1441 CHECK_EQ(2, NumberOfGlobalObjects()); | 1434 CHECK_EQ(2, NumberOfGlobalObjects()); |
1442 ctx2.Dispose(); | 1435 ctx2.Dispose(); |
1443 HEAP->CollectAllAvailableGarbage(); | 1436 HEAP->CollectAllAvailableGarbage(); |
1444 CHECK_EQ(0, NumberOfGlobalObjects()); | 1437 CHECK_EQ(0, NumberOfGlobalObjects()); |
1445 } | 1438 } |
1446 | 1439 |
1447 | 1440 |
1448 TEST(LeakNativeContextViaMapKeyed) { | 1441 TEST(LeakGlobalContextViaMapKeyed) { |
1449 i::FLAG_allow_natives_syntax = true; | 1442 i::FLAG_allow_natives_syntax = true; |
1450 v8::HandleScope outer_scope; | 1443 v8::HandleScope outer_scope; |
1451 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1444 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
1452 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1445 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
1453 ctx1->Enter(); | 1446 ctx1->Enter(); |
1454 | 1447 |
1455 HEAP->CollectAllAvailableGarbage(); | 1448 HEAP->CollectAllAvailableGarbage(); |
1456 CHECK_EQ(4, NumberOfGlobalObjects()); | 1449 CHECK_EQ(4, NumberOfGlobalObjects()); |
1457 | 1450 |
1458 { | 1451 { |
1459 v8::HandleScope inner_scope; | 1452 v8::HandleScope inner_scope; |
1460 CompileRun("var v = [42, 43]"); | 1453 CompileRun("var v = [42, 43]"); |
1461 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); | 1454 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); |
1462 ctx2->Enter(); | 1455 ctx2->Enter(); |
1463 ctx2->Global()->Set(v8_str("o"), v); | 1456 ctx2->Global()->Set(v8_str("o"), v); |
1464 v8::Local<v8::Value> res = CompileRun( | 1457 v8::Local<v8::Value> res = CompileRun( |
1465 "function f() { return o[0]; }" | 1458 "function f() { return o[0]; }" |
1466 "for (var i = 0; i < 10; ++i) f();" | 1459 "for (var i = 0; i < 10; ++i) f();" |
1467 "%OptimizeFunctionOnNextCall(f);" | 1460 "%OptimizeFunctionOnNextCall(f);" |
1468 "f();"); | 1461 "f();"); |
1469 CHECK_EQ(42, res->Int32Value()); | 1462 CHECK_EQ(42, res->Int32Value()); |
1470 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1463 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
1471 ctx2->Exit(); | 1464 ctx2->Exit(); |
1472 ctx1->Exit(); | 1465 ctx1->Exit(); |
1473 ctx1.Dispose(); | 1466 ctx1.Dispose(); |
1474 v8::V8::ContextDisposedNotification(); | |
1475 } | 1467 } |
1476 HEAP->CollectAllAvailableGarbage(); | 1468 HEAP->CollectAllAvailableGarbage(); |
1477 CHECK_EQ(2, NumberOfGlobalObjects()); | 1469 CHECK_EQ(2, NumberOfGlobalObjects()); |
1478 ctx2.Dispose(); | 1470 ctx2.Dispose(); |
1479 HEAP->CollectAllAvailableGarbage(); | 1471 HEAP->CollectAllAvailableGarbage(); |
1480 CHECK_EQ(0, NumberOfGlobalObjects()); | 1472 CHECK_EQ(0, NumberOfGlobalObjects()); |
1481 } | 1473 } |
1482 | 1474 |
1483 | 1475 |
1484 TEST(LeakNativeContextViaMapProto) { | 1476 TEST(LeakGlobalContextViaMapProto) { |
1485 i::FLAG_allow_natives_syntax = true; | 1477 i::FLAG_allow_natives_syntax = true; |
1486 v8::HandleScope outer_scope; | 1478 v8::HandleScope outer_scope; |
1487 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); | 1479 v8::Persistent<v8::Context> ctx1 = v8::Context::New(); |
1488 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); | 1480 v8::Persistent<v8::Context> ctx2 = v8::Context::New(); |
1489 ctx1->Enter(); | 1481 ctx1->Enter(); |
1490 | 1482 |
1491 HEAP->CollectAllAvailableGarbage(); | 1483 HEAP->CollectAllAvailableGarbage(); |
1492 CHECK_EQ(4, NumberOfGlobalObjects()); | 1484 CHECK_EQ(4, NumberOfGlobalObjects()); |
1493 | 1485 |
1494 { | 1486 { |
1495 v8::HandleScope inner_scope; | 1487 v8::HandleScope inner_scope; |
1496 CompileRun("var v = { y: 42}"); | 1488 CompileRun("var v = { y: 42}"); |
1497 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); | 1489 v8::Local<v8::Value> v = ctx1->Global()->Get(v8_str("v")); |
1498 ctx2->Enter(); | 1490 ctx2->Enter(); |
1499 ctx2->Global()->Set(v8_str("o"), v); | 1491 ctx2->Global()->Set(v8_str("o"), v); |
1500 v8::Local<v8::Value> res = CompileRun( | 1492 v8::Local<v8::Value> res = CompileRun( |
1501 "function f() {" | 1493 "function f() {" |
1502 " var p = {x: 42};" | 1494 " var p = {x: 42};" |
1503 " p.__proto__ = o;" | 1495 " p.__proto__ = o;" |
1504 " return p.x;" | 1496 " return p.x;" |
1505 "}" | 1497 "}" |
1506 "for (var i = 0; i < 10; ++i) f();" | 1498 "for (var i = 0; i < 10; ++i) f();" |
1507 "%OptimizeFunctionOnNextCall(f);" | 1499 "%OptimizeFunctionOnNextCall(f);" |
1508 "f();"); | 1500 "f();"); |
1509 CHECK_EQ(42, res->Int32Value()); | 1501 CHECK_EQ(42, res->Int32Value()); |
1510 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); | 1502 ctx2->Global()->Set(v8_str("o"), v8::Int32::New(0)); |
1511 ctx2->Exit(); | 1503 ctx2->Exit(); |
1512 ctx1->Exit(); | 1504 ctx1->Exit(); |
1513 ctx1.Dispose(); | 1505 ctx1.Dispose(); |
1514 v8::V8::ContextDisposedNotification(); | |
1515 } | 1506 } |
1516 HEAP->CollectAllAvailableGarbage(); | 1507 HEAP->CollectAllAvailableGarbage(); |
1517 CHECK_EQ(2, NumberOfGlobalObjects()); | 1508 CHECK_EQ(2, NumberOfGlobalObjects()); |
1518 ctx2.Dispose(); | 1509 ctx2.Dispose(); |
1519 HEAP->CollectAllAvailableGarbage(); | 1510 HEAP->CollectAllAvailableGarbage(); |
1520 CHECK_EQ(0, NumberOfGlobalObjects()); | 1511 CHECK_EQ(0, NumberOfGlobalObjects()); |
1521 } | 1512 } |
1522 | 1513 |
1523 | 1514 |
1524 TEST(InstanceOfStubWriteBarrier) { | 1515 TEST(InstanceOfStubWriteBarrier) { |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2042 fun1 = env->Global()->Get(v8_str("fun")); | 2033 fun1 = env->Global()->Get(v8_str("fun")); |
2043 } | 2034 } |
2044 | 2035 |
2045 { | 2036 { |
2046 LocalContext env; | 2037 LocalContext env; |
2047 CompileRun("function fun() {};"); | 2038 CompileRun("function fun() {};"); |
2048 fun2 = env->Global()->Get(v8_str("fun")); | 2039 fun2 = env->Global()->Get(v8_str("fun")); |
2049 } | 2040 } |
2050 | 2041 |
2051 // Prepare function f that contains type feedback for closures | 2042 // Prepare function f that contains type feedback for closures |
2052 // originating from two different native contexts. | 2043 // originating from two different global contexts. |
2053 v8::Context::GetCurrent()->Global()->Set(v8_str("fun1"), fun1); | 2044 v8::Context::GetCurrent()->Global()->Set(v8_str("fun1"), fun1); |
2054 v8::Context::GetCurrent()->Global()->Set(v8_str("fun2"), fun2); | 2045 v8::Context::GetCurrent()->Global()->Set(v8_str("fun2"), fun2); |
2055 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); | 2046 CompileRun("function f(a, b) { a(); b(); } f(fun1, fun2);"); |
2056 Handle<JSFunction> f = | 2047 Handle<JSFunction> f = |
2057 v8::Utils::OpenHandle( | 2048 v8::Utils::OpenHandle( |
2058 *v8::Handle<v8::Function>::Cast( | 2049 *v8::Handle<v8::Function>::Cast( |
2059 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); | 2050 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); |
2060 Handle<TypeFeedbackCells> cells(TypeFeedbackInfo::cast( | 2051 Handle<TypeFeedbackCells> cells(TypeFeedbackInfo::cast( |
2061 f->shared()->code()->type_feedback_info())->type_feedback_cells()); | 2052 f->shared()->code()->type_feedback_info())->type_feedback_cells()); |
2062 | 2053 |
(...skipping 25 matching lines...) Expand all Loading... |
2088 return NULL; | 2079 return NULL; |
2089 } | 2080 } |
2090 | 2081 |
2091 | 2082 |
2092 TEST(IncrementalMarkingPreservesMonomorhpicIC) { | 2083 TEST(IncrementalMarkingPreservesMonomorhpicIC) { |
2093 if (i::FLAG_always_opt) return; | 2084 if (i::FLAG_always_opt) return; |
2094 InitializeVM(); | 2085 InitializeVM(); |
2095 v8::HandleScope scope; | 2086 v8::HandleScope scope; |
2096 | 2087 |
2097 // Prepare function f that contains a monomorphic IC for object | 2088 // Prepare function f that contains a monomorphic IC for object |
2098 // originating from the same native context. | 2089 // originating from the same global context. |
2099 CompileRun("function fun() { this.x = 1; }; var obj = new fun();" | 2090 CompileRun("function fun() { this.x = 1; }; var obj = new fun();" |
2100 "function f(o) { return o.x; } f(obj); f(obj);"); | 2091 "function f(o) { return o.x; } f(obj); f(obj);"); |
2101 Handle<JSFunction> f = | 2092 Handle<JSFunction> f = |
2102 v8::Utils::OpenHandle( | 2093 v8::Utils::OpenHandle( |
2103 *v8::Handle<v8::Function>::Cast( | 2094 *v8::Handle<v8::Function>::Cast( |
2104 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); | 2095 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); |
2105 | 2096 |
2106 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); | 2097 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); |
2107 CHECK(ic_before->ic_state() == MONOMORPHIC); | 2098 CHECK(ic_before->ic_state() == MONOMORPHIC); |
2108 | 2099 |
| 2100 // Fire context dispose notification. |
| 2101 v8::V8::ContextDisposedNotification(); |
2109 SimulateIncrementalMarking(); | 2102 SimulateIncrementalMarking(); |
2110 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 2103 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
2111 | 2104 |
2112 Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); | 2105 Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); |
2113 CHECK(ic_after->ic_state() == MONOMORPHIC); | 2106 CHECK(ic_after->ic_state() == MONOMORPHIC); |
2114 } | 2107 } |
2115 | 2108 |
2116 | 2109 |
2117 TEST(IncrementalMarkingClearsMonomorhpicIC) { | 2110 TEST(IncrementalMarkingClearsMonomorhpicIC) { |
2118 if (i::FLAG_always_opt) return; | 2111 if (i::FLAG_always_opt) return; |
2119 InitializeVM(); | 2112 InitializeVM(); |
2120 v8::HandleScope scope; | 2113 v8::HandleScope scope; |
2121 v8::Local<v8::Value> obj1; | 2114 v8::Local<v8::Value> obj1; |
2122 | 2115 |
2123 { | 2116 { |
2124 LocalContext env; | 2117 LocalContext env; |
2125 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"); | 2118 CompileRun("function fun() { this.x = 1; }; var obj = new fun();"); |
2126 obj1 = env->Global()->Get(v8_str("obj")); | 2119 obj1 = env->Global()->Get(v8_str("obj")); |
2127 } | 2120 } |
2128 | 2121 |
2129 // Prepare function f that contains a monomorphic IC for object | 2122 // Prepare function f that contains a monomorphic IC for object |
2130 // originating from a different native context. | 2123 // originating from a different global context. |
2131 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1); | 2124 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1); |
2132 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);"); | 2125 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1);"); |
2133 Handle<JSFunction> f = | 2126 Handle<JSFunction> f = |
2134 v8::Utils::OpenHandle( | 2127 v8::Utils::OpenHandle( |
2135 *v8::Handle<v8::Function>::Cast( | 2128 *v8::Handle<v8::Function>::Cast( |
2136 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); | 2129 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); |
2137 | 2130 |
2138 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); | 2131 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); |
2139 CHECK(ic_before->ic_state() == MONOMORPHIC); | 2132 CHECK(ic_before->ic_state() == MONOMORPHIC); |
2140 | 2133 |
(...skipping 19 matching lines...) Expand all Loading... |
2160 obj1 = env->Global()->Get(v8_str("obj")); | 2153 obj1 = env->Global()->Get(v8_str("obj")); |
2161 } | 2154 } |
2162 | 2155 |
2163 { | 2156 { |
2164 LocalContext env; | 2157 LocalContext env; |
2165 CompileRun("function fun() { this.x = 2; }; var obj = new fun();"); | 2158 CompileRun("function fun() { this.x = 2; }; var obj = new fun();"); |
2166 obj2 = env->Global()->Get(v8_str("obj")); | 2159 obj2 = env->Global()->Get(v8_str("obj")); |
2167 } | 2160 } |
2168 | 2161 |
2169 // Prepare function f that contains a polymorphic IC for objects | 2162 // Prepare function f that contains a polymorphic IC for objects |
2170 // originating from two different native contexts. | 2163 // originating from two different global contexts. |
2171 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1); | 2164 v8::Context::GetCurrent()->Global()->Set(v8_str("obj1"), obj1); |
2172 v8::Context::GetCurrent()->Global()->Set(v8_str("obj2"), obj2); | 2165 v8::Context::GetCurrent()->Global()->Set(v8_str("obj2"), obj2); |
2173 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);"); | 2166 CompileRun("function f(o) { return o.x; } f(obj1); f(obj1); f(obj2);"); |
2174 Handle<JSFunction> f = | 2167 Handle<JSFunction> f = |
2175 v8::Utils::OpenHandle( | 2168 v8::Utils::OpenHandle( |
2176 *v8::Handle<v8::Function>::Cast( | 2169 *v8::Handle<v8::Function>::Cast( |
2177 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); | 2170 v8::Context::GetCurrent()->Global()->Get(v8_str("f")))); |
2178 | 2171 |
2179 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); | 2172 Code* ic_before = FindFirstIC(f->shared()->code(), Code::LOAD_IC); |
2180 CHECK(ic_before->ic_state() == MEGAMORPHIC); | 2173 CHECK(ic_before->ic_state() == MEGAMORPHIC); |
2181 | 2174 |
2182 // Fire context dispose notification. | 2175 // Fire context dispose notification. |
2183 v8::V8::ContextDisposedNotification(); | 2176 v8::V8::ContextDisposedNotification(); |
2184 SimulateIncrementalMarking(); | 2177 SimulateIncrementalMarking(); |
2185 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | 2178 HEAP->CollectAllGarbage(Heap::kNoGCFlags); |
2186 | 2179 |
2187 Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); | 2180 Code* ic_after = FindFirstIC(f->shared()->code(), Code::LOAD_IC); |
2188 CHECK(ic_after->ic_state() == UNINITIALIZED); | 2181 CHECK(ic_after->ic_state() == UNINITIALIZED); |
2189 } | 2182 } |
OLD | NEW |