| Index: test/cctest/test-heap.cc
|
| diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
|
| index ac121e059fe9a313e921d656918281da96d105eb..944eb3b98f7bc7148be126457735652212768fe8 100644
|
| --- a/test/cctest/test-heap.cc
|
| +++ b/test/cctest/test-heap.cc
|
| @@ -31,6 +31,7 @@
|
| #include "src/v8.h"
|
|
|
| #include "src/compilation-cache.h"
|
| +#include "src/deoptimizer.h"
|
| #include "src/execution.h"
|
| #include "src/factory.h"
|
| #include "src/global-handles.h"
|
| @@ -4608,6 +4609,79 @@ TEST(Regress388880) {
|
| }
|
|
|
|
|
| +TEST(ConstantPoolICUpdateDeopt) {
|
| + i::FLAG_allow_natives_syntax = true;
|
| +#ifdef VERIFY_HEAP
|
| + i::FLAG_verify_heap = true;
|
| +#endif
|
| +
|
| + CcTest::InitializeVM();
|
| + if (!CcTest::i_isolate()->use_crankshaft()) return;
|
| + if (i::FLAG_force_marking_deque_overflows) return;
|
| + v8::HandleScope outer_scope(CcTest::isolate());
|
| +
|
| + {
|
| + v8::HandleScope scope(CcTest::isolate());
|
| + CompileRun(
|
| + "function f(o) { return o.x; }"
|
| + // Call the function with different classes
|
| + // to force Crankshaft to generate LoadIC.
|
| + "f({a1 : 1});"
|
| + "f({a2 : 1});"
|
| + "f({a3 : 1});"
|
| + "f({a4 : 1});"
|
| + "f({a5 : 1});"
|
| + "f({a6 : 1});"
|
| + "f({a7 : 1});"
|
| + "f({a8 : 1});"
|
| + "f({a9 : 1});"
|
| + "f({a0 : 1});"
|
| + // Optimize the function with LoadIC.
|
| + "%OptimizeFunctionOnNextCall(f);"
|
| + "function g() { f({x : 1}); }"
|
| + "g();");
|
| + }
|
| +
|
| + SimulateIncrementalMarking(CcTest::heap());
|
| + // On ARM, this marks function f, its constant pool and the (pre-monomorphic)
|
| + // IC inside it.
|
| +
|
| + Handle<JSFunction> f = v8::Utils::OpenHandle(
|
| + *v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("f"))));
|
| +
|
| + // Code* ic_before = FindFirstIC(f->code(), Code::LOAD_IC);
|
| + // printf("Marked code: %i\n",
|
| + // Marking::IsBlack(Marking::MarkBitFrom(f->code())));
|
| + // printf("Marked IC: %i\n",
|
| + // Marking::IsBlack(Marking::MarkBitFrom(ic_before)));
|
| + // printf("Marked CP: %i\n",
|
| + // Marking::IsBlack(Marking::MarkBitFrom(f->code()->constant_pool())));
|
| +
|
| + // Call the function g to transition the IC to monomorphic.
|
| + v8::Handle<v8::Function> g =
|
| + v8::Handle<v8::Function>::Cast(CcTest::global()->Get(v8_str("g")));
|
| + g->Call(CcTest::global(), 0, NULL);
|
| +
|
| + // Now we have the marked (black) constant pool pointing to an unmarked
|
| + // (white) IC. However, the code for function f goes gray and it will
|
| + // be visited again.
|
| +
|
| + // Code* ic_after = FindFirstIC(f->code(), Code::LOAD_IC);
|
| + // printf("IC 0x%x white: %i\n", (int)ic_after,
|
| + // Marking::IsWhite(Marking::MarkBitFrom(ic_after)));
|
| + // printf("CP black: %i\n",
|
| + // Marking::IsBlack(Marking::MarkBitFrom(f->code()->constant_pool())));
|
| + // f->code()->constant_pool()->Print();
|
| +
|
| + // Invoke lazy deoptimization on f. This will invalidate the relocation table
|
| + // of f's code. As a result, marking of f will not mark the IC (since the
|
| + // relocation info no longer refers to the IC.
|
| + Deoptimizer::DeoptimizeFunction(*f);
|
| +
|
| + CcTest::heap()->CollectGarbage(OLD_POINTER_SPACE);
|
| +}
|
| +
|
| +
|
| #ifdef DEBUG
|
| TEST(PathTracer) {
|
| CcTest::InitializeVM();
|
|
|