1
0
mirror of https://github.com/golang/go synced 2024-11-18 13:04:46 -07:00

cmd/heapview: delete

This is all dead code that never went anywhere.

Change-Id: I79db05d6391709bb9ae3d86f557246f1dd3b21f7
Reviewed-on: https://go-review.googlesource.com/c/159957
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Michael Matloob 2019-01-28 17:30:02 -05:00
parent d66bd3c5d5
commit 3c4dfba64b
14 changed files with 0 additions and 966 deletions

View File

@ -1 +0,0 @@
BasedOnStyle: Google

View File

@ -1 +0,0 @@
/node_modules/

View File

@ -1,45 +0,0 @@
# Go Heap Viewer Client
This directory contains the client Typescript code for the Go
heap viewer.
## Typescript Tooling
Below are instructions for downloading tooling and files to
help make the development process more convenient. These tools
are not required for contributing or running the heap viewer-
they are just meant as development aids.
## Node and NPM
We use npm to manage the dependencies for these tools. There are
a couple of ways of installing npm on your system, but we recommend
using nvm.
Run the following command to install nvm:
[shell]$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash
or see the instructions on [the nvm github page](github.com/creationix/nvm)
for alternative methods. This will put the nvm tool in your home directory
and edit your path to add nvm, node and other tools you install using them.
Once nvm is installed, use
[shell]$ nvm install node
then
[shell]$ nvm use node
to install node.js.
Once node is installed, you can install typescript using
[shell]$ npm install -g typescript
Finally, import type definitions into this project by running
[shell]$ npm install
in this directory. They will be imported into the node_packages directory
and be automatically available to the Typescript compiler.

View File

@ -1,195 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/**
* An enum of types of actions that might be requested
* by the app.
*/
enum Action {
TOGGLE_SIDEBAR, // Toggle the sidebar.
NAVIGATE_ABOUT, // Go to the about page.
}
const TITLE = 'Go Heap Viewer';
/**
* A type of event that signals to the AppElement controller
* that something shoud be done. For the most part, the structure
* of the app will be that elements' state will mostly be controlled
* by parent elements. Elements will issue actions that the AppElement
* will handle, and the app will be re-rendered down the DOM
* hierarchy.
*/
class ActionEvent extends Event {
static readonly EVENT_TYPE = 'action-event'
constructor(public readonly action: Action) { super(ActionEvent.EVENT_TYPE); }
}
/**
* A hamburger menu element. Triggers a TOGGLE_SIDE action to toggle the
* sidebar.
*/
export class HamburgerElement extends HTMLElement {
static readonly NAME = 'heap-hamburger';
createdCallback() {
this.appendChild(document.createTextNode('☰'));
this.onclick =
() => { this.dispatchEvent(new ActionEvent(Action.TOGGLE_SIDEBAR)) };
}
}
document.registerElement(HamburgerElement.NAME, HamburgerElement);
/**
* A heading for the page with a hamburger menu and a title.
*/
export class HeadingElement extends HTMLElement {
static readonly NAME = 'heap-heading';
createdCallback() {
this.style.display = 'block';
this.style.backgroundColor = '#2196F3';
this.style.webkitUserSelect = 'none';
this.style.cursor = 'default';
this.style.color = '#FFFFFF';
this.style.padding = '10px';
const div = document.createElement('div');
div.style.margin = '0px';
div.style.fontSize = '2em';
div.appendChild(document.createElement(HamburgerElement.NAME));
div.appendChild(document.createTextNode(' ' + TITLE));
this.appendChild(div);
}
}
document.registerElement(HeadingElement.NAME, HeadingElement);
/**
* A sidebar that has navigation for the app.
*/
export class SidebarElement extends HTMLElement {
static readonly NAME = 'heap-sidebar';
createdCallback() {
this.style.display = 'none';
this.style.backgroundColor = '#9E9E9E';
this.style.width = '15em';
const aboutButton = document.createElement('button');
aboutButton.innerText = 'about';
aboutButton.onclick =
() => { this.dispatchEvent(new ActionEvent(Action.NAVIGATE_ABOUT)) };
this.appendChild(aboutButton);
}
toggle() {
this.style.display = this.style.display === 'none' ? 'block' : 'none';
}
}
document.registerElement(SidebarElement.NAME, SidebarElement);
/**
* A Container for the main content in the app.
* TODO(matloob): Implement main content.
*/
export class MainContentElement extends HTMLElement {
static readonly NAME = 'heap-container';
attachedCallback() {
this.style.backgroundColor = '#E0E0E0';
this.style.height = '100%';
this.style.flex = '1';
}
}
document.registerElement(MainContentElement.NAME, MainContentElement);
/**
* A container and controller for the whole app.
* Contains the heading, side drawer and main panel.
*/
class AppElement extends HTMLElement {
static readonly NAME = 'heap-app';
private sidebar: SidebarElement;
private mainContent: MainContentElement;
attachedCallback() {
document.title = TITLE;
this.addEventListener(
ActionEvent.EVENT_TYPE, e => this.handleAction(e as ActionEvent),
/* capture */ true);
this.render();
}
render() {
this.style.display = 'block';
this.style.height = '100vh';
this.style.width = '100vw';
this.appendChild(document.createElement(HeadingElement.NAME));
const bodyDiv = document.createElement('div');
bodyDiv.style.height = '100%';
bodyDiv.style.display = 'flex';
this.sidebar =
document.createElement(SidebarElement.NAME) as SidebarElement;
bodyDiv.appendChild(this.sidebar);
this.mainContent =
document.createElement(MainContentElement.NAME) as MainContentElement;
bodyDiv.appendChild(this.mainContent);
this.appendChild(bodyDiv);
this.renderRoute();
}
renderRoute() {
this.mainContent.innerHTML = ''
switch (window.location.pathname) {
case '/about':
this.mainContent.appendChild(
document.createElement(AboutPageElement.NAME));
break;
}
}
handleAction(event: ActionEvent) {
switch (event.action) {
case Action.TOGGLE_SIDEBAR:
this.sidebar.toggle();
break;
case Action.NAVIGATE_ABOUT:
window.history.pushState({}, '', '/about');
this.renderRoute();
break;
}
}
}
document.registerElement(AppElement.NAME, AppElement);
/**
* An about page.
*/
class AboutPageElement extends HTMLElement {
static readonly NAME = 'heap-about';
createdCallback() { this.textContent = TITLE; }
}
document.registerElement(AboutPageElement.NAME, AboutPageElement);
/**
* Resets body's margin and padding, and sets font.
*/
function clearStyle(document: Document) {
const styleElement = document.createElement('style') as HTMLStyleElement;
document.head.appendChild(styleElement);
const styleSheet = styleElement.sheet as CSSStyleSheet;
styleSheet.insertRule(
'* {font-family: Roboto,Helvetica; box-sizing: border-box}', 0);
styleSheet.insertRule('body {margin: 0px; padding:0px}', 0);
}
export function main() {
clearStyle(document);
document.body.appendChild(document.createElement(AppElement.NAME));
}

View File

@ -1,29 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import {HamburgerElement, HeadingElement, SidebarElement, main} from './main';
describe('main', () => {
it('sets the document\'s title', () => {
main();
expect(document.title).toBe('Go Heap Viewer');
});
it('has a heading', () => {
main();
expect(document.querySelector(HeadingElement.NAME)).toBeDefined();
});
it('has a sidebar', () => {
main();
const hamburger = document.querySelector(HamburgerElement.NAME);
const sidebar =
document.querySelector(SidebarElement.NAME) as SidebarElement;
expect(sidebar.style.display).toBe('none');
// Click on the hamburger. Sidebar should then be visible.
hamburger.dispatchEvent(new Event('click'));
expect(sidebar.style.display).toBe('block');
})
});

View File

@ -1,35 +0,0 @@
{
"//": [
"Copyright 2016 The Go Authors. All rights reserved.",
"Use of this source code is governed by a BSD-style",
"license that can be found in the LICENSE file.",
"This file exists to help import typescript typings",
"for web features used in this project. Neither the",
"typings nor node or npm are required to do development",
"on the code in this project.",
"If you do have npm installed, use the `npm i` command",
"in this directory to install the typings."
],
"private": true,
"name": "@golangtools/heapview",
"version": "0.0.0",
"devDependencies": {
"@types/webcomponents.js": "latest",
"@types/whatwg-fetch": "latest",
"@types/jasmine": "latest",
"jasmine-core": "latest",
"karma": "latest",
"karma-jasmine": "latest",
"karma-chrome-launcher": "latest",
"clang-format": "latest"
},
"scripts": {
"test": "karma start testing/karma.conf.js",
"format": "find . | grep '\\(test_main\\.js\\|\\.ts\\)$' | xargs clang-format -i",
"lint": "tslint --project ."
}
}

View File

@ -1,22 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
module.exports = config => {
config.set({
frameworks: ['jasmine'],
basePath: '../../../..',
files: [
'third_party/webcomponents/customelements.js',
'third_party/typescript/typescript.js',
'third_party/moduleloader/moduleloader.js',
'cmd/heapview/client/testing/test_main.js',
{pattern: 'cmd/heapview/client/**/*.ts', included: false},
],
browsers: ['Chrome'],
plugins: [
'karma-jasmine',
'karma-chrome-launcher'
],
})
}

View File

@ -1,32 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Configure module loader.
System.transpiler = 'typescript'
System.typescriptOptions = {
target: ts.ScriptTarget.ES2015
};
System.locate = (load) => load.name + '.ts';
// Determine set of test files.
var tests = [];
for (var file in window.__karma__.files) {
if (window.__karma__.files.hasOwnProperty(file)) {
if (/_test\.ts$/.test(file)) {
tests.push(file.slice(0, -3));
}
}
}
// Steal loaded callback so we can block until we're
// done loading all test modules.
var loadedCallback = window.__karma__.loaded.bind(window.__karma__);
window.__karma__.loaded = () => {};
// Load all test modules, and then call loadedCallback.
var promises = [];
for (var i = 0; i < tests.length; i++) {
promises.push(System.import(tests[i]));
}
Promise.all(promises).then(loadedCallback);

View File

@ -1,16 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file contains configuration for the Typescript
// compiler if you're running it locally for typechecking
// and other tooling. The Typescript compiler is
// not necessary to do development on this project.
{
"compilerOptions": {
"noEmit": true,
"strictNullChecks": true,
"target": "es2015"
}
}

View File

@ -1,40 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This tslint file is based on a configuration used at
// Google.
{
"rules": {
"class-name": true,
"forin": true,
"interface-name": [true, "never-prefix"],
"jsdoc-format": true,
"label-position": true,
"label-undefined": true,
"new-parens": true,
"no-angle-bracket-type-assertion": true,
"no-construct": true,
"no-debugger": true,
"no-namespace": [true, "allow-declarations"],
"no-reference": true,
"no-require-imports": true,
"no-unused-expression": true,
"no-unused-variable": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"semicolon": [true, "always"],
"switch-default": true,
"triple-equals": [true, "allow-null-check"],
"use-isnan": true,
"variable-name": [
true,
"check-format",
"ban-keywords",
"allow-leading-underscore",
"allow-trailing-underscore",
"allow-pascal-case"
]
}
}

View File

@ -1,145 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin linux
package core
import (
"errors"
"fmt"
"io"
"os"
"syscall"
)
var errMmapClosed = errors.New("mmap: closed")
// mmapFile wraps a memory-mapped file.
type mmapFile struct {
data []byte
pos uint64
writable bool
}
// mmapOpen opens the named file for reading.
// If writable is true, the file is also open for writing.
func mmapOpen(filename string, writable bool) (*mmapFile, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
st, err := f.Stat()
if err != nil {
return nil, err
}
size := st.Size()
if size == 0 {
return &mmapFile{data: []byte{}}, nil
}
if size < 0 {
return nil, fmt.Errorf("mmap: file %q has negative size: %d", filename, size)
}
if size != int64(int(size)) {
return nil, fmt.Errorf("mmap: file %q is too large", filename)
}
prot := syscall.PROT_READ
if writable {
prot |= syscall.PROT_WRITE
}
data, err := syscall.Mmap(int(f.Fd()), 0, int(size), prot, syscall.MAP_SHARED)
if err != nil {
return nil, err
}
return &mmapFile{data: data, writable: writable}, nil
}
// Size returns the size of the mapped file.
func (f *mmapFile) Size() uint64 {
return uint64(len(f.data))
}
// Pos returns the current file pointer.
func (f *mmapFile) Pos() uint64 {
return f.pos
}
// SeekTo sets the current file pointer relative to the start of the file.
func (f *mmapFile) SeekTo(offset uint64) {
f.pos = offset
}
// Read implements io.Reader.
func (f *mmapFile) Read(p []byte) (int, error) {
if f.data == nil {
return 0, errMmapClosed
}
if f.pos >= f.Size() {
return 0, io.EOF
}
n := copy(p, f.data[f.pos:])
f.pos += uint64(n)
if n < len(p) {
return n, io.EOF
}
return n, nil
}
// ReadByte implements io.ByteReader.
func (f *mmapFile) ReadByte() (byte, error) {
if f.data == nil {
return 0, errMmapClosed
}
if f.pos >= f.Size() {
return 0, io.EOF
}
b := f.data[f.pos]
f.pos++
return b, nil
}
// ReadSlice returns a slice of size n that points directly at the
// underlying mapped file. There is no copying. Fails if it cannot
// read at least n bytes.
func (f *mmapFile) ReadSlice(n uint64) ([]byte, error) {
if f.data == nil {
return nil, errMmapClosed
}
if f.pos+n >= f.Size() {
return nil, io.EOF
}
first := f.pos
f.pos += n
return f.data[first:f.pos:f.pos], nil
}
// ReadSliceAt is like ReadSlice, but reads from a specific offset.
// The file pointer is not used or advanced.
func (f *mmapFile) ReadSliceAt(offset, n uint64) ([]byte, error) {
if f.data == nil {
return nil, errMmapClosed
}
if f.Size() < offset {
return nil, fmt.Errorf("mmap: out-of-bounds ReadSliceAt offset %d, size is %d", offset, f.Size())
}
if offset+n >= f.Size() {
return nil, io.EOF
}
end := offset + n
return f.data[offset:end:end], nil
}
// Close closes the file.
func (f *mmapFile) Close() error {
if f.data == nil {
return nil
}
err := syscall.Munmap(f.data)
f.data = nil
f.pos = 0
return err
}

View File

@ -1,14 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !darwin,!linux
package core
// TODO(matloob): perhaps use the more portable golang.org/x/exp/mmap
// instead of the mmap code in mmapfile.go.
type mmapFile struct{}
func (m *mmapFile) Close() error { return nil }

View File

@ -1,308 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package core provides functions for reading core dumps
// and examining their contained heaps.
package core
import (
"bytes"
"encoding/binary"
"fmt"
"runtime"
"sort"
)
// RawDump provides raw access to the heap records in a core file.
// The raw records in this file are described by other structs named Raw{*}.
// All []byte slices are direct references to the underlying mmap'd file.
// These references will become invalid as soon as the RawDump is closed.
type RawDump struct {
Params *RawParams
MemStats *runtime.MemStats
HeapObjects []RawSegment // heap objects sorted by Addr, low-to-high
GlobalSegments []RawSegment // data, bss, and noptrbss segments
OSThreads []*RawOSThread
Goroutines []*RawGoroutine
StackFrames []*RawStackFrame
OtherRoots []*RawOtherRoot
Finalizers []*RawFinalizer
Defers []*RawDefer
Panics []*RawPanic
TypeFromItab map[uint64]uint64 // map from itab address to the type address that itab represents
TypeFromAddr map[uint64]*RawType // map from RawType.Addr to RawType
MemProfMap map[uint64]*RawMemProfEntry
AllocSamples []*RawAllocSample
fmap *mmapFile
}
// RawParams holds metadata about the program that generated the dump.
type RawParams struct {
// Info about the memory space
ByteOrder binary.ByteOrder // byte order of all memory in this dump
PtrSize uint64 // in bytes
HeapStart uint64 // heap start address
HeapEnd uint64 // heap end address (this is the last byte in the heap + 1)
// Info about the program that generated this heapdump
GoArch string // GOARCH of the runtime library that generated this dump
GoExperiment string // GOEXPERIMENT of the toolchain that build the runtime library
NCPU uint64 // number of physical cpus available to the program
}
// RawSegment represents a segment of memory.
type RawSegment struct {
Addr uint64 // base address of the segment
Data []byte // data for this segment
PtrFields RawPtrFields // offsets of ptr fields within this segment
}
// RawPtrFields represents a pointer field.
type RawPtrFields struct {
encoded []byte // list of uvarint-encoded offsets, or nil if none
startOff, endOff uint64 // decoded offsets are translated and clipped to [startOff,endOff)
}
// RawOSThread represents an OS thread.
type RawOSThread struct {
MAddr uint64 // address of the OS thread descriptor (M)
GoID uint64 // go's internal ID for the thread
ProcID uint64 // kernel's ID for the thread
}
// RawGoroutine represents a goroutine structure.
type RawGoroutine struct {
GAddr uint64 // address of the goroutine descriptor
SP uint64 // current stack pointer (lowest address in the currently running frame)
GoID uint64 // goroutine ID
GoPC uint64 // PC of the go statement that created this goroutine
Status uint64
IsSystem bool // true if started by the system
IsBackground bool // always false in go1.7
WaitSince uint64 // time the goroutine started waiting, in nanoseconds since the Unix epoch
WaitReason string
CtxtAddr uint64 // address of the scheduling ctxt
MAddr uint64 // address of the OS thread descriptor (M)
TopDeferAddr uint64 // address of the top defer record
TopPanicAddr uint64 // address of the top panic record
}
// RawStackFrame represents a stack frame.
type RawStackFrame struct {
Name string
Depth uint64 // 0 = bottom of stack (currently running frame)
CalleeSP uint64 // stack pointer of the child frame (or 0 for the bottom-most frame)
EntryPC uint64 // entry PC for the function
PC uint64 // current PC being executed
NextPC uint64 // for callers, where the function resumes (if anywhere) after the callee is done
Segment RawSegment // local vars (Segment.Addr is the stack pointer, i.e., lowest address in the frame)
}
// RawOtherRoot represents the other roots not in RawDump's other fields.
type RawOtherRoot struct {
Description string
Addr uint64 // address pointed to by this root
}
// RawFinalizer represents a finalizer.
type RawFinalizer struct {
IsQueued bool // if true, the object is unreachable and the finalizer is ready to run
ObjAddr uint64 // address of the object to finalize
ObjTypeAddr uint64 // address of the descriptor for typeof(obj)
FnAddr uint64 // function to be run (a FuncVal*)
FnArgTypeAddr uint64 // address of the descriptor for the type of the function argument
FnPC uint64 // PC of finalizer entry point
}
// RawDefer represents a defer.
type RawDefer struct {
Addr uint64 // address of the defer record
GAddr uint64 // address of the containing goroutine's descriptor
ArgP uint64 // stack pointer giving the args for defer (TODO: is this right?)
PC uint64 // PC of the defer instruction
FnAddr uint64 // function to be run (a FuncVal*)
FnPC uint64 // PC of the defered function's entry point
LinkAddr uint64 // address of the next defer record in this chain
}
// RawPanic represents a panic.
type RawPanic struct {
Addr uint64 // address of the panic record
GAddr uint64 // address of the containing goroutine's descriptor
ArgTypeAddr uint64 // type of the panic arg
ArgAddr uint64 // address of the panic arg
DeferAddr uint64 // address of the defer record that is currently running
LinkAddr uint64 // address of the next panic record in this chain
}
// RawType repesents the Go runtime's representation of a type.
type RawType struct {
Addr uint64 // address of the type descriptor
Size uint64 // in bytes
Name string // not necessarily unique
// If true, this type is equivalent to a single pointer, so ifaces can store
// this type directly in the data field (without indirection).
DirectIFace bool
}
// RawMemProfEntry represents a memory profiler entry.
type RawMemProfEntry struct {
Size uint64 // size of the allocated object
NumAllocs uint64 // number of allocations
NumFrees uint64 // number of frees
Stacks []RawMemProfFrame // call stacks
}
// RawMemProfFrame represents a memory profiler frame.
type RawMemProfFrame struct {
Func []byte // string left as []byte reference to save memory
File []byte // string left as []byte reference to save memory
Line uint64
}
// RawAllocSample represents a memory profiler allocation sample.
type RawAllocSample struct {
Addr uint64 // address of object
Prof *RawMemProfEntry // record of allocation site
}
// Close closes the file.
func (r *RawDump) Close() error {
return r.fmap.Close()
}
// FindSegment returns the segment that contains the given address, or
// nil of no segment contains the address.
func (r *RawDump) FindSegment(addr uint64) *RawSegment {
// Binary search for an upper-bound heap object, then check
// if the previous object contains addr.
k := sort.Search(len(r.HeapObjects), func(k int) bool {
return addr < r.HeapObjects[k].Addr
})
k--
if k >= 0 && r.HeapObjects[k].Contains(addr) {
return &r.HeapObjects[k]
}
// Check all global segments.
for k := range r.GlobalSegments {
if r.GlobalSegments[k].Contains(addr) {
return &r.GlobalSegments[k]
}
}
// NB: Stack-local vars are technically allocated in the heap, since stack frames are
// allocated in the heap space, however, stack frames don't show up in r.HeapObjects.
for _, f := range r.StackFrames {
if f.Segment.Contains(addr) {
return &f.Segment
}
}
return nil
}
// Contains returns true if the segment contains the given address.
func (r RawSegment) Contains(addr uint64) bool {
return r.Addr <= addr && addr < r.Addr+r.Size()
}
// ContainsRange returns true if the segment contains the range [addr, addr+size).
func (r RawSegment) ContainsRange(addr, size uint64) bool {
if !r.Contains(addr) {
return false
}
if size > 0 && !r.Contains(addr+size-1) {
return false
}
return true
}
// Size returns the size of the segment in bytes.
func (r RawSegment) Size() uint64 {
return uint64(len(r.Data))
}
// Slice takes a slice of the given segment. Panics if [offset,offset+size)
// is out-of-bounds. The resulting RawSegment.PtrOffsets will clipped and
// translated into the new segment.
func (r RawSegment) Slice(offset, size uint64) *RawSegment {
if offset+size > uint64(len(r.Data)) {
panic(fmt.Errorf("slice(%d,%d) out-of-bounds of segment @%x sz=%d", offset, size, r.Addr, len(r.Data)))
}
return &RawSegment{
Addr: r.Addr + offset,
Data: r.Data[offset : offset+size : offset+size],
PtrFields: RawPtrFields{
encoded: r.PtrFields.encoded,
startOff: r.PtrFields.startOff + offset,
endOff: r.PtrFields.startOff + offset + size,
},
}
}
// Offsets decodes the list of ptr field offsets.
func (r RawPtrFields) Offsets() []uint64 {
if r.encoded == nil {
return nil
}
// NB: This should never fail since we already decoded the varints once
// when parsing the file originally. Hence we panic on failure.
reader := bytes.NewReader(r.encoded)
readUint64 := func() uint64 {
x, err := binary.ReadUvarint(reader)
if err != nil {
panic(fmt.Errorf("unexpected failure decoding uvarint: %v", err))
}
return x
}
var out []uint64
for {
k := readUint64()
switch k {
case 0: // end
return out
case 1: // ptr
x := readUint64()
if r.startOff <= x && x < r.endOff {
out = append(out, x-r.startOff)
}
default:
panic(fmt.Errorf("unexpected FieldKind %d", k))
}
}
}
// ReadPtr decodes a ptr from the given byte slice.
func (r *RawParams) ReadPtr(b []byte) uint64 {
switch r.PtrSize {
case 4:
return uint64(r.ByteOrder.Uint32(b))
case 8:
return r.ByteOrder.Uint64(b)
default:
panic(fmt.Errorf("unsupported PtrSize=%d", r.PtrSize))
}
}
// WritePtr encodes a ptr into the given byte slice.
func (r *RawParams) WritePtr(b []byte, addr uint64) {
switch r.PtrSize {
case 4:
r.ByteOrder.PutUint32(b, uint32(addr))
case 8:
r.ByteOrder.PutUint64(b, addr)
default:
panic(fmt.Errorf("unsupported PtrSize=%d", r.PtrSize))
}
}

View File

@ -1,83 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// heapview is a tool for viewing Go heap dumps.
package main
import (
"flag"
"fmt"
"go/build"
"io"
"log"
"net/http"
"os"
"path/filepath"
)
var host = flag.String("host", "", "host addr to listen on")
var port = flag.Int("port", 8080, "service port")
var index = `<!DOCTYPE html>
<script src="js/customelements.js"></script>
<script src="js/typescript.js"></script>
<script src="js/moduleloader.js"></script>
<script>
System.transpiler = 'typescript';
System.typescriptOptions = {target: ts.ScriptTarget.ES2015};
System.locate = (load) => load.name + '.ts';
</script>
<script type="module">
import {main} from './client/main';
main();
</script>
`
func toolsDir() string {
p, err := build.Import("golang.org/x/tools", "", build.FindOnly)
if err != nil {
log.Println("error: can't find client files:", err)
os.Exit(1)
}
return p.Dir
}
var parseFlags = func() {
flag.Parse()
}
var addHandlers = func() {
toolsDir := toolsDir()
// Directly serve typescript code in client directory for development.
http.Handle("/client/", http.StripPrefix("/client",
http.FileServer(http.Dir(filepath.Join(toolsDir, "cmd/heapview/client")))))
// Serve typescript.js and moduleloader.js for development.
http.HandleFunc("/js/typescript.js", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filepath.Join(toolsDir, "third_party/typescript/typescript.js"))
})
http.HandleFunc("/js/moduleloader.js", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filepath.Join(toolsDir, "third_party/moduleloader/moduleloader.js"))
})
http.HandleFunc("/js/customelements.js", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, filepath.Join(toolsDir, "third_party/webcomponents/customelements.js"))
})
// Serve index.html using html string above.
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html")
io.WriteString(w, index)
})
}
var listenAndServe = func() error {
return http.ListenAndServe(fmt.Sprintf("%s:%d", *host, *port), nil)
}
func main() {
parseFlags()
addHandlers()
log.Fatal(listenAndServe())
}