Trace parseStackTrace()

in analysis/thread-dump/src/main/java/org/eclipse/jifa/tda/parser/JStackParser.java [554:740]


        Trace parseStackTrace(Thread thread, boolean deadLockThread, List<String> stackTraces) {
            Pool<String> symbolPool = snapshot.getSymbols();
            Pool<Frame> framePool = snapshot.getFrames();
            Pool<Monitor> monitorPool = snapshot.getMonitors();

            Trace trace = new Trace();
            List<Frame> frames = new ArrayList<>();
            List<Monitor> monitors = new ArrayList<>();
            Frame last = null;
            for (int i = 0; i < stackTraces.size(); i++) {
                Matcher m;
                String line = stackTraces.get(i);
                if (line.startsWith("at")) {
                    m = PATTERNS.JAVA_FRAME.matcher(line);
                    if (!m.matches()) {
                        throw new ParserException("Illegal java frame: " + line);
                    }

                    if (!monitors.isEmpty()) {
                        last.setMonitors(monitors.toArray(new Monitor[0]));
                        monitors.clear();
                    }

                    if (last != null) {
                        // add frame here since all related information has been processed
                        frames.add(framePool.add(last));
                    }

                    last = new Frame();
                    last.setClazz(symbolPool.add(m.group("class")));
                    last.setMethod(symbolPool.add(m.group("method")));
                    String module = m.group("module");
                    if (module != null) {
                        // strip '/'
                        last.setModule(symbolPool.add(module.substring(0, module.length() - 1)));
                    }
                    String source = m.group("source");
                    SourceType sourceType = SourceType.judge(source);
                    last.setSourceType(sourceType);
                    if (sourceType == SourceType.SOURCE_FILE_WITH_LINE_NUMBER) {
                        int index = source.indexOf(":");
                        last.setLine(Integer.parseInt(source.substring(index + 1)));
                        source = source.substring(0, index);
                        last.setSource(symbolPool.add(source));
                    } else if (sourceType == SourceType.SOURCE_FILE) {
                        last.setSource(symbolPool.add(source));
                    }

                } else {
                    if (line.startsWith(MonitorState.PARKING.prefix())) {
                        assert last != null;
                        m = PATTERNS.PARKING.matcher(line);
                        if (!m.matches()) {
                            throw new ParserException("Illegal parking line: " + line);
                        }
                        monitors.add(assembleMonitor(thread, !deadLockThread, MonitorState.PARKING,
                                                     Long.decode(m.group("address")),
                                                     false, symbolPool.add(m.group("class"))));
                    } else if (line.startsWith(MonitorState.WAITING_ON.prefix())) {
                        assert last != null;
                        if (line.contains("<no object reference available>")) {
                            monitors
                                .add(assembleMonitor(thread, !deadLockThread,
                                                     MonitorState.WAITING_ON_NO_OBJECT_REFERENCE_AVAILABLE,
                                                     -1, false, null));
                        } else {
                            m = PATTERNS.WAITING_ON.matcher(line);
                            if (!m.matches()) {
                                throw new ParserException("Illegal waiting line: " + line);
                            }
                            monitors
                                .add(assembleMonitor(thread, !deadLockThread, MonitorState.WAITING_ON,
                                                     Long.decode(m.group("address")),
                                                     m.group("isClass") != null,
                                                     symbolPool.add(m.group("class"))));
                        }
                    } else if (line.startsWith(MonitorState.WAITING_TO_RE_LOCK.prefix())) {
                        assert last != null;
                        m = PATTERNS.WAITING_TO_RE_LOCK.matcher(line);
                        if (!m.matches()) {
                            throw new ParserException("Illegal waiting to re-lock line: " + line);
                        }
                        monitors
                            .add(assembleMonitor(thread, !deadLockThread, MonitorState.WAITING_TO_RE_LOCK,
                                                 Long.decode(m.group("address")),
                                                 m.group("isClass") != null,
                                                 symbolPool.add(m.group("class"))));
                    } else if (line.startsWith(MonitorState.WAITING_ON_CLASS_INITIALIZATION.prefix())) {
                        assert last != null;
                        m = PATTERNS.WAITING_ON_CLASS_INITIALIZATION.matcher(line);
                        if (!m.matches()) {
                            throw new ParserException(
                                "Illegal waiting on class initialization line: " + line);
                        }
                        monitors
                            .add(assembleMonitor(thread, !deadLockThread,
                                                 MonitorState.WAITING_ON_CLASS_INITIALIZATION,
                                                 -1, true, symbolPool.add(m.group("class"))));
                    } else if (line.startsWith(MonitorState.LOCKED.prefix())) {
                        checkLastFrameNotNull(last, line);
                        m = PATTERNS.LOCKED.matcher(line);
                        if (!m.matches()) {
                            throw new ParserException("Illegal locked line: " + line);
                        }
                        monitors.add(assembleMonitor(thread, !deadLockThread, MonitorState.LOCKED,
                                                     Long.decode(m.group("address")),
                                                     m.group("isClass") != null,
                                                     symbolPool.add(m.group("class"))));
                    } else if (line.startsWith(MonitorState.WAITING_TO_LOCK.prefix())) {
                        checkLastFrameNotNull(last, line);
                        m = PATTERNS.WAITING_TO_LOCK.matcher(line);
                        if (!m.matches()) {
                            throw new ParserException("Illegal waiting to lock line: " + line);
                        }
                        monitors.add(assembleMonitor(thread, !deadLockThread, MonitorState.WAITING_TO_LOCK,
                                                     Long.decode(m.group("address")),
                                                     m.group("isClass") != null,
                                                     symbolPool.add(m.group("class"))));
                    } else if (line.startsWith(MonitorState.ELIMINATED.prefix())) {
                        checkLastFrameNotNull(last, line);
                        m = PATTERNS.ELIMINATED.matcher(line);
                        if (!m.matches()) {
                            throw new ParserException("Illegal eliminated lock line: " + line);
                        }
                        monitors.add(assembleMonitor(thread, !deadLockThread, MonitorState.ELIMINATED,
                                                     Long.decode(m.group("address")),
                                                     m.group("isClass") != null,
                                                     symbolPool.add(m.group("class"))));
                    } else if (line.startsWith(MonitorState.ELIMINATED_SCALAR_REPLACED.prefix())) {
                        checkLastFrameNotNull(last, line);
                        m = PATTERNS.ELIMINATED_SCALAR_REPLACED.matcher(line);
                        if (!m.matches()) {
                            throw new ParserException(
                                "Illegal eliminated(scalar replaced) lock line: " + line);
                        }
                        monitors.add(assembleMonitor(thread, !deadLockThread,
                                                     MonitorState.ELIMINATED_SCALAR_REPLACED,
                                                     -1,
                                                     false,
                                                     symbolPool.add(m.group("class"))));
                    } else if (line.equals(PATTERNS.LOCKED_OWNABLE_SYNCHRONIZERS)) {
                        // concurrent locks
                        int lockIndex = i + 1;
                        line = stackTraces.get(lockIndex);
                        if (PATTERNS.NONE.equals(line)) {
                            if (lockIndex + 1 != stackTraces.size()) {
                                throw new ParserException("Should not have content after: " + line);
                            }
                        } else {
                            Pool<ConcurrentLock> concurrentPool = snapshot.getConcurrentLocks();
                            List<ConcurrentLock> concurrentLocks = new ArrayList<>();
                            do {
                                m = PATTERNS.LOCKED_SYNCHRONIZER.matcher(line);
                                if (!m.matches()) {
                                    throw new ParserException("Illegal lock synchronizer line: " + line);
                                }
                                ConcurrentLock concurrentLock = new ConcurrentLock();
                                concurrentLock.setAddress(Long.decode(m.group("address")));
                                concurrentLock.setClazz(symbolPool.add(m.group("class")));
                                concurrentLocks.add(concurrentPool.add(concurrentLock));

                                if (++lockIndex < stackTraces.size()) {
                                    line = stackTraces.get(lockIndex);
                                } else {
                                    break;
                                }
                            } while (true);
                            trace.setConcurrentLocks(
                                concurrentLocks.toArray(new ConcurrentLock[0]));
                        }
                        break;
                    } else {
                        throw new ParserException("Unrecognized line: " + line);
                    }
                }
            }

            if (last != null) {
                if (!monitors.isEmpty()) {
                    last.setMonitors(monitors.toArray(new Monitor[0]));
                }
                frames.add(framePool.add(last));
            }

            trace.setFrames(frames.toArray(new Frame[0]));
            return trace;
        }