| 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 "stub-cache.h" | |
| 13 #include "cctest.h" | 11 #include "cctest.h" |
| 14 | 12 |
| 15 using namespace v8::internal; | 13 using namespace v8::internal; |
| 16 | 14 |
| 17 static v8::Persistent<v8::Context> env; | 15 static v8::Persistent<v8::Context> env; |
| 18 | 16 |
| 19 static void InitializeVM() { | 17 static void InitializeVM() { |
| 20 if (env.IsEmpty()) env = v8::Context::New(); | 18 if (env.IsEmpty()) env = v8::Context::New(); |
| 21 v8::HandleScope scope; | 19 v8::HandleScope scope; |
| 22 env->Enter(); | 20 env->Enter(); |
| (...skipping 1997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2020 CHECK(value->Equals(obj->GetHiddenValue(v8_str("key string")))); | 2018 CHECK(value->Equals(obj->GetHiddenValue(v8_str("key string")))); |
| 2021 | 2019 |
| 2022 // Check size. | 2020 // Check size. |
| 2023 DescriptorArray* descriptors = internal_obj->map()->instance_descriptors(); | 2021 DescriptorArray* descriptors = internal_obj->map()->instance_descriptors(); |
| 2024 ObjectHashTable* hashtable = ObjectHashTable::cast( | 2022 ObjectHashTable* hashtable = ObjectHashTable::cast( |
| 2025 internal_obj->FastPropertyAt(descriptors->GetFieldIndex(0))); | 2023 internal_obj->FastPropertyAt(descriptors->GetFieldIndex(0))); |
| 2026 // HashTable header (5) and 4 initial entries (8). | 2024 // HashTable header (5) and 4 initial entries (8). |
| 2027 CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize); | 2025 CHECK_LE(hashtable->SizeFor(hashtable->length()), 13 * kPointerSize); |
| 2028 } | 2026 } |
| 2029 } | 2027 } |
| 2030 | |
| 2031 | |
| 2032 TEST(Regression144230) { | |
| 2033 InitializeVM(); | |
| 2034 v8::HandleScope scope; | |
| 2035 | |
| 2036 // First make sure that the uninitialized CallIC stub is on a single page | |
| 2037 // that will later be selected as an evacuation candidate. | |
| 2038 { | |
| 2039 v8::HandleScope inner_scope; | |
| 2040 AlwaysAllocateScope always_allocate; | |
| 2041 SimulateFullSpace(HEAP->code_space()); | |
| 2042 ISOLATE->stub_cache()->ComputeCallInitialize(9, RelocInfo::CODE_TARGET); | |
| 2043 } | |
| 2044 | |
| 2045 // Second compile a CallIC and execute it once so that it gets patched to | |
| 2046 // the pre-monomorphic stub. These code objects are on yet another page. | |
| 2047 { | |
| 2048 v8::HandleScope inner_scope; | |
| 2049 AlwaysAllocateScope always_allocate; | |
| 2050 SimulateFullSpace(HEAP->code_space()); | |
| 2051 CompileRun("var o = { f:function(a,b,c,d,e,f,g,h,i) {}};" | |
| 2052 "function call() { o.f(1,2,3,4,5,6,7,8,9); };" | |
| 2053 "call();"); | |
| 2054 } | |
| 2055 | |
| 2056 // Third we fill up the last page of the code space so that it does not get | |
| 2057 // chosen as an evacuation candidate. | |
| 2058 { | |
| 2059 v8::HandleScope inner_scope; | |
| 2060 AlwaysAllocateScope always_allocate; | |
| 2061 CompileRun("for (var i = 0; i < 2000; i++) {" | |
| 2062 " eval('function f' + i + '() { return ' + i +'; };' +" | |
| 2063 " 'f' + i + '();');" | |
| 2064 "}"); | |
| 2065 } | |
| 2066 HEAP->CollectAllGarbage(Heap::kNoGCFlags); | |
| 2067 | |
| 2068 // Fourth is the tricky part. Make sure the code containing the CallIC is | |
| 2069 // visited first without clearing the IC. The shared function info is then | |
| 2070 // visited later, causing the CallIC to be cleared. | |
| 2071 Handle<String> name = FACTORY->LookupAsciiSymbol("call"); | |
| 2072 Handle<GlobalObject> global(ISOLATE->context()->global()); | |
| 2073 MaybeObject* maybe_call = global->GetProperty(*name); | |
| 2074 JSFunction* call = JSFunction::cast(maybe_call->ToObjectChecked()); | |
| 2075 USE(global->SetProperty(*name, Smi::FromInt(0), NONE, kNonStrictMode)); | |
| 2076 ISOLATE->compilation_cache()->Clear(); | |
| 2077 call->shared()->set_ic_age(HEAP->global_ic_age() + 1); | |
| 2078 Handle<Object> call_code(call->code()); | |
| 2079 Handle<Object> call_function(call); | |
| 2080 | |
| 2081 // Now we are ready to mess up the heap. | |
| 2082 HEAP->CollectAllGarbage(Heap::kReduceMemoryFootprintMask); | |
| 2083 | |
| 2084 // Either heap verification caught the problem already or we go kaboom once | |
| 2085 // the CallIC is executed the next time. | |
| 2086 USE(global->SetProperty(*name, *call_function, NONE, kNonStrictMode)); | |
| 2087 CompileRun("call();"); | |
| 2088 } | |
| OLD | NEW |