| Differences between
and this patch
- Source/JavaScriptCore/ChangeLog +74 lines
Lines 1-3 Source/JavaScriptCore/ChangeLog_sec1
1
2014-02-02  Filip Pizlo  <fpizlo@apple.com>
2
3
        GC should keep structures alive if they are inlined into optimized code (DFG or FTL) and their globalObject is alive
4
        https://bugs.webkit.org/show_bug.cgi?id=128072
5
6
        Reviewed by NOBODY (OOPS!).
7
        
8
        The original role of the structure transition fixpoint was to guard against cases
9
        where we had code that cached on a now-dead structure with a now-dead global object.
10
        Originally cached structures were strong references and so such a case could lead to
11
        a massive memory leak.
12
        
13
        Of course, we couldn't turn these references into simply weak references because then
14
        we would be throwing away code too frequently. It's surprisingly common to have
15
        idioms that reduce to something like:
16
        
17
            for (forever) {
18
                var o = new SuperImportantStateObject();
19
                // Do a bunch of work involving o.
20
                o = null; // Something that kills o.
21
                // Do some more work, and we GC here.
22
            }
23
        
24
        Usually the "o = null" arises because the allocation of the object is inside of a
25
        function that the loop calls. This is particularly frequent on the Web because that
26
        outer loop is actually the runloop and the GC is typically scheduled when the runloop
27
        is idle. So, if we treated all cached structures as weak and the app had any types
28
        that existed only during event handling but typically didn't remain reachable after
29
        the event got handled, then we would be throwing away a lot of code.
30
        
31
        So, instead of making those structures completely weak, we threw in a clever trick:
32
        we would fixpoint over all cached transitions that create new structures, and if any
33
        of those transitions was a part of code that appeared live, then we would mark the
34
        target structure. This tended to keep alive structures for objects that hot code
35
        would tend to create.
36
        
37
        But now it looks like this isn't enough. Those transition caches are just that -
38
        caches. They are imperfect. So, this patch adds another rule for keeping structures
39
        alive:
40
        
41
            If a structure is cached by an optimizing compiler and its global object is
42
            otherwise still live, then mark the structure.
43
        
44
        This rule will usually dominate the transition rule, but the transition rule is still
45
        critical for when we haven't created optimized code yet or for structures that aren't
46
        associated with a global object.
47
        
48
        This fix introduces two possibilities for simplifying the code, but they probably
49
        require some more investigation:
50
        
51
        - https://bugs.webkit.org/show_bug.cgi?id=128078
52
          Consider getting rid of the GC transition fixpoint for optimized code, since the
53
          global object rule is likely to dominate it
54
            
55
        - https://bugs.webkit.org/show_bug.cgi?id=128079
56
          Consider getting rid of the StructureStubInfo::resetByGC flag because the global
57
          object rule implies that caching on possibly-GCable structures is no longer
58
          disastrous
59
        
60
        This looks like a 50% speed-up on Octane2/gbemu in the FTL.
61
        
62
        This also includes a bunch of debug support for tracking what is going on inside of
63
        the GC's structure clearing. That's actually the bulk of this patch.
64
65
        * bytecode/CodeBlock.cpp:
66
        (JSC::dumpStructure):
67
        (JSC::dumpChain):
68
        (JSC::dumpStructureStubInfo):
69
        (JSC::CodeBlock::printGetByIdCacheStatus):
70
        (JSC::forceStructureLiveness):
71
        (JSC::CodeBlock::propagateTransitions):
72
        (JSC::CodeBlock::finalizeUnconditionally):
73
        * runtime/Options.h:
74
1
2014-02-01  Filip Pizlo  <fpizlo@apple.com>
75
2014-02-01  Filip Pizlo  <fpizlo@apple.com>
2
76
3
        JSC profiler's stub info profiling support should work again
77
        JSC profiler's stub info profiling support should work again
- Source/JavaScriptCore/bytecode/CodeBlock.cpp -106 / +175 lines
Lines 312-332 void CodeBlock::printGetByIdOp(PrintStre Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec1
312
}
312
}
313
313
314
#if ENABLE(JIT) || ENABLE(LLINT) // unused in some configurations
314
#if ENABLE(JIT) || ENABLE(LLINT) // unused in some configurations
315
static void dumpStructure(PrintStream& out, const char* name, ExecState* exec, Structure* structure, const Identifier& ident)
315
static void dumpStructure(PrintStream& out, const char* name, VM& vm, Structure* structure, const Identifier* ident)
316
{
316
{
317
    if (!structure)
317
    if (!structure)
318
        return;
318
        return;
319
    
319
    
320
    out.printf("%s = %p", name, structure);
320
    out.printf("%s = %p", name, structure);
321
    
321
    
322
    PropertyOffset offset = structure->getConcurrently(exec->vm(), ident.impl());
322
    if (ident) {
323
    if (offset != invalidOffset)
323
        PropertyOffset offset = structure->getConcurrently(vm, ident->impl());
324
        out.printf(" (offset = %d)", offset);
324
        if (offset != invalidOffset)
325
            out.printf(" (offset = %d)", offset);
326
    }
325
}
327
}
326
#endif
328
#endif
327
329
328
#if ENABLE(JIT) // unused when not ENABLE(JIT), leading to silly warnings
330
#if ENABLE(JIT) // unused when not ENABLE(JIT), leading to silly warnings
329
static void dumpChain(PrintStream& out, ExecState* exec, StructureChain* chain, const Identifier& ident)
331
static void dumpChain(PrintStream& out, VM& vm, StructureChain* chain, const Identifier* ident)
330
{
332
{
331
    out.printf("chain = %p: [", chain);
333
    out.printf("chain = %p: [", chain);
332
    bool first = true;
334
    bool first = true;
Lines 337-346 static void dumpChain(PrintStream& out, Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec2
337
            first = false;
339
            first = false;
338
        else
340
        else
339
            out.printf(", ");
341
            out.printf(", ");
340
        dumpStructure(out, "struct", exec, currentStructure->get(), ident);
342
        dumpStructure(out, "struct", vm, currentStructure->get(), ident);
341
    }
343
    }
342
    out.printf("]");
344
    out.printf("]");
343
}
345
}
346
347
static void dumpStructureStubInfo(PrintStream& out, VM& vm, StructureStubInfo& stubInfo, const Identifier* ident)
348
{
349
    Structure* baseStructure = 0;
350
    Structure* prototypeStructure = 0;
351
    StructureChain* chain = 0;
352
    PolymorphicAccessStructureList* structureList = 0;
353
    int listSize = 0;
354
    
355
    switch (stubInfo.accessType) {
356
    case access_get_by_id_self:
357
        out.printf("self");
358
        baseStructure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
359
        break;
360
    case access_get_by_id_proto:
361
        out.printf("proto");
362
        baseStructure = stubInfo.u.getByIdProto.baseObjectStructure.get();
363
        prototypeStructure = stubInfo.u.getByIdProto.prototypeStructure.get();
364
        break;
365
    case access_get_by_id_chain:
366
        out.printf("chain");
367
        baseStructure = stubInfo.u.getByIdChain.baseObjectStructure.get();
368
        chain = stubInfo.u.getByIdChain.chain.get();
369
        break;
370
    case access_get_by_id_self_list:
371
        out.printf("self_list");
372
        structureList = stubInfo.u.getByIdSelfList.structureList;
373
        listSize = stubInfo.u.getByIdSelfList.listSize;
374
        break;
375
    case access_get_by_id_proto_list:
376
        out.printf("proto_list");
377
        structureList = stubInfo.u.getByIdProtoList.structureList;
378
        listSize = stubInfo.u.getByIdProtoList.listSize;
379
        break;
380
    case access_unset:
381
        out.printf("unset");
382
        break;
383
    case access_get_by_id_generic:
384
        out.printf("generic");
385
        break;
386
    case access_get_array_length:
387
        out.printf("array_length");
388
        break;
389
    case access_get_string_length:
390
        out.printf("string_length");
391
        break;
392
    case access_in_list:
393
        out.printf("in_list");
394
        structureList = stubInfo.u.inList.structureList;
395
        listSize = stubInfo.u.inList.listSize;
396
        break;
397
    case access_put_by_id_transition_normal:
398
    case access_put_by_id_transition_direct:
399
    case access_put_by_id_replace:
400
    case access_put_by_id_list:
401
    case access_put_by_id_generic:
402
        // FIXME: Support dumping these.
403
        // https://bugs.webkit.org/show_bug.cgi?id=128062
404
        return;
405
    default:
406
        RELEASE_ASSERT_NOT_REACHED();
407
        break;
408
    }
409
    
410
    if (baseStructure) {
411
        out.printf(", ");
412
        dumpStructure(out, "struct", vm, baseStructure, ident);
413
    }
414
    
415
    if (prototypeStructure) {
416
        out.printf(", ");
417
        dumpStructure(out, "prototypeStruct", vm, baseStructure, ident);
418
    }
419
    
420
    if (chain) {
421
        out.printf(", ");
422
        dumpChain(out, vm, chain, ident);
423
    }
424
    
425
    if (structureList) {
426
        out.printf(", list = %p: [", structureList);
427
        for (int i = 0; i < listSize; ++i) {
428
            if (i)
429
                out.printf(", ");
430
            out.printf("(");
431
            dumpStructure(out, "base", vm, structureList->list[i].base.get(), ident);
432
            if (structureList->list[i].isChain) {
433
                if (structureList->list[i].u.chain.get()) {
434
                    out.printf(", ");
435
                    dumpChain(out, vm, structureList->list[i].u.chain.get(), ident);
436
                }
437
            } else {
438
                if (structureList->list[i].u.proto.get()) {
439
                    out.printf(", ");
440
                    dumpStructure(out, "proto", vm, structureList->list[i].u.proto.get(), ident);
441
                }
442
            }
443
            out.printf(")");
444
        }
445
        out.printf("]");
446
    }
447
}
344
#endif
448
#endif
345
449
346
void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int location, const StubInfoMap& map)
450
void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int location, const StubInfoMap& map)
Lines 356-362 void CodeBlock::printGetByIdCacheStatus( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec3
356
        out.printf(" llint(array_length)");
460
        out.printf(" llint(array_length)");
357
    else if (Structure* structure = instruction[4].u.structure.get()) {
461
    else if (Structure* structure = instruction[4].u.structure.get()) {
358
        out.printf(" llint(");
462
        out.printf(" llint(");
359
        dumpStructure(out, "struct", exec, structure, ident);
463
        dumpStructure(out, "struct", exec->vm(), structure, &ident);
360
        out.printf(")");
464
        out.printf(")");
361
    }
465
    }
362
#endif
466
#endif
Lines 369-460 void CodeBlock::printGetByIdCacheStatus( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec4
369
        
473
        
370
        if (stubInfo.seen) {
474
        if (stubInfo.seen) {
371
            out.printf(" jit(");
475
            out.printf(" jit(");
372
            
476
            dumpStructureStubInfo(out, exec->vm(), stubInfo, &ident);
373
            Structure* baseStructure = 0;
374
            Structure* prototypeStructure = 0;
375
            StructureChain* chain = 0;
376
            PolymorphicAccessStructureList* structureList = 0;
377
            int listSize = 0;
378
            
379
            switch (stubInfo.accessType) {
380
            case access_get_by_id_self:
381
                out.printf("self");
382
                baseStructure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
383
                break;
384
            case access_get_by_id_proto:
385
                out.printf("proto");
386
                baseStructure = stubInfo.u.getByIdProto.baseObjectStructure.get();
387
                prototypeStructure = stubInfo.u.getByIdProto.prototypeStructure.get();
388
                break;
389
            case access_get_by_id_chain:
390
                out.printf("chain");
391
                baseStructure = stubInfo.u.getByIdChain.baseObjectStructure.get();
392
                chain = stubInfo.u.getByIdChain.chain.get();
393
                break;
394
            case access_get_by_id_self_list:
395
                out.printf("self_list");
396
                structureList = stubInfo.u.getByIdSelfList.structureList;
397
                listSize = stubInfo.u.getByIdSelfList.listSize;
398
                break;
399
            case access_get_by_id_proto_list:
400
                out.printf("proto_list");
401
                structureList = stubInfo.u.getByIdProtoList.structureList;
402
                listSize = stubInfo.u.getByIdProtoList.listSize;
403
                break;
404
            case access_unset:
405
                out.printf("unset");
406
                break;
407
            case access_get_by_id_generic:
408
                out.printf("generic");
409
                break;
410
            case access_get_array_length:
411
                out.printf("array_length");
412
                break;
413
            case access_get_string_length:
414
                out.printf("string_length");
415
                break;
416
            default:
417
                RELEASE_ASSERT_NOT_REACHED();
418
                break;
419
            }
420
            
421
            if (baseStructure) {
422
                out.printf(", ");
423
                dumpStructure(out, "struct", exec, baseStructure, ident);
424
            }
425
            
426
            if (prototypeStructure) {
427
                out.printf(", ");
428
                dumpStructure(out, "prototypeStruct", exec, baseStructure, ident);
429
            }
430
            
431
            if (chain) {
432
                out.printf(", ");
433
                dumpChain(out, exec, chain, ident);
434
            }
435
            
436
            if (structureList) {
437
                out.printf(", list = %p: [", structureList);
438
                for (int i = 0; i < listSize; ++i) {
439
                    if (i)
440
                        out.printf(", ");
441
                    out.printf("(");
442
                    dumpStructure(out, "base", exec, structureList->list[i].base.get(), ident);
443
                    if (structureList->list[i].isChain) {
444
                        if (structureList->list[i].u.chain.get()) {
445
                            out.printf(", ");
446
                            dumpChain(out, exec, structureList->list[i].u.chain.get(), ident);
447
                        }
448
                    } else {
449
                        if (structureList->list[i].u.proto.get()) {
450
                            out.printf(", ");
451
                            dumpStructure(out, "proto", exec, structureList->list[i].u.proto.get(), ident);
452
                        }
453
                    }
454
                    out.printf(")");
455
                }
456
                out.printf("]");
457
            }
458
            out.printf(")");
477
            out.printf(")");
459
        }
478
        }
460
    }
479
    }
Lines 2036-2041 void CodeBlock::visitAggregate(SlotVisit Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec5
2036
#endif // ENABLE(DFG_JIT)
2055
#endif // ENABLE(DFG_JIT)
2037
}
2056
}
2038
2057
2058
// Returns false if we want this reconsidered.
2059
static void forceStructureLiveness(
2060
    SlotVisitor& visitor, WriteBarrier<JSCell>& possibleStructure)
2061
{
2062
    JSCell* cell = possibleStructure.get();
2063
    if (Heap::isMarked(cell))
2064
        return;
2065
    
2066
    if (cell->classInfo() != Structure::info())
2067
        return;
2068
    
2069
    Structure* structure = jsCast<Structure*>(cell);
2070
    if (!Heap::isMarked(structure->globalObject()))
2071
        return;
2072
    
2073
    visitor.append(&possibleStructure);
2074
    return;
2075
}
2076
2039
void CodeBlock::propagateTransitions(SlotVisitor& visitor)
2077
void CodeBlock::propagateTransitions(SlotVisitor& visitor)
2040
{
2078
{
2041
    UNUSED_PARAM(visitor);
2079
    UNUSED_PARAM(visitor);
Lines 2114-2120 void CodeBlock::propagateTransitions(Slo Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec6
2114
#if ENABLE(DFG_JIT)
2152
#if ENABLE(DFG_JIT)
2115
    if (JITCode::isOptimizingJIT(jitType())) {
2153
    if (JITCode::isOptimizingJIT(jitType())) {
2116
        DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
2154
        DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
2155
        
2156
        // This does the following:
2157
        // - Forces liveness of structures with live global objects
2158
        // - Forces liveness of structures that are known to be transitioned-to,
2159
        //   and where the sources of those transitions are live.
2160
        
2161
        for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i)
2162
            forceStructureLiveness(visitor, dfgCommon->weakReferences[i]);
2163
        
2117
        for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
2164
        for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
2165
            // FIXME: Consider getting rid of the transition fixpoint part of this.
2166
            // https://bugs.webkit.org/show_bug.cgi?id=128078
2167
            
2118
            if ((!dfgCommon->transitions[i].m_codeOrigin
2168
            if ((!dfgCommon->transitions[i].m_codeOrigin
2119
                 || Heap::isMarked(dfgCommon->transitions[i].m_codeOrigin.get()))
2169
                 || Heap::isMarked(dfgCommon->transitions[i].m_codeOrigin.get()))
2120
                && Heap::isMarked(dfgCommon->transitions[i].m_from.get())) {
2170
                && Heap::isMarked(dfgCommon->transitions[i].m_from.get())) {
Lines 2130-2136 void CodeBlock::propagateTransitions(Slo Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec7
2130
                //   heap location holds the source, and if so, stores the target.
2180
                //   heap location holds the source, and if so, stores the target.
2131
                //   Hence the source must be live for the transition to be live.
2181
                //   Hence the source must be live for the transition to be live.
2132
                visitor.append(&dfgCommon->transitions[i].m_to);
2182
                visitor.append(&dfgCommon->transitions[i].m_to);
2133
            } else
2183
            }
2184
2185
            forceStructureLiveness(visitor, dfgCommon->transitions[i].m_from);
2186
            forceStructureLiveness(visitor, dfgCommon->transitions[i].m_to);
2187
            
2188
            if (!Heap::isMarked(dfgCommon->transitions[i].m_to.get()))
2134
                allAreMarkedSoFar = false;
2189
                allAreMarkedSoFar = false;
2135
        }
2190
        }
2136
    }
2191
    }
Lines 2184-2189 void CodeBlock::visitWeakReferences(Slot Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec8
2184
2239
2185
void CodeBlock::finalizeUnconditionally()
2240
void CodeBlock::finalizeUnconditionally()
2186
{
2241
{
2242
    bool verbose = Options::verboseStructureClearingInGC() || Options::verboseOSR();
2243
    
2187
    Interpreter* interpreter = m_vm->interpreter;
2244
    Interpreter* interpreter = m_vm->interpreter;
2188
    if (JITCode::couldBeInterpreted(jitType())) {
2245
    if (JITCode::couldBeInterpreted(jitType())) {
2189
        const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
2246
        const Vector<unsigned>& propertyAccessInstructions = m_unlinkedCode->propertyAccessInstructions();
Lines 2196-2202 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec9
2196
            case op_put_by_id_out_of_line:
2253
            case op_put_by_id_out_of_line:
2197
                if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
2254
                if (!curInstruction[4].u.structure || Heap::isMarked(curInstruction[4].u.structure.get()))
2198
                    break;
2255
                    break;
2199
                if (Options::verboseOSR())
2256
                if (verbose)
2200
                    dataLogF("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
2257
                    dataLogF("Clearing LLInt property access with structure %p.\n", curInstruction[4].u.structure.get());
2201
                curInstruction[4].u.structure.clear();
2258
                curInstruction[4].u.structure.clear();
2202
                curInstruction[5].u.operand = 0;
2259
                curInstruction[5].u.operand = 0;
Lines 2209-2215 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec10
2209
                    && Heap::isMarked(curInstruction[6].u.structure.get())
2266
                    && Heap::isMarked(curInstruction[6].u.structure.get())
2210
                    && Heap::isMarked(curInstruction[7].u.structureChain.get()))
2267
                    && Heap::isMarked(curInstruction[7].u.structureChain.get()))
2211
                    break;
2268
                    break;
2212
                if (Options::verboseOSR()) {
2269
                if (verbose) {
2213
                    dataLogF("Clearing LLInt put transition with structures %p -> %p, chain %p.\n",
2270
                    dataLogF("Clearing LLInt put transition with structures %p -> %p, chain %p.\n",
2214
                            curInstruction[4].u.structure.get(),
2271
                            curInstruction[4].u.structure.get(),
2215
                            curInstruction[6].u.structure.get(),
2272
                            curInstruction[6].u.structure.get(),
Lines 2225-2238 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec11
2225
            case op_to_this:
2282
            case op_to_this:
2226
                if (!curInstruction[2].u.structure || Heap::isMarked(curInstruction[2].u.structure.get()))
2283
                if (!curInstruction[2].u.structure || Heap::isMarked(curInstruction[2].u.structure.get()))
2227
                    break;
2284
                    break;
2228
                if (Options::verboseOSR())
2285
                if (verbose)
2229
                    dataLogF("Clearing LLInt to_this with structure %p.\n", curInstruction[2].u.structure.get());
2286
                    dataLogF("Clearing LLInt to_this with structure %p.\n", curInstruction[2].u.structure.get());
2230
                curInstruction[2].u.structure.clear();
2287
                curInstruction[2].u.structure.clear();
2231
                break;
2288
                break;
2232
            case op_get_callee:
2289
            case op_get_callee:
2233
                if (!curInstruction[2].u.jsCell || Heap::isMarked(curInstruction[2].u.jsCell.get()))
2290
                if (!curInstruction[2].u.jsCell || Heap::isMarked(curInstruction[2].u.jsCell.get()))
2234
                    break;
2291
                    break;
2235
                if (Options::verboseOSR())
2292
                if (verbose)
2236
                    dataLogF("Clearing LLInt get callee with function %p.\n", curInstruction[2].u.jsCell.get());
2293
                    dataLogF("Clearing LLInt get callee with function %p.\n", curInstruction[2].u.jsCell.get());
2237
                curInstruction[2].u.jsCell.clear();
2294
                curInstruction[2].u.jsCell.clear();
2238
                break;
2295
                break;
Lines 2240-2246 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec12
2240
                WriteBarrierBase<JSActivation>& activation = curInstruction[5].u.activation;
2297
                WriteBarrierBase<JSActivation>& activation = curInstruction[5].u.activation;
2241
                if (!activation || Heap::isMarked(activation.get()))
2298
                if (!activation || Heap::isMarked(activation.get()))
2242
                    break;
2299
                    break;
2243
                if (Options::verboseOSR())
2300
                if (verbose)
2244
                    dataLogF("Clearing dead activation %p.\n", activation.get());
2301
                    dataLogF("Clearing dead activation %p.\n", activation.get());
2245
                activation.clear();
2302
                activation.clear();
2246
                break;
2303
                break;
Lines 2254-2260 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec13
2254
                WriteBarrierBase<Structure>& structure = curInstruction[5].u.structure;
2311
                WriteBarrierBase<Structure>& structure = curInstruction[5].u.structure;
2255
                if (!structure || Heap::isMarked(structure.get()))
2312
                if (!structure || Heap::isMarked(structure.get()))
2256
                    break;
2313
                    break;
2257
                if (Options::verboseOSR())
2314
                if (verbose)
2258
                    dataLogF("Clearing scope access with structure %p.\n", structure.get());
2315
                    dataLogF("Clearing scope access with structure %p.\n", structure.get());
2259
                structure.clear();
2316
                structure.clear();
2260
                break;
2317
                break;
Lines 2267-2273 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec14
2267
#if ENABLE(LLINT)
2324
#if ENABLE(LLINT)
2268
        for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
2325
        for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) {
2269
            if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
2326
            if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) {
2270
                if (Options::verboseOSR())
2327
                if (verbose)
2271
                    dataLog("Clearing LLInt call from ", *this, "\n");
2328
                    dataLog("Clearing LLInt call from ", *this, "\n");
2272
                m_llintCallLinkInfos[i].unlink();
2329
                m_llintCallLinkInfos[i].unlink();
2273
            }
2330
            }
Lines 2280-2289 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec15
2280
#if ENABLE(DFG_JIT)
2337
#if ENABLE(DFG_JIT)
2281
    // Check if we're not live. If we are, then jettison.
2338
    // Check if we're not live. If we are, then jettison.
2282
    if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_jitCode->dfgCommon()->livenessHasBeenProved)) {
2339
    if (!(shouldImmediatelyAssumeLivenessDuringScan() || m_jitCode->dfgCommon()->livenessHasBeenProved)) {
2283
        if (Options::verboseOSR())
2340
        if (verbose)
2284
            dataLog(*this, " has dead weak references, jettisoning during GC.\n");
2341
            dataLog(*this, " has dead weak references, jettisoning during GC.\n");
2285
2342
2286
        if (DFG::shouldShowDisassembly()) {
2343
        if (verbose || DFG::shouldShowDisassembly()) {
2287
            dataLog(*this, " will be jettisoned because of the following dead references:\n");
2344
            dataLog(*this, " will be jettisoned because of the following dead references:\n");
2288
            DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
2345
            DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
2289
            for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
2346
            for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
Lines 2317-2323 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec16
2317
                if (ClosureCallStubRoutine* stub = callLinkInfo(i).stub.get()) {
2374
                if (ClosureCallStubRoutine* stub = callLinkInfo(i).stub.get()) {
2318
                    if (!Heap::isMarked(stub->structure())
2375
                    if (!Heap::isMarked(stub->structure())
2319
                        || !Heap::isMarked(stub->executable())) {
2376
                        || !Heap::isMarked(stub->executable())) {
2320
                        if (Options::verboseOSR()) {
2377
                        if (verbose) {
2321
                            dataLog(
2378
                            dataLog(
2322
                                "Clearing closure call from ", *this, " to ",
2379
                                "Clearing closure call from ", *this, " to ",
2323
                                stub->executable()->hashFor(callLinkInfo(i).specializationKind()),
2380
                                stub->executable()->hashFor(callLinkInfo(i).specializationKind()),
Lines 2326-2332 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec17
2326
                        callLinkInfo(i).unlink(*m_vm, repatchBuffer);
2383
                        callLinkInfo(i).unlink(*m_vm, repatchBuffer);
2327
                    }
2384
                    }
2328
                } else if (!Heap::isMarked(callLinkInfo(i).callee.get())) {
2385
                } else if (!Heap::isMarked(callLinkInfo(i).callee.get())) {
2329
                    if (Options::verboseOSR()) {
2386
                    if (verbose) {
2330
                        dataLog(
2387
                        dataLog(
2331
                            "Clearing call from ", *this, " to ",
2388
                            "Clearing call from ", *this, " to ",
2332
                            RawPointer(callLinkInfo(i).callee.get()), " (",
2389
                            RawPointer(callLinkInfo(i).callee.get()), " (",
Lines 2338-2345 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec18
2338
                }
2395
                }
2339
            }
2396
            }
2340
            if (!!callLinkInfo(i).lastSeenCallee
2397
            if (!!callLinkInfo(i).lastSeenCallee
2341
                && !Heap::isMarked(callLinkInfo(i).lastSeenCallee.get()))
2398
                && !Heap::isMarked(callLinkInfo(i).lastSeenCallee.get())) {
2399
                if (verbose)
2400
                    dataLog("Clearing lastSeenCallee from ", *this, " to ", RawPointer(callLinkInfo(i).lastSeenCallee.get()), "\n");
2342
                callLinkInfo(i).lastSeenCallee.clear();
2401
                callLinkInfo(i).lastSeenCallee.clear();
2402
            }
2343
        }
2403
        }
2344
        for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
2404
        for (Bag<StructureStubInfo>::iterator iter = m_stubInfos.begin(); !!iter; ++iter) {
2345
            StructureStubInfo& stubInfo = **iter;
2405
            StructureStubInfo& stubInfo = **iter;
Lines 2347-2352 void CodeBlock::finalizeUnconditionally( Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec19
2347
            if (stubInfo.visitWeakReferences())
2407
            if (stubInfo.visitWeakReferences())
2348
                continue;
2408
                continue;
2349
            
2409
            
2410
            if (verbose) {
2411
                dataLog("Clearing stubInfo from ", *this, " at ", stubInfo.codeOrigin, " with state: ");
2412
                dumpStructureStubInfo(WTF::dataFile(), *vm(), stubInfo, 0);
2413
                dataLog("\n");
2414
            }
2415
            
2350
            resetStubDuringGCInternal(repatchBuffer, stubInfo);
2416
            resetStubDuringGCInternal(repatchBuffer, stubInfo);
2351
        }
2417
        }
2352
    }
2418
    }
Lines 2413-2418 void CodeBlock::resetStubInternal(Repatc Source/JavaScriptCore/bytecode/CodeBlock.cpp_sec20
2413
void CodeBlock::resetStubDuringGCInternal(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
2479
void CodeBlock::resetStubDuringGCInternal(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo)
2414
{
2480
{
2415
    resetStubInternal(repatchBuffer, stubInfo);
2481
    resetStubInternal(repatchBuffer, stubInfo);
2482
    
2483
    // FIXME: Consider getting rid of this flag; it might not be needed anymore.
2484
    // https://bugs.webkit.org/show_bug.cgi?id=128079
2416
    stubInfo.resetByGC = true;
2485
    stubInfo.resetByGC = true;
2417
}
2486
}
2418
#endif
2487
#endif
- Source/JavaScriptCore/runtime/Options.h +1 lines
Lines 132-137 typedef OptionRange optionRange; Source/JavaScriptCore/runtime/Options.h_sec1
132
    v(bool, alwaysComputeHash, false) \
132
    v(bool, alwaysComputeHash, false) \
133
    v(bool, testTheFTL, false) \
133
    v(bool, testTheFTL, false) \
134
    v(bool, verboseSanitizeStack, false) \
134
    v(bool, verboseSanitizeStack, false) \
135
    v(bool, verboseStructureClearingInGC, false) \
135
    \
136
    \
136
    v(bool, enableOSREntryToDFG, true) \
137
    v(bool, enableOSREntryToDFG, true) \
137
    v(bool, enableOSREntryToFTL, true) \
138
    v(bool, enableOSREntryToFTL, true) \

Return to Bug 128072