diff --git a/cmd/heapview/client/.clang-format b/cmd/heapview/client/.clang-format deleted file mode 100644 index f6cb8ad931..0000000000 --- a/cmd/heapview/client/.clang-format +++ /dev/null @@ -1 +0,0 @@ -BasedOnStyle: Google diff --git a/cmd/heapview/client/.gitignore b/cmd/heapview/client/.gitignore deleted file mode 100644 index 2ccbe4656c..0000000000 --- a/cmd/heapview/client/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/node_modules/ diff --git a/cmd/heapview/client/README.md b/cmd/heapview/client/README.md deleted file mode 100644 index 4cb26219db..0000000000 --- a/cmd/heapview/client/README.md +++ /dev/null @@ -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. \ No newline at end of file diff --git a/cmd/heapview/client/main.ts b/cmd/heapview/client/main.ts deleted file mode 100644 index fe3985c111..0000000000 --- a/cmd/heapview/client/main.ts +++ /dev/null @@ -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)); -} diff --git a/cmd/heapview/client/main_test.ts b/cmd/heapview/client/main_test.ts deleted file mode 100644 index a2086538e7..0000000000 --- a/cmd/heapview/client/main_test.ts +++ /dev/null @@ -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'); - }) -}); \ No newline at end of file diff --git a/cmd/heapview/client/package.json b/cmd/heapview/client/package.json deleted file mode 100644 index b2febe8890..0000000000 --- a/cmd/heapview/client/package.json +++ /dev/null @@ -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 ." - } -} diff --git a/cmd/heapview/client/testing/karma.conf.js b/cmd/heapview/client/testing/karma.conf.js deleted file mode 100644 index acaf9d5bc7..0000000000 --- a/cmd/heapview/client/testing/karma.conf.js +++ /dev/null @@ -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' - ], - }) -} \ No newline at end of file diff --git a/cmd/heapview/client/testing/test_main.js b/cmd/heapview/client/testing/test_main.js deleted file mode 100644 index 6c2afd7336..0000000000 --- a/cmd/heapview/client/testing/test_main.js +++ /dev/null @@ -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); \ No newline at end of file diff --git a/cmd/heapview/client/tsconfig.json b/cmd/heapview/client/tsconfig.json deleted file mode 100644 index 14c38a1b55..0000000000 --- a/cmd/heapview/client/tsconfig.json +++ /dev/null @@ -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" - } -} diff --git a/cmd/heapview/client/tslint.json b/cmd/heapview/client/tslint.json deleted file mode 100644 index a0f2d15d2f..0000000000 --- a/cmd/heapview/client/tslint.json +++ /dev/null @@ -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" - ] - } -} \ No newline at end of file diff --git a/cmd/heapview/internal/core/mmapfile.go b/cmd/heapview/internal/core/mmapfile.go deleted file mode 100644 index 78445a9ca8..0000000000 --- a/cmd/heapview/internal/core/mmapfile.go +++ /dev/null @@ -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 -} diff --git a/cmd/heapview/internal/core/mmapfile_other.go b/cmd/heapview/internal/core/mmapfile_other.go deleted file mode 100644 index 181f842067..0000000000 --- a/cmd/heapview/internal/core/mmapfile_other.go +++ /dev/null @@ -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 } diff --git a/cmd/heapview/internal/core/raw.go b/cmd/heapview/internal/core/raw.go deleted file mode 100644 index febed0f4dc..0000000000 --- a/cmd/heapview/internal/core/raw.go +++ /dev/null @@ -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)) - } -} diff --git a/cmd/heapview/main.go b/cmd/heapview/main.go deleted file mode 100644 index 6dac12e00e..0000000000 --- a/cmd/heapview/main.go +++ /dev/null @@ -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 = ` - - - - - -` - -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()) -}