mirror of https://github.com/lukechilds/node.git
Browse Source
This commit removes the simple/test-event-emitter-memory-leak test for being unreliable with the new garbage collector: the memory pressure exerted by the test case is too low for the garbage collector to kick in. It can be made to work again by limiting the heap size with the --max_old_space_size=x flag but that won't be very reliable across platforms and architectures.v0.11.9-release
474 changed files with 31104 additions and 26995 deletions
@ -0,0 +1,54 @@ |
|||||
|
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
|
// Redistribution and use in source and binary forms, with or without
|
||||
|
// modification, are permitted provided that the following conditions are
|
||||
|
// met:
|
||||
|
//
|
||||
|
// * Redistributions of source code must retain the above copyright
|
||||
|
// notice, this list of conditions and the following disclaimer.
|
||||
|
// * Redistributions in binary form must reproduce the above
|
||||
|
// copyright notice, this list of conditions and the following
|
||||
|
// disclaimer in the documentation and/or other materials provided
|
||||
|
// with the distribution.
|
||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||
|
// contributors may be used to endorse or promote products derived
|
||||
|
// from this software without specific prior written permission.
|
||||
|
//
|
||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
||||
|
#ifndef V8_V8_DEFAULTS_H_ |
||||
|
#define V8_V8_DEFAULTS_H_ |
||||
|
|
||||
|
#include "v8.h" |
||||
|
|
||||
|
/**
|
||||
|
* Default configuration support for the V8 JavaScript engine. |
||||
|
*/ |
||||
|
namespace v8 { |
||||
|
|
||||
|
/**
|
||||
|
* Configures the constraints with reasonable default values based on the |
||||
|
* capabilities of the current device the VM is running on. |
||||
|
*/ |
||||
|
bool V8_EXPORT ConfigureResourceConstraintsForCurrentPlatform( |
||||
|
ResourceConstraints* constraints); |
||||
|
|
||||
|
|
||||
|
/**
|
||||
|
* Convience function which performs SetResourceConstraints with the settings |
||||
|
* returned by ConfigureResourceConstraintsForCurrentPlatform. |
||||
|
*/ |
||||
|
bool V8_EXPORT SetDefaultResourceConstraintsForCurrentPlatform(); |
||||
|
|
||||
|
} // namespace v8
|
||||
|
|
||||
|
#endif // V8_V8_DEFAULTS_H_
|
@ -1,84 +0,0 @@ |
|||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#ifndef PREPARSER_H |
|
||||
#define PREPARSER_H |
|
||||
|
|
||||
#include "v8.h" |
|
||||
#include "v8stdint.h" |
|
||||
|
|
||||
namespace v8 { |
|
||||
|
|
||||
// The result of preparsing is either a stack overflow error, or an opaque
|
|
||||
// blob of data that can be passed back into the parser.
|
|
||||
class V8_EXPORT PreParserData { |
|
||||
public: |
|
||||
PreParserData(size_t size, const uint8_t* data) |
|
||||
: data_(data), size_(size) { } |
|
||||
|
|
||||
// Create a PreParserData value where stack_overflow reports true.
|
|
||||
static PreParserData StackOverflow() { return PreParserData(0, NULL); } |
|
||||
|
|
||||
// Whether the pre-parser stopped due to a stack overflow.
|
|
||||
// If this is the case, size() and data() should not be used.
|
|
||||
bool stack_overflow() { return size_ == 0u; } |
|
||||
|
|
||||
// The size of the data in bytes.
|
|
||||
size_t size() const { return size_; } |
|
||||
|
|
||||
// Pointer to the data.
|
|
||||
const uint8_t* data() const { return data_; } |
|
||||
|
|
||||
private: |
|
||||
const uint8_t* const data_; |
|
||||
const size_t size_; |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
// Interface for a stream of Unicode characters.
|
|
||||
class V8_EXPORT UnicodeInputStream { // NOLINT - V8_EXPORT is not a class name.
|
|
||||
public: |
|
||||
virtual ~UnicodeInputStream(); |
|
||||
|
|
||||
// Returns the next Unicode code-point in the input, or a negative value when
|
|
||||
// there is no more input in the stream.
|
|
||||
virtual int32_t Next() = 0; |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
// Preparse a JavaScript program. The source code is provided as a
|
|
||||
// UnicodeInputStream. The max_stack_size limits the amount of stack
|
|
||||
// space that the preparser is allowed to use. If the preparser uses
|
|
||||
// more stack space than the limit provided, the result's stack_overflow()
|
|
||||
// method will return true. Otherwise the result contains preparser
|
|
||||
// data that can be used by the V8 parser to speed up parsing.
|
|
||||
PreParserData V8_EXPORT Preparse(UnicodeInputStream* input, |
|
||||
size_t max_stack_size); |
|
||||
|
|
||||
} // namespace v8.
|
|
||||
|
|
||||
#endif // PREPARSER_H
|
|
@ -1,372 +0,0 @@ |
|||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
|
||||
// Redistribution and use in source and binary forms, with or without
|
|
||||
// modification, are permitted provided that the following conditions are
|
|
||||
// met:
|
|
||||
//
|
|
||||
// * Redistributions of source code must retain the above copyright
|
|
||||
// notice, this list of conditions and the following disclaimer.
|
|
||||
// * Redistributions in binary form must reproduce the above
|
|
||||
// copyright notice, this list of conditions and the following
|
|
||||
// disclaimer in the documentation and/or other materials provided
|
|
||||
// with the distribution.
|
|
||||
// * Neither the name of Google Inc. nor the names of its
|
|
||||
// contributors may be used to endorse or promote products derived
|
|
||||
// from this software without specific prior written permission.
|
|
||||
//
|
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||
|
|
||||
#include <stdlib.h> |
|
||||
#include <stdarg.h> |
|
||||
#include <stdio.h> |
|
||||
#include <string.h> |
|
||||
|
|
||||
#include "../include/v8.h" |
|
||||
#include "../include/v8stdint.h" |
|
||||
#include "../include/v8-preparser.h" |
|
||||
|
|
||||
#include "../src/preparse-data-format.h" |
|
||||
|
|
||||
namespace i = v8::internal; |
|
||||
|
|
||||
// This file is only used for testing the preparser.
|
|
||||
// The first argument must be the path of a JavaScript source file, or
|
|
||||
// the flags "-e" and the next argument is then the source of a JavaScript
|
|
||||
// program.
|
|
||||
// Optionally this can be followed by the word "throws" (case sensitive),
|
|
||||
// which signals that the parsing is expected to throw - the default is
|
|
||||
// to expect the parsing to not throw.
|
|
||||
// The command line can further be followed by a message text (the
|
|
||||
// *type* of the exception to throw), and even more optionally, the
|
|
||||
// start and end position reported with the exception.
|
|
||||
//
|
|
||||
// This source file is preparsed and tested against the expectations, and if
|
|
||||
// successful, the resulting preparser data is written to stdout.
|
|
||||
// Diagnostic output is output on stderr.
|
|
||||
// The source file must contain only ASCII characters (UTF-8 isn't supported).
|
|
||||
// The file is read into memory, so it should have a reasonable size.
|
|
||||
|
|
||||
|
|
||||
// Adapts an ASCII string to the UnicodeInputStream interface.
|
|
||||
class AsciiInputStream : public v8::UnicodeInputStream { |
|
||||
public: |
|
||||
AsciiInputStream(const uint8_t* buffer, size_t length) |
|
||||
: buffer_(buffer), |
|
||||
end_offset_(static_cast<int>(length)), |
|
||||
offset_(0) { } |
|
||||
|
|
||||
virtual ~AsciiInputStream() { } |
|
||||
|
|
||||
virtual void PushBack(int32_t ch) { |
|
||||
offset_--; |
|
||||
#ifdef DEBUG |
|
||||
if (offset_ < 0 || |
|
||||
(ch != ((offset_ >= end_offset_) ? -1 : buffer_[offset_]))) { |
|
||||
fprintf(stderr, "Invalid pushback: '%c' at offset %d.", ch, offset_); |
|
||||
exit(1); |
|
||||
} |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
virtual int32_t Next() { |
|
||||
if (offset_ >= end_offset_) { |
|
||||
offset_++; // Increment anyway to allow symmetric pushbacks.
|
|
||||
return -1; |
|
||||
} |
|
||||
uint8_t next_char = buffer_[offset_]; |
|
||||
#ifdef DEBUG |
|
||||
if (next_char > 0x7fu) { |
|
||||
fprintf(stderr, "Non-ASCII character in input: '%c'.", next_char); |
|
||||
exit(1); |
|
||||
} |
|
||||
#endif |
|
||||
offset_++; |
|
||||
return static_cast<int32_t>(next_char); |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
const uint8_t* buffer_; |
|
||||
const int end_offset_; |
|
||||
int offset_; |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
bool ReadBuffer(FILE* source, void* buffer, size_t length) { |
|
||||
size_t actually_read = fread(buffer, 1, length, source); |
|
||||
return (actually_read == length); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
bool WriteBuffer(FILE* dest, const void* buffer, size_t length) { |
|
||||
size_t actually_written = fwrite(buffer, 1, length, dest); |
|
||||
return (actually_written == length); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
class PreparseDataInterpreter { |
|
||||
public: |
|
||||
PreparseDataInterpreter(const uint8_t* data, int length) |
|
||||
: data_(data), length_(length), message_(NULL) { } |
|
||||
|
|
||||
~PreparseDataInterpreter() { |
|
||||
if (message_ != NULL) delete[] message_; |
|
||||
} |
|
||||
|
|
||||
bool valid() { |
|
||||
int header_length = |
|
||||
i::PreparseDataConstants::kHeaderSize * sizeof(int); // NOLINT
|
|
||||
return length_ >= header_length; |
|
||||
} |
|
||||
|
|
||||
bool throws() { |
|
||||
return valid() && |
|
||||
word(i::PreparseDataConstants::kHasErrorOffset) != 0; |
|
||||
} |
|
||||
|
|
||||
const char* message() { |
|
||||
if (message_ != NULL) return message_; |
|
||||
if (!throws()) return NULL; |
|
||||
int text_pos = i::PreparseDataConstants::kHeaderSize + |
|
||||
i::PreparseDataConstants::kMessageTextPos; |
|
||||
int length = word(text_pos); |
|
||||
char* buffer = new char[length + 1]; |
|
||||
for (int i = 1; i <= length; i++) { |
|
||||
int character = word(text_pos + i); |
|
||||
buffer[i - 1] = character; |
|
||||
} |
|
||||
buffer[length] = '\0'; |
|
||||
message_ = buffer; |
|
||||
return buffer; |
|
||||
} |
|
||||
|
|
||||
int beg_pos() { |
|
||||
if (!throws()) return -1; |
|
||||
return word(i::PreparseDataConstants::kHeaderSize + |
|
||||
i::PreparseDataConstants::kMessageStartPos); |
|
||||
} |
|
||||
|
|
||||
int end_pos() { |
|
||||
if (!throws()) return -1; |
|
||||
return word(i::PreparseDataConstants::kHeaderSize + |
|
||||
i::PreparseDataConstants::kMessageEndPos); |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
int word(int offset) { |
|
||||
const int* word_data = reinterpret_cast<const int*>(data_); |
|
||||
if (word_data + offset < reinterpret_cast<const int*>(data_ + length_)) { |
|
||||
return word_data[offset]; |
|
||||
} |
|
||||
return -1; |
|
||||
} |
|
||||
|
|
||||
const uint8_t* const data_; |
|
||||
const int length_; |
|
||||
const char* message_; |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
template <typename T> |
|
||||
class ScopedPointer { |
|
||||
public: |
|
||||
explicit ScopedPointer() : pointer_(NULL) {} |
|
||||
explicit ScopedPointer(T* pointer) : pointer_(pointer) {} |
|
||||
~ScopedPointer() { if (pointer_ != NULL) delete[] pointer_; } |
|
||||
T& operator[](int index) { return pointer_[index]; } |
|
||||
T* operator*() { return pointer_ ;} |
|
||||
T* operator=(T* new_value) { |
|
||||
if (pointer_ != NULL) delete[] pointer_; |
|
||||
pointer_ = new_value; |
|
||||
return new_value; |
|
||||
} |
|
||||
private: |
|
||||
T* pointer_; |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
|
|
||||
void fail(v8::PreParserData* data, const char* message, ...) { |
|
||||
va_list args; |
|
||||
va_start(args, message); |
|
||||
vfprintf(stderr, message, args); |
|
||||
va_end(args); |
|
||||
fflush(stderr); |
|
||||
if (data != NULL) { |
|
||||
// Print preparser data to stdout.
|
|
||||
uint32_t size = static_cast<uint32_t>(data->size()); |
|
||||
fprintf(stderr, "LOG: data size: %u\n", size); |
|
||||
if (!WriteBuffer(stdout, data->data(), size)) { |
|
||||
perror("ERROR: Writing data"); |
|
||||
fflush(stderr); |
|
||||
} |
|
||||
} |
|
||||
exit(EXIT_FAILURE); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
bool IsFlag(const char* arg) { |
|
||||
// Anything starting with '-' is considered a flag.
|
|
||||
// It's summarily ignored for now.
|
|
||||
return arg[0] == '-'; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
struct ExceptionExpectation { |
|
||||
ExceptionExpectation() |
|
||||
: throws(false), type(NULL), beg_pos(-1), end_pos(-1) { } |
|
||||
bool throws; |
|
||||
const char* type; |
|
||||
int beg_pos; |
|
||||
int end_pos; |
|
||||
}; |
|
||||
|
|
||||
|
|
||||
void CheckException(v8::PreParserData* data, |
|
||||
ExceptionExpectation* expects) { |
|
||||
PreparseDataInterpreter reader(data->data(), static_cast<int>(data->size())); |
|
||||
if (expects->throws) { |
|
||||
if (!reader.throws()) { |
|
||||
if (expects->type == NULL) { |
|
||||
fail(data, "Didn't throw as expected\n"); |
|
||||
} else { |
|
||||
fail(data, "Didn't throw \"%s\" as expected\n", expects->type); |
|
||||
} |
|
||||
} |
|
||||
if (expects->type != NULL) { |
|
||||
const char* actual_message = reader.message(); |
|
||||
if (strcmp(expects->type, actual_message)) { |
|
||||
fail(data, "Wrong error message. Expected <%s>, found <%s> at %d..%d\n", |
|
||||
expects->type, actual_message, reader.beg_pos(), reader.end_pos()); |
|
||||
} |
|
||||
} |
|
||||
if (expects->beg_pos >= 0) { |
|
||||
if (expects->beg_pos != reader.beg_pos()) { |
|
||||
fail(data, "Wrong error start position: Expected %i, found %i\n", |
|
||||
expects->beg_pos, reader.beg_pos()); |
|
||||
} |
|
||||
} |
|
||||
if (expects->end_pos >= 0) { |
|
||||
if (expects->end_pos != reader.end_pos()) { |
|
||||
fail(data, "Wrong error end position: Expected %i, found %i\n", |
|
||||
expects->end_pos, reader.end_pos()); |
|
||||
} |
|
||||
} |
|
||||
} else if (reader.throws()) { |
|
||||
const char* message = reader.message(); |
|
||||
fail(data, "Throws unexpectedly with message: %s at location %d-%d\n", |
|
||||
message, reader.beg_pos(), reader.end_pos()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
ExceptionExpectation ParseExpectation(int argc, const char* argv[]) { |
|
||||
// Parse ["throws" [<exn-type> [<start> [<end>]]]].
|
|
||||
ExceptionExpectation expects; |
|
||||
int arg_index = 0; |
|
||||
while (argc > arg_index && strncmp("throws", argv[arg_index], 7)) { |
|
||||
arg_index++; |
|
||||
} |
|
||||
if (argc > arg_index) { |
|
||||
expects.throws = true; |
|
||||
arg_index++; |
|
||||
if (argc > arg_index && !IsFlag(argv[arg_index])) { |
|
||||
expects.type = argv[arg_index]; |
|
||||
arg_index++; |
|
||||
if (argc > arg_index && !IsFlag(argv[arg_index])) { |
|
||||
expects.beg_pos = atoi(argv[arg_index]); // NOLINT
|
|
||||
arg_index++; |
|
||||
if (argc > arg_index && !IsFlag(argv[arg_index])) { |
|
||||
expects.end_pos = atoi(argv[arg_index]); // NOLINT
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
return expects; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
int main(int argc, const char* argv[]) { |
|
||||
// Parse command line.
|
|
||||
// Format: preparser (<scriptfile> | -e "<source>")
|
|
||||
// ["throws" [<exn-type> [<start> [<end>]]]]
|
|
||||
// Any flags (except an initial -e) are ignored.
|
|
||||
// Flags must not separate "throws" and its arguments.
|
|
||||
|
|
||||
// Check for mandatory filename argument.
|
|
||||
int arg_index = 1; |
|
||||
if (argc <= arg_index) { |
|
||||
fail(NULL, "ERROR: No filename on command line.\n"); |
|
||||
} |
|
||||
const uint8_t* source = NULL; |
|
||||
const char* filename = argv[arg_index]; |
|
||||
if (!strcmp(filename, "-e")) { |
|
||||
arg_index++; |
|
||||
if (argc <= arg_index) { |
|
||||
fail(NULL, "ERROR: No source after -e on command line.\n"); |
|
||||
} |
|
||||
source = reinterpret_cast<const uint8_t*>(argv[arg_index]); |
|
||||
} |
|
||||
// Check remainder of command line for exception expectations.
|
|
||||
arg_index++; |
|
||||
ExceptionExpectation expects = |
|
||||
ParseExpectation(argc - arg_index, argv + arg_index); |
|
||||
|
|
||||
v8::V8::Initialize(); |
|
||||
|
|
||||
ScopedPointer<uint8_t> buffer; |
|
||||
size_t length; |
|
||||
|
|
||||
if (source == NULL) { |
|
||||
// Open JS file.
|
|
||||
FILE* input = fopen(filename, "rb"); |
|
||||
if (input == NULL) { |
|
||||
perror("ERROR: Error opening file"); |
|
||||
fflush(stderr); |
|
||||
return EXIT_FAILURE; |
|
||||
} |
|
||||
// Find length of JS file.
|
|
||||
if (fseek(input, 0, SEEK_END) != 0) { |
|
||||
perror("ERROR: Error during seek"); |
|
||||
fflush(stderr); |
|
||||
return EXIT_FAILURE; |
|
||||
} |
|
||||
length = static_cast<size_t>(ftell(input)); |
|
||||
rewind(input); |
|
||||
// Read JS file into memory buffer.
|
|
||||
buffer = new uint8_t[length]; |
|
||||
if (!ReadBuffer(input, *buffer, length)) { |
|
||||
perror("ERROR: Reading file"); |
|
||||
fflush(stderr); |
|
||||
return EXIT_FAILURE; |
|
||||
} |
|
||||
fclose(input); |
|
||||
source = *buffer; |
|
||||
} else { |
|
||||
length = strlen(reinterpret_cast<const char*>(source)); |
|
||||
} |
|
||||
|
|
||||
// Preparse input file.
|
|
||||
AsciiInputStream input_buffer(source, length); |
|
||||
size_t kMaxStackSize = 64 * 1024 * sizeof(void*); // NOLINT
|
|
||||
v8::PreParserData data = v8::Preparse(&input_buffer, kMaxStackSize); |
|
||||
|
|
||||
// Fail if stack overflow.
|
|
||||
if (data.stack_overflow()) { |
|
||||
fail(&data, "ERROR: Stack overflow\n"); |
|
||||
} |
|
||||
|
|
||||
// Check that the expected exception is thrown, if an exception is
|
|
||||
// expected.
|
|
||||
CheckException(&data, &expects); |
|
||||
|
|
||||
return EXIT_SUCCESS; |
|
||||
} |
|
@ -1,58 +0,0 @@ |
|||||
# Copyright 2011 the V8 project authors. All rights reserved. |
|
||||
# Redistribution and use in source and binary forms, with or without |
|
||||
# modification, are permitted provided that the following conditions are |
|
||||
# met: |
|
||||
# |
|
||||
# * Redistributions of source code must retain the above copyright |
|
||||
# notice, this list of conditions and the following disclaimer. |
|
||||
# * Redistributions in binary form must reproduce the above |
|
||||
# copyright notice, this list of conditions and the following |
|
||||
# disclaimer in the documentation and/or other materials provided |
|
||||
# with the distribution. |
|
||||
# * Neither the name of Google Inc. nor the names of its |
|
||||
# contributors may be used to endorse or promote products derived |
|
||||
# from this software without specific prior written permission. |
|
||||
# |
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
||||
|
|
||||
{ |
|
||||
'variables': { |
|
||||
'v8_code': 1, |
|
||||
}, |
|
||||
'includes': ['../build/toolchain.gypi', '../build/features.gypi'], |
|
||||
'targets': [ |
|
||||
{ |
|
||||
'target_name': 'preparser', |
|
||||
'type': 'executable', |
|
||||
'conditions': [ |
|
||||
# preparser can't link against a shared library, so link against |
|
||||
# the underlying static targets. |
|
||||
['v8_use_snapshot=="true"', { |
|
||||
'dependencies': ['../tools/gyp/v8.gyp:v8_snapshot'], |
|
||||
}, { |
|
||||
'dependencies': [ |
|
||||
'../tools/gyp/v8.gyp:v8_nosnapshot.<(v8_target_arch)', |
|
||||
], |
|
||||
}], |
|
||||
], |
|
||||
'include_dirs+': [ |
|
||||
'../src', |
|
||||
], |
|
||||
'sources': [ |
|
||||
'preparser-process.cc', |
|
||||
'../include/v8-preparser.h', |
|
||||
'../src/preparser-api.cc', |
|
||||
], |
|
||||
}, |
|
||||
], |
|
||||
} |
|
@ -0,0 +1,2 @@ |
|||||
|
per-file i18n.*=cira@chromium.org |
||||
|
per-file i18n.*=mnita@google.com |
@ -0,0 +1,108 @@ |
|||||
|
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
|
// Redistribution and use in source and binary forms, with or without
|
||||
|
// modification, are permitted provided that the following conditions are
|
||||
|
// met:
|
||||
|
//
|
||||
|
// * Redistributions of source code must retain the above copyright
|
||||
|
// notice, this list of conditions and the following disclaimer.
|
||||
|
// * Redistributions in binary form must reproduce the above
|
||||
|
// copyright notice, this list of conditions and the following
|
||||
|
// disclaimer in the documentation and/or other materials provided
|
||||
|
// with the distribution.
|
||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||
|
// contributors may be used to endorse or promote products derived
|
||||
|
// from this software without specific prior written permission.
|
||||
|
//
|
||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
||||
|
#include "allocation-site-scopes.h" |
||||
|
|
||||
|
namespace v8 { |
||||
|
namespace internal { |
||||
|
|
||||
|
|
||||
|
Handle<AllocationSite> AllocationSiteCreationContext::EnterNewScope() { |
||||
|
Handle<AllocationSite> scope_site; |
||||
|
if (top().is_null()) { |
||||
|
// We are creating the top level AllocationSite as opposed to a nested
|
||||
|
// AllocationSite.
|
||||
|
InitializeTraversal(isolate()->factory()->NewAllocationSite()); |
||||
|
scope_site = Handle<AllocationSite>(*top(), isolate()); |
||||
|
if (FLAG_trace_creation_allocation_sites) { |
||||
|
PrintF("*** Creating top level AllocationSite %p\n", |
||||
|
static_cast<void*>(*scope_site)); |
||||
|
} |
||||
|
} else { |
||||
|
ASSERT(!current().is_null()); |
||||
|
scope_site = isolate()->factory()->NewAllocationSite(); |
||||
|
if (FLAG_trace_creation_allocation_sites) { |
||||
|
PrintF("Creating nested site (top, current, new) (%p, %p, %p)\n", |
||||
|
static_cast<void*>(*top()), |
||||
|
static_cast<void*>(*current()), |
||||
|
static_cast<void*>(*scope_site)); |
||||
|
} |
||||
|
current()->set_nested_site(*scope_site); |
||||
|
update_current_site(*scope_site); |
||||
|
} |
||||
|
ASSERT(!scope_site.is_null()); |
||||
|
return scope_site; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationSiteCreationContext::ExitScope( |
||||
|
Handle<AllocationSite> scope_site, |
||||
|
Handle<JSObject> object) { |
||||
|
if (!object.is_null() && !object->IsFailure()) { |
||||
|
bool top_level = !scope_site.is_null() && |
||||
|
top().is_identical_to(scope_site); |
||||
|
|
||||
|
scope_site->set_transition_info(*object); |
||||
|
if (FLAG_trace_creation_allocation_sites) { |
||||
|
if (top_level) { |
||||
|
PrintF("*** Setting AllocationSite %p transition_info %p\n", |
||||
|
static_cast<void*>(*scope_site), |
||||
|
static_cast<void*>(*object)); |
||||
|
} else { |
||||
|
PrintF("Setting AllocationSite (%p, %p) transition_info %p\n", |
||||
|
static_cast<void*>(*top()), |
||||
|
static_cast<void*>(*scope_site), |
||||
|
static_cast<void*>(*object)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
Handle<AllocationSite> AllocationSiteUsageContext::EnterNewScope() { |
||||
|
if (top().is_null()) { |
||||
|
InitializeTraversal(top_site_); |
||||
|
} else { |
||||
|
// Advance current site
|
||||
|
Object* nested_site = current()->nested_site(); |
||||
|
// Something is wrong if we advance to the end of the list here.
|
||||
|
ASSERT(nested_site->IsAllocationSite()); |
||||
|
update_current_site(AllocationSite::cast(nested_site)); |
||||
|
} |
||||
|
return Handle<AllocationSite>(*current(), isolate()); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationSiteUsageContext::ExitScope( |
||||
|
Handle<AllocationSite> scope_site, |
||||
|
Handle<JSObject> object) { |
||||
|
// This assert ensures that we are pointing at the right sub-object in a
|
||||
|
// recursive walk of a nested literal.
|
||||
|
ASSERT(object.is_null() || *object == scope_site->transition_info()); |
||||
|
} |
||||
|
|
||||
|
} } // namespace v8::internal
|
@ -0,0 +1,115 @@ |
|||||
|
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
|
// Redistribution and use in source and binary forms, with or without
|
||||
|
// modification, are permitted provided that the following conditions are
|
||||
|
// met:
|
||||
|
//
|
||||
|
// * Redistributions of source code must retain the above copyright
|
||||
|
// notice, this list of conditions and the following disclaimer.
|
||||
|
// * Redistributions in binary form must reproduce the above
|
||||
|
// copyright notice, this list of conditions and the following
|
||||
|
// disclaimer in the documentation and/or other materials provided
|
||||
|
// with the distribution.
|
||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||
|
// contributors may be used to endorse or promote products derived
|
||||
|
// from this software without specific prior written permission.
|
||||
|
//
|
||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
||||
|
#ifndef V8_ALLOCATION_SITE_SCOPES_H_ |
||||
|
#define V8_ALLOCATION_SITE_SCOPES_H_ |
||||
|
|
||||
|
#include "ast.h" |
||||
|
#include "handles.h" |
||||
|
#include "objects.h" |
||||
|
#include "zone.h" |
||||
|
|
||||
|
namespace v8 { |
||||
|
namespace internal { |
||||
|
|
||||
|
|
||||
|
// AllocationSiteContext is the base class for walking and copying a nested
|
||||
|
// boilerplate with AllocationSite and AllocationMemento support.
|
||||
|
class AllocationSiteContext { |
||||
|
public: |
||||
|
AllocationSiteContext(Isolate* isolate, bool activated) { |
||||
|
isolate_ = isolate; |
||||
|
activated_ = activated; |
||||
|
}; |
||||
|
virtual ~AllocationSiteContext() {} |
||||
|
|
||||
|
Handle<AllocationSite> top() { return top_; } |
||||
|
Handle<AllocationSite> current() { return current_; } |
||||
|
|
||||
|
// If activated, then recursively create mementos
|
||||
|
bool activated() const { return activated_; } |
||||
|
|
||||
|
// Returns the AllocationSite that matches this scope.
|
||||
|
virtual Handle<AllocationSite> EnterNewScope() = 0; |
||||
|
|
||||
|
// scope_site should be the handle returned by the matching EnterNewScope()
|
||||
|
virtual void ExitScope(Handle<AllocationSite> scope_site, |
||||
|
Handle<JSObject> object) = 0; |
||||
|
|
||||
|
protected: |
||||
|
void update_current_site(AllocationSite* site) { |
||||
|
*(current_.location()) = site; |
||||
|
} |
||||
|
|
||||
|
Isolate* isolate() { return isolate_; } |
||||
|
void InitializeTraversal(Handle<AllocationSite> site) { |
||||
|
top_ = site; |
||||
|
current_ = Handle<AllocationSite>(*top_, isolate()); |
||||
|
} |
||||
|
|
||||
|
private: |
||||
|
Isolate* isolate_; |
||||
|
Handle<AllocationSite> top_; |
||||
|
Handle<AllocationSite> current_; |
||||
|
bool activated_; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// AllocationSiteCreationContext aids in the creation of AllocationSites to
|
||||
|
// accompany object literals.
|
||||
|
class AllocationSiteCreationContext : public AllocationSiteContext { |
||||
|
public: |
||||
|
explicit AllocationSiteCreationContext(Isolate* isolate) |
||||
|
: AllocationSiteContext(isolate, true) { } |
||||
|
|
||||
|
virtual Handle<AllocationSite> EnterNewScope() V8_OVERRIDE; |
||||
|
virtual void ExitScope(Handle<AllocationSite> site, |
||||
|
Handle<JSObject> object) V8_OVERRIDE; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
// AllocationSiteUsageContext aids in the creation of AllocationMementos placed
|
||||
|
// behind some/all components of a copied object literal.
|
||||
|
class AllocationSiteUsageContext : public AllocationSiteContext { |
||||
|
public: |
||||
|
AllocationSiteUsageContext(Isolate* isolate, Handle<AllocationSite> site, |
||||
|
bool activated) |
||||
|
: AllocationSiteContext(isolate, activated), |
||||
|
top_site_(site) { } |
||||
|
|
||||
|
virtual Handle<AllocationSite> EnterNewScope() V8_OVERRIDE; |
||||
|
virtual void ExitScope(Handle<AllocationSite> site, |
||||
|
Handle<JSObject> object) V8_OVERRIDE; |
||||
|
|
||||
|
private: |
||||
|
Handle<AllocationSite> top_site_; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
} } // namespace v8::internal
|
||||
|
|
||||
|
#endif // V8_ALLOCATION_SITE_SCOPES_H_
|
@ -0,0 +1,279 @@ |
|||||
|
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
|
// Redistribution and use in source and binary forms, with or without
|
||||
|
// modification, are permitted provided that the following conditions are
|
||||
|
// met:
|
||||
|
//
|
||||
|
// * Redistributions of source code must retain the above copyright
|
||||
|
// notice, this list of conditions and the following disclaimer.
|
||||
|
// * Redistributions in binary form must reproduce the above
|
||||
|
// copyright notice, this list of conditions and the following
|
||||
|
// disclaimer in the documentation and/or other materials provided
|
||||
|
// with the distribution.
|
||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||
|
// contributors may be used to endorse or promote products derived
|
||||
|
// from this software without specific prior written permission.
|
||||
|
//
|
||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
||||
|
#include "v8.h" |
||||
|
|
||||
|
#include "allocation-tracker.h" |
||||
|
|
||||
|
#include "heap-snapshot-generator.h" |
||||
|
#include "frames-inl.h" |
||||
|
|
||||
|
namespace v8 { |
||||
|
namespace internal { |
||||
|
|
||||
|
AllocationTraceNode::AllocationTraceNode( |
||||
|
AllocationTraceTree* tree, SnapshotObjectId shared_function_info_id) |
||||
|
: tree_(tree), |
||||
|
function_id_(shared_function_info_id), |
||||
|
total_size_(0), |
||||
|
allocation_count_(0), |
||||
|
id_(tree->next_node_id()) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTraceNode::~AllocationTraceNode() { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTraceNode* AllocationTraceNode::FindChild(SnapshotObjectId id) { |
||||
|
for (int i = 0; i < children_.length(); i++) { |
||||
|
AllocationTraceNode* node = children_[i]; |
||||
|
if (node->function_id() == id) return node; |
||||
|
} |
||||
|
return NULL; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTraceNode* AllocationTraceNode::FindOrAddChild(SnapshotObjectId id) { |
||||
|
AllocationTraceNode* child = FindChild(id); |
||||
|
if (child == NULL) { |
||||
|
child = new AllocationTraceNode(tree_, id); |
||||
|
children_.Add(child); |
||||
|
} |
||||
|
return child; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationTraceNode::AddAllocation(unsigned size) { |
||||
|
total_size_ += size; |
||||
|
++allocation_count_; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationTraceNode::Print(int indent, AllocationTracker* tracker) { |
||||
|
OS::Print("%10u %10u %*c", total_size_, allocation_count_, indent, ' '); |
||||
|
if (tracker != NULL) { |
||||
|
const char* name = "<unknown function>"; |
||||
|
if (function_id_ != 0) { |
||||
|
AllocationTracker::FunctionInfo* info = |
||||
|
tracker->GetFunctionInfo(function_id_); |
||||
|
if (info != NULL) { |
||||
|
name = info->name; |
||||
|
} |
||||
|
} |
||||
|
OS::Print("%s #%u", name, id_); |
||||
|
} else { |
||||
|
OS::Print("%u #%u", function_id_, id_); |
||||
|
} |
||||
|
OS::Print("\n"); |
||||
|
indent += 2; |
||||
|
for (int i = 0; i < children_.length(); i++) { |
||||
|
children_[i]->Print(indent, tracker); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTraceTree::AllocationTraceTree() |
||||
|
: next_node_id_(1), |
||||
|
root_(this, 0) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTraceTree::~AllocationTraceTree() { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTraceNode* AllocationTraceTree::AddPathFromEnd( |
||||
|
const Vector<SnapshotObjectId>& path) { |
||||
|
AllocationTraceNode* node = root(); |
||||
|
for (SnapshotObjectId* entry = path.start() + path.length() - 1; |
||||
|
entry != path.start() - 1; |
||||
|
--entry) { |
||||
|
node = node->FindOrAddChild(*entry); |
||||
|
} |
||||
|
return node; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationTraceTree::Print(AllocationTracker* tracker) { |
||||
|
OS::Print("[AllocationTraceTree:]\n"); |
||||
|
OS::Print("Total size | Allocation count | Function id | id\n"); |
||||
|
root()->Print(0, tracker); |
||||
|
} |
||||
|
|
||||
|
void AllocationTracker::DeleteUnresolvedLocation( |
||||
|
UnresolvedLocation** location) { |
||||
|
delete *location; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTracker::FunctionInfo::FunctionInfo() |
||||
|
: name(""), |
||||
|
script_name(""), |
||||
|
script_id(0), |
||||
|
line(-1), |
||||
|
column(-1) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static bool AddressesMatch(void* key1, void* key2) { |
||||
|
return key1 == key2; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTracker::AllocationTracker( |
||||
|
HeapObjectsMap* ids, StringsStorage* names) |
||||
|
: ids_(ids), |
||||
|
names_(names), |
||||
|
id_to_function_info_(AddressesMatch) { |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTracker::~AllocationTracker() { |
||||
|
unresolved_locations_.Iterate(DeleteUnresolvedLocation); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationTracker::PrepareForSerialization() { |
||||
|
List<UnresolvedLocation*> copy(unresolved_locations_.length()); |
||||
|
copy.AddAll(unresolved_locations_); |
||||
|
unresolved_locations_.Clear(); |
||||
|
for (int i = 0; i < copy.length(); i++) { |
||||
|
copy[i]->Resolve(); |
||||
|
delete copy[i]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationTracker::NewObjectEvent(Address addr, int size) { |
||||
|
DisallowHeapAllocation no_allocation; |
||||
|
Heap* heap = ids_->heap(); |
||||
|
|
||||
|
// Mark the new block as FreeSpace to make sure the heap is iterable
|
||||
|
// while we are capturing stack trace.
|
||||
|
FreeListNode::FromAddress(addr)->set_size(heap, size); |
||||
|
ASSERT_EQ(HeapObject::FromAddress(addr)->Size(), size); |
||||
|
ASSERT(FreeListNode::IsFreeListNode(HeapObject::FromAddress(addr))); |
||||
|
|
||||
|
Isolate* isolate = heap->isolate(); |
||||
|
int length = 0; |
||||
|
StackTraceFrameIterator it(isolate); |
||||
|
while (!it.done() && length < kMaxAllocationTraceLength) { |
||||
|
JavaScriptFrame* frame = it.frame(); |
||||
|
SharedFunctionInfo* shared = frame->function()->shared(); |
||||
|
SnapshotObjectId id = ids_->FindEntry(shared->address()); |
||||
|
allocation_trace_buffer_[length++] = id; |
||||
|
AddFunctionInfo(shared, id); |
||||
|
it.Advance(); |
||||
|
} |
||||
|
AllocationTraceNode* top_node = trace_tree_.AddPathFromEnd( |
||||
|
Vector<SnapshotObjectId>(allocation_trace_buffer_, length)); |
||||
|
top_node->AddAllocation(size); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
static uint32_t SnapshotObjectIdHash(SnapshotObjectId id) { |
||||
|
return ComputeIntegerHash(static_cast<uint32_t>(id), |
||||
|
v8::internal::kZeroHashSeed); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTracker::FunctionInfo* AllocationTracker::GetFunctionInfo( |
||||
|
SnapshotObjectId id) { |
||||
|
HashMap::Entry* entry = id_to_function_info_.Lookup( |
||||
|
reinterpret_cast<void*>(id), SnapshotObjectIdHash(id), false); |
||||
|
if (entry == NULL) { |
||||
|
return NULL; |
||||
|
} |
||||
|
return reinterpret_cast<FunctionInfo*>(entry->value); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationTracker::AddFunctionInfo(SharedFunctionInfo* shared, |
||||
|
SnapshotObjectId id) { |
||||
|
HashMap::Entry* entry = id_to_function_info_.Lookup( |
||||
|
reinterpret_cast<void*>(id), SnapshotObjectIdHash(id), true); |
||||
|
if (entry->value == NULL) { |
||||
|
FunctionInfo* info = new FunctionInfo(); |
||||
|
info->name = names_->GetFunctionName(shared->DebugName()); |
||||
|
if (shared->script()->IsScript()) { |
||||
|
Script* script = Script::cast(shared->script()); |
||||
|
if (script->name()->IsName()) { |
||||
|
Name* name = Name::cast(script->name()); |
||||
|
info->script_name = names_->GetName(name); |
||||
|
} |
||||
|
info->script_id = script->id()->value(); |
||||
|
// Converting start offset into line and column may cause heap
|
||||
|
// allocations so we postpone them until snapshot serialization.
|
||||
|
unresolved_locations_.Add(new UnresolvedLocation( |
||||
|
script, |
||||
|
shared->start_position(), |
||||
|
info)); |
||||
|
} |
||||
|
entry->value = info; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTracker::UnresolvedLocation::UnresolvedLocation( |
||||
|
Script* script, int start, FunctionInfo* info) |
||||
|
: start_position_(start), |
||||
|
info_(info) { |
||||
|
script_ = Handle<Script>::cast( |
||||
|
script->GetIsolate()->global_handles()->Create(script)); |
||||
|
GlobalHandles::MakeWeak( |
||||
|
reinterpret_cast<Object**>(script_.location()), |
||||
|
this, &HandleWeakScript); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
AllocationTracker::UnresolvedLocation::~UnresolvedLocation() { |
||||
|
if (!script_.is_null()) { |
||||
|
script_->GetIsolate()->global_handles()->Destroy( |
||||
|
reinterpret_cast<Object**>(script_.location())); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationTracker::UnresolvedLocation::Resolve() { |
||||
|
if (script_.is_null()) return; |
||||
|
info_->line = GetScriptLineNumber(script_, start_position_); |
||||
|
info_->column = GetScriptColumnNumber(script_, start_position_); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void AllocationTracker::UnresolvedLocation::HandleWeakScript( |
||||
|
v8::Isolate* isolate, |
||||
|
v8::Persistent<v8::Value>* obj, |
||||
|
void* data) { |
||||
|
UnresolvedLocation* location = reinterpret_cast<UnresolvedLocation*>(data); |
||||
|
location->script_ = Handle<Script>::null(); |
||||
|
obj->Dispose(); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
} } // namespace v8::internal
|
@ -0,0 +1,138 @@ |
|||||
|
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
|
// Redistribution and use in source and binary forms, with or without
|
||||
|
// modification, are permitted provided that the following conditions are
|
||||
|
// met:
|
||||
|
//
|
||||
|
// * Redistributions of source code must retain the above copyright
|
||||
|
// notice, this list of conditions and the following disclaimer.
|
||||
|
// * Redistributions in binary form must reproduce the above
|
||||
|
// copyright notice, this list of conditions and the following
|
||||
|
// disclaimer in the documentation and/or other materials provided
|
||||
|
// with the distribution.
|
||||
|
// * Neither the name of Google Inc. nor the names of its
|
||||
|
// contributors may be used to endorse or promote products derived
|
||||
|
// from this software without specific prior written permission.
|
||||
|
//
|
||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
||||
|
#ifndef V8_ALLOCATION_TRACKER_H_ |
||||
|
#define V8_ALLOCATION_TRACKER_H_ |
||||
|
|
||||
|
namespace v8 { |
||||
|
namespace internal { |
||||
|
|
||||
|
class HeapObjectsMap; |
||||
|
|
||||
|
class AllocationTraceTree; |
||||
|
|
||||
|
class AllocationTraceNode { |
||||
|
public: |
||||
|
AllocationTraceNode(AllocationTraceTree* tree, |
||||
|
SnapshotObjectId shared_function_info_id); |
||||
|
~AllocationTraceNode(); |
||||
|
AllocationTraceNode* FindChild(SnapshotObjectId shared_function_info_id); |
||||
|
AllocationTraceNode* FindOrAddChild(SnapshotObjectId shared_function_info_id); |
||||
|
void AddAllocation(unsigned size); |
||||
|
|
||||
|
SnapshotObjectId function_id() const { return function_id_; } |
||||
|
unsigned allocation_size() const { return total_size_; } |
||||
|
unsigned allocation_count() const { return allocation_count_; } |
||||
|
unsigned id() const { return id_; } |
||||
|
Vector<AllocationTraceNode*> children() const { return children_.ToVector(); } |
||||
|
|
||||
|
void Print(int indent, AllocationTracker* tracker); |
||||
|
|
||||
|
private: |
||||
|
AllocationTraceTree* tree_; |
||||
|
SnapshotObjectId function_id_; |
||||
|
unsigned total_size_; |
||||
|
unsigned allocation_count_; |
||||
|
unsigned id_; |
||||
|
List<AllocationTraceNode*> children_; |
||||
|
|
||||
|
DISALLOW_COPY_AND_ASSIGN(AllocationTraceNode); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
class AllocationTraceTree { |
||||
|
public: |
||||
|
AllocationTraceTree(); |
||||
|
~AllocationTraceTree(); |
||||
|
AllocationTraceNode* AddPathFromEnd(const Vector<SnapshotObjectId>& path); |
||||
|
AllocationTraceNode* root() { return &root_; } |
||||
|
unsigned next_node_id() { return next_node_id_++; } |
||||
|
void Print(AllocationTracker* tracker); |
||||
|
|
||||
|
private: |
||||
|
unsigned next_node_id_; |
||||
|
AllocationTraceNode root_; |
||||
|
|
||||
|
DISALLOW_COPY_AND_ASSIGN(AllocationTraceTree); |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
class AllocationTracker { |
||||
|
public: |
||||
|
struct FunctionInfo { |
||||
|
FunctionInfo(); |
||||
|
const char* name; |
||||
|
const char* script_name; |
||||
|
int script_id; |
||||
|
int line; |
||||
|
int column; |
||||
|
}; |
||||
|
|
||||
|
AllocationTracker(HeapObjectsMap* ids, StringsStorage* names); |
||||
|
~AllocationTracker(); |
||||
|
|
||||
|
void PrepareForSerialization(); |
||||
|
void NewObjectEvent(Address addr, int size); |
||||
|
|
||||
|
AllocationTraceTree* trace_tree() { return &trace_tree_; } |
||||
|
HashMap* id_to_function_info() { return &id_to_function_info_; } |
||||
|
FunctionInfo* GetFunctionInfo(SnapshotObjectId id); |
||||
|
|
||||
|
private: |
||||
|
void AddFunctionInfo(SharedFunctionInfo* info, SnapshotObjectId id); |
||||
|
|
||||
|
class UnresolvedLocation { |
||||
|
public: |
||||
|
UnresolvedLocation(Script* script, int start, FunctionInfo* info); |
||||
|
~UnresolvedLocation(); |
||||
|
void Resolve(); |
||||
|
|
||||
|
private: |
||||
|
static void HandleWeakScript(v8::Isolate* isolate, |
||||
|
v8::Persistent<v8::Value>* obj, |
||||
|
void* data); |
||||
|
Handle<Script> script_; |
||||
|
int start_position_; |
||||
|
FunctionInfo* info_; |
||||
|
}; |
||||
|
static void DeleteUnresolvedLocation(UnresolvedLocation** location); |
||||
|
|
||||
|
static const int kMaxAllocationTraceLength = 64; |
||||
|
HeapObjectsMap* ids_; |
||||
|
StringsStorage* names_; |
||||
|
AllocationTraceTree trace_tree_; |
||||
|
SnapshotObjectId allocation_trace_buffer_[kMaxAllocationTraceLength]; |
||||
|
HashMap id_to_function_info_; |
||||
|
List<UnresolvedLocation*> unresolved_locations_; |
||||
|
|
||||
|
DISALLOW_COPY_AND_ASSIGN(AllocationTracker); |
||||
|
}; |
||||
|
|
||||
|
} } // namespace v8::internal
|
||||
|
|
||||
|
#endif // V8_ALLOCATION_TRACKER_H_
|
||||
|
|
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
File diff suppressed because it is too large
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue