Browse Source

Upgrade V8 to 2.5.9.1

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
7286b79521
  1. 1
      deps/v8/AUTHORS
  2. 25
      deps/v8/ChangeLog
  3. 5
      deps/v8/include/v8.h
  4. 227
      deps/v8/preparser/preparser-process.cc
  5. 18
      deps/v8/samples/process.cc
  6. 14
      deps/v8/samples/shell.cc
  7. 2
      deps/v8/src/SConscript
  8. 9
      deps/v8/src/api.cc
  9. 6
      deps/v8/src/arm/assembler-arm-inl.h
  10. 25
      deps/v8/src/arm/assembler-arm.cc
  11. 20
      deps/v8/src/arm/assembler-arm.h
  12. 125
      deps/v8/src/arm/builtins-arm.cc
  13. 270
      deps/v8/src/arm/codegen-arm.cc
  14. 8
      deps/v8/src/arm/codegen-arm.h
  15. 2
      deps/v8/src/arm/debug-arm.cc
  16. 75
      deps/v8/src/arm/ic-arm.cc
  17. 27
      deps/v8/src/arm/macro-assembler-arm.cc
  18. 42
      deps/v8/src/arm/macro-assembler-arm.h
  19. 7
      deps/v8/src/arm/stub-cache-arm.cc
  20. 1
      deps/v8/src/checks.cc
  21. 34
      deps/v8/src/checks.h
  22. 6
      deps/v8/src/conversions.cc
  23. 2
      deps/v8/src/dateparser-inl.h
  24. 12
      deps/v8/src/dateparser.h
  25. 2
      deps/v8/src/handles.cc
  26. 8
      deps/v8/src/hashmap.cc
  27. 10
      deps/v8/src/heap-profiler.cc
  28. 8
      deps/v8/src/ia32/macro-assembler-ia32.cc
  29. 1
      deps/v8/src/ia32/macro-assembler-ia32.h
  30. 7
      deps/v8/src/ia32/stub-cache-ia32.cc
  31. 11
      deps/v8/src/log.cc
  32. 3
      deps/v8/src/objects.cc
  33. 193
      deps/v8/src/parser.cc
  34. 151
      deps/v8/src/parser.h
  35. 3
      deps/v8/src/platform-freebsd.cc
  36. 3
      deps/v8/src/platform-linux.cc
  37. 3
      deps/v8/src/platform-macos.cc
  38. 6
      deps/v8/src/platform-openbsd.cc
  39. 3
      deps/v8/src/platform-solaris.cc
  40. 3
      deps/v8/src/platform-win32.cc
  41. 17
      deps/v8/src/platform.h
  42. 180
      deps/v8/src/preparse-data.cc
  43. 223
      deps/v8/src/preparse-data.h
  44. 1184
      deps/v8/src/preparser.cc
  45. 1188
      deps/v8/src/preparser.h
  46. 23
      deps/v8/src/profile-generator.cc
  47. 4
      deps/v8/src/profile-generator.h
  48. 8
      deps/v8/src/runtime.cc
  49. 2
      deps/v8/src/runtime.h
  50. 2
      deps/v8/src/string.js
  51. 2
      deps/v8/src/stub-cache.h
  52. 3
      deps/v8/src/token.cc
  53. 2
      deps/v8/src/v8.h
  54. 64
      deps/v8/src/v8checks.h
  55. 4
      deps/v8/src/version.cc
  56. 8
      deps/v8/src/x64/macro-assembler-x64.cc
  57. 3
      deps/v8/src/x64/macro-assembler-x64.h
  58. 7
      deps/v8/src/x64/stub-cache-x64.cc
  59. 27
      deps/v8/test/cctest/test-api.cc
  60. 6
      deps/v8/test/cctest/test-conversions.cc
  61. 15
      deps/v8/test/cctest/test-heap-profiler.cc
  62. 42
      deps/v8/test/cctest/test-log.cc
  63. 3
      deps/v8/test/cctest/test-parsing.cc
  64. 46
      deps/v8/test/mjsunit/regress/regress-944.js
  65. 19
      deps/v8/test/mjsunit/string-split.js
  66. 7
      deps/v8/tools/gyp/v8.gyp
  67. 2
      deps/v8/tools/presubmit.py
  68. 32
      deps/v8/tools/visual_studio/v8_base.vcproj

1
deps/v8/AUTHORS

@ -9,7 +9,6 @@ ARM Ltd.
Hewlett-Packard Development Company, LP Hewlett-Packard Development Company, LP
Alexander Botero-Lowry <alexbl@FreeBSD.org> Alexander Botero-Lowry <alexbl@FreeBSD.org>
Alexandre Rames <alexandre.rames@arm.com>
Alexandre Vassalotti <avassalotti@gmail.com> Alexandre Vassalotti <avassalotti@gmail.com>
Andreas Anyuru <andreas.anyuru@gmail.com> Andreas Anyuru <andreas.anyuru@gmail.com>
Burcu Dogan <burcujdogan@gmail.com> Burcu Dogan <burcujdogan@gmail.com>

25
deps/v8/ChangeLog

@ -1,3 +1,28 @@
2010-11-29: Version 2.5.9
Fixed crashes during GC caused by partially initialize heap
objects.
Fixed bug in process sample that caused memory leaks.
Improved performance on ARM by implementing missing stubs and
inlining.
Improved heap profiler support.
Added separate seeding on Windows of the random number generator
used internally by the compiler (issue 936).
Exposed API for getting the name of the function used to construct
an object.
Fixed date parser to handle one and two digit millisecond
values (issue 944).
Fixed number parsing to disallow space between sign and
digits (issue 946).
2010-11-23: Version 2.5.8 2010-11-23: Version 2.5.8
Removed dependency on Gay's dtoa. Removed dependency on Gay's dtoa.

5
deps/v8/include/v8.h

@ -1539,6 +1539,11 @@ class Object : public Value {
*/ */
V8EXPORT Local<String> ObjectProtoToString(); V8EXPORT Local<String> ObjectProtoToString();
/**
* Returns the name of the function invoked as a constructor for this object.
*/
V8EXPORT Local<String> GetConstructorName();
/** Gets the number of internal fields for this Object. */ /** Gets the number of internal fields for this Object. */
V8EXPORT int InternalFieldCount(); V8EXPORT int InternalFieldCount();
/** Gets the value in an internal field. */ /** Gets the value in an internal field. */

227
deps/v8/preparser/preparser-process.cc

@ -0,0 +1,227 @@
// Copyright 2010 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 <stdarg.h>
#include "../include/v8stdint.h"
#include "globals.h"
#include "checks.h"
#include "allocation.h"
#include "utils.h"
#include "list.h"
#include "smart-pointer.h"
#include "scanner-base.h"
#include "preparse-data.h"
#include "preparser.h"
enum ResultCode { kSuccess = 0, kErrorReading = 1, kErrorWriting = 2 };
namespace v8 {
namespace internal {
// THIS FILE IS PROOF-OF-CONCEPT ONLY.
// The final goal is a stand-alone preparser library.
// UTF16Buffer based on an UTF-8 string in memory.
class UTF8UTF16Buffer : public UTF16Buffer {
public:
UTF8UTF16Buffer(uint8_t* buffer, size_t length)
: UTF16Buffer(),
buffer_(buffer),
offset_(0),
end_offset_(static_cast<int>(length)) { }
virtual void PushBack(uc32 ch) {
// Pushback assumes that the character pushed back is the
// one that was most recently read, and jumps back in the
// UTF-8 stream by the length of that character's encoding.
offset_ -= unibrow::Utf8::Length(ch);
pos_--;
#ifdef DEBUG
int tmp = 0;
ASSERT_EQ(ch, unibrow::Utf8::ValueOf(buffer_ + offset_,
end_offset_ - offset_,
&tmp);
#endif
}
virtual uc32 Advance() {
if (offset_ == end_offset_) return -1;
uint8_t first_char = buffer_[offset_];
if (first_char <= unibrow::Utf8::kMaxOneByteChar) {
pos_++;
offset_++;
return static_cast<uc32>(first_char);
}
unibrow::uchar codepoint =
unibrow::Utf8::CalculateValue(buffer_ + offset_,
end_offset_ - offset_,
&offset_);
pos_++;
return static_cast<uc32>(codepoint);
}
virtual void SeekForward(int pos) {
while (pos_ < pos) {
uint8_t first_byte = buffer_[offset_++];
while (first_byte & 0x80u && offset_ < end_offset_) {
offset_++;
first_byte <<= 1;
}
pos_++;
}
}
private:
const uint8_t* buffer_;
unsigned offset_;
unsigned end_offset_;
};
class StandAloneJavaScriptScanner : public JavaScriptScanner {
public:
void Initialize(UTF16Buffer* source) {
source_ = source;
literal_flags_ = kLiteralString | kLiteralIdentifier;
Init();
// Skip initial whitespace allowing HTML comment ends just like
// after a newline and scan first token.
has_line_terminator_before_next_ = true;
SkipWhiteSpace();
Scan();
}
};
// Write a number to dest in network byte order.
void WriteUInt32(FILE* dest, uint32_t value, bool* ok) {
for (int i = 3; i >= 0; i--) {
uint8_t byte = static_cast<uint8_t>(value >> (i << 3));
int result = fputc(byte, dest);
if (result == EOF) {
*ok = false;
return;
}
}
}
// Read number from FILE* in network byte order.
uint32_t ReadUInt32(FILE* source, bool* ok) {
uint32_t n = 0;
for (int i = 0; i < 4; i++) {
int c = fgetc(source);
if (c == EOF) {
*ok = false;
return 0;
}
n = (n << 8) + static_cast<uint32_t>(c);
}
return n;
}
bool ReadBuffer(FILE* source, void* buffer, size_t length) {
size_t actually_read = fread(buffer, 1, length, stdin);
return (actually_read == length);
}
bool WriteBuffer(FILE* dest, void* buffer, size_t length) {
size_t actually_written = fwrite(buffer, 1, length, dest);
return (actually_written == length);
}
// Preparse stdin and output result on stdout.
int PreParseIO() {
fprintf(stderr, "LOG: Enter parsing loop\n");
bool ok = true;
uint32_t length = ReadUInt32(stdin, &ok);
if (!ok) return kErrorReading;
SmartPointer<byte> buffer(NewArray<byte>(length));
if (!ReadBuffer(stdin, *buffer, length)) {
return kErrorReading;
}
UTF8UTF16Buffer input_buffer(*buffer, static_cast<size_t>(length));
StandAloneJavaScriptScanner scanner;
scanner.Initialize(&input_buffer);
CompleteParserRecorder recorder;
preparser::PreParser preparser;
if (!preparser.PreParseProgram(&scanner, &recorder, true)) {
if (scanner.stack_overflow()) {
// Report stack overflow error/no-preparser-data.
WriteUInt32(stdout, 0, &ok);
if (!ok) return kErrorWriting;
return 0;
}
}
Vector<unsigned> pre_data = recorder.ExtractData();
uint32_t size = static_cast<uint32_t>(pre_data.length() * sizeof(uint32_t));
WriteUInt32(stdout, size, &ok);
if (!ok) return kErrorWriting;
if (!WriteBuffer(stdout,
reinterpret_cast<byte*>(pre_data.start()),
size)) {
return kErrorWriting;
}
return 0;
}
// Functions declared by allocation.h
void FatalProcessOutOfMemory(const char* location) {
V8_Fatal("", 0, location);
}
bool EnableSlowAsserts() { return true; }
} } // namespace v8::internal
int main(int argc, char* argv[]) {
int status = 0;
do {
status = v8::internal::PreParseIO();
} while (status == 0);
fprintf(stderr, "EXIT: Failure %d\n", status);
return EXIT_FAILURE;
}
// Fatal error handling declared by checks.h.
extern "C" void V8_Fatal(const char* file, int line, const char* format, ...) {
fflush(stdout);
fflush(stderr);
va_list arguments;
va_start(arguments, format);
vfprintf(stderr, format, arguments);
va_end(arguments);
fputs("\n#\n\n", stderr);
exit(EXIT_FAILURE);
}

18
deps/v8/samples/process.cc

@ -152,18 +152,16 @@ bool JsHttpRequestProcessor::Initialize(map<string, string>* opts,
Handle<ObjectTemplate> global = ObjectTemplate::New(); Handle<ObjectTemplate> global = ObjectTemplate::New();
global->Set(String::New("log"), FunctionTemplate::New(LogCallback)); global->Set(String::New("log"), FunctionTemplate::New(LogCallback));
// Each processor gets its own context so different processors // Each processor gets its own context so different processors don't
// don't affect each other (ignore the first three lines). // affect each other. Context::New returns a persistent handle which
Handle<Context> context = Context::New(NULL, global); // is what we need for the reference to remain after we return from
// this method. That persistent handle has to be disposed in the
// Store the context in the processor object in a persistent handle, // destructor.
// since we want the reference to remain after we return from this context_ = Context::New(NULL, global);
// method.
context_ = Persistent<Context>::New(context);
// Enter the new context so all the following operations take place // Enter the new context so all the following operations take place
// within it. // within it.
Context::Scope context_scope(context); Context::Scope context_scope(context_);
// Make the options mapping available within the context // Make the options mapping available within the context
if (!InstallMaps(opts, output)) if (!InstallMaps(opts, output))
@ -176,7 +174,7 @@ bool JsHttpRequestProcessor::Initialize(map<string, string>* opts,
// The script compiled and ran correctly. Now we fetch out the // The script compiled and ran correctly. Now we fetch out the
// Process function from the global object. // Process function from the global object.
Handle<String> process_name = String::New("Process"); Handle<String> process_name = String::New("Process");
Handle<Value> process_val = context->Global()->Get(process_name); Handle<Value> process_val = context_->Global()->Get(process_name);
// If there is no Process function, or if it is not a function, // If there is no Process function, or if it is not a function,
// bail out // bail out

14
deps/v8/samples/shell.cc

@ -37,7 +37,6 @@ bool ExecuteString(v8::Handle<v8::String> source,
v8::Handle<v8::Value> name, v8::Handle<v8::Value> name,
bool print_result, bool print_result,
bool report_exceptions); bool report_exceptions);
v8::Handle<v8::Value> PrintToInteger(const v8::Arguments& args);
v8::Handle<v8::Value> Print(const v8::Arguments& args); v8::Handle<v8::Value> Print(const v8::Arguments& args);
v8::Handle<v8::Value> Read(const v8::Arguments& args); v8::Handle<v8::Value> Read(const v8::Arguments& args);
v8::Handle<v8::Value> Load(const v8::Arguments& args); v8::Handle<v8::Value> Load(const v8::Arguments& args);
@ -54,8 +53,7 @@ int RunMain(int argc, char* argv[]) {
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
// Bind the global 'print' function to the C++ Print callback. // Bind the global 'print' function to the C++ Print callback.
global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
global->Set(v8::String::New("print2int"), v8::FunctionTemplate::New(PrintToInteger)); // Bind the global 'read' function to the C++ Read callback.
// Bind the global 'read' function to the C++ Read callback.
global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read)); global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read));
// Bind the global 'load' function to the C++ Load callback. // Bind the global 'load' function to the C++ Load callback.
global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load)); global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
@ -140,16 +138,6 @@ v8::Handle<v8::Value> Print(const v8::Arguments& args) {
} }
v8::Handle<v8::Value> PrintToInteger(const v8::Arguments& args) {
v8::HandleScope handle_scope;
v8::String::Utf8Value str(args[0]);
const char* cstr = ToCString(str);
printf("%s -> %d\n", cstr, args[0]->ToInt32()->Value());
fflush(stdout);
return v8::Undefined();
}
// The callback that is invoked by v8 whenever the JavaScript 'read' // The callback that is invoked by v8 whenever the JavaScript 'read'
// function is called. This function loads the content of the file named in // function is called. This function loads the content of the file named in
// the argument into a JavaScript string. // the argument into a JavaScript string.

2
deps/v8/src/SConscript

@ -89,6 +89,8 @@ SOURCES = {
objects-visiting.cc objects-visiting.cc
oprofile-agent.cc oprofile-agent.cc
parser.cc parser.cc
preparser.cc
preparse-data.cc
profile-generator.cc profile-generator.cc
property.cc property.cc
regexp-macro-assembler-irregexp.cc regexp-macro-assembler-irregexp.cc

9
deps/v8/src/api.cc

@ -2451,6 +2451,15 @@ Local<String> v8::Object::ObjectProtoToString() {
} }
Local<String> v8::Object::GetConstructorName() {
ON_BAILOUT("v8::Object::GetConstructorName()", return Local<v8::String>());
ENTER_V8;
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::String> name(self->constructor_name());
return Utils::ToLocal(name);
}
bool v8::Object::Delete(v8::Handle<String> key) { bool v8::Object::Delete(v8::Handle<String> key) {
ON_BAILOUT("v8::Object::Delete()", return false); ON_BAILOUT("v8::Object::Delete()", return false);
ENTER_V8; ENTER_V8;

6
deps/v8/src/arm/assembler-arm-inl.h

@ -164,7 +164,7 @@ bool RelocInfo::IsPatchedReturnSequence() {
bool RelocInfo::IsPatchedDebugBreakSlotSequence() { bool RelocInfo::IsPatchedDebugBreakSlotSequence() {
Instr current_instr = Assembler::instr_at(pc_); Instr current_instr = Assembler::instr_at(pc_);
return !Assembler::IsNop(current_instr, 2); return !Assembler::IsNop(current_instr, Assembler::DEBUG_BREAK_NOP);
} }
@ -288,9 +288,7 @@ Address Assembler::target_address_address_at(Address pc) {
} }
#endif #endif
// Verify that the instruction to patch is a ASSERT(IsLdrPcImmediateOffset(instr));
// ldr<cond> <Rd>, [pc +/- offset_12].
ASSERT((instr & 0x0f7f0000) == 0x051f0000);
int offset = instr & 0xfff; // offset_12 is unsigned int offset = instr & 0xfff; // offset_12 is unsigned
if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign if ((instr & (1 << 23)) == 0) offset = -offset; // U bit defines offset sign
// Verify that the constant pool comes after the instruction referencing it. // Verify that the constant pool comes after the instruction referencing it.

25
deps/v8/src/arm/assembler-arm.cc

@ -397,13 +397,6 @@ void Assembler::CodeTargetAlign() {
} }
bool Assembler::IsNop(Instr instr, int type) {
// Check for mov rx, rx.
ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop.
return instr == (al | 13*B21 | type*B12 | type);
}
bool Assembler::IsBranch(Instr instr) { bool Assembler::IsBranch(Instr instr) {
return (instr & (B27 | B25)) == (B27 | B25); return (instr & (B27 | B25)) == (B27 | B25);
} }
@ -510,6 +503,13 @@ bool Assembler::IsLdrRegFpNegOffset(Instr instr) {
} }
bool Assembler::IsLdrPcImmediateOffset(Instr instr) {
// Check the instruction is indeed a
// ldr<cond> <Rd>, [pc +/- offset_12].
return (instr & 0x0f7f0000) == 0x051f0000;
}
// Labels refer to positions in the (to be) generated code. // Labels refer to positions in the (to be) generated code.
// There are bound, linked, and unused labels. // There are bound, linked, and unused labels.
// //
@ -1113,8 +1113,8 @@ void Assembler::mov(Register dst, const Operand& src, SBit s, Condition cond) {
positions_recorder()->WriteRecordedPositions(); positions_recorder()->WriteRecordedPositions();
} }
// Don't allow nop instructions in the form mov rn, rn to be generated using // Don't allow nop instructions in the form mov rn, rn to be generated using
// the mov instruction. They must be generated using nop(int) // the mov instruction. They must be generated using nop(int/NopMarkerTypes)
// pseudo instructions. // or MarkCode(int/NopMarkerTypes) pseudo instructions.
ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al)); ASSERT(!(src.is_reg() && src.rm().is(dst) && s == LeaveCC && cond == al));
addrmod1(cond | 13*B21 | s, r0, dst, src); addrmod1(cond | 13*B21 | s, r0, dst, src);
} }
@ -2376,6 +2376,13 @@ void Assembler::nop(int type) {
} }
bool Assembler::IsNop(Instr instr, int type) {
// Check for mov rx, rx.
ASSERT(0 <= type && type <= 14); // mov pc, pc is not a nop.
return instr == (al | 13*B21 | type*B12 | type);
}
bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) { bool Assembler::ImmediateFitsAddrMode1Instruction(int32_t imm32) {
uint32_t dummy1; uint32_t dummy1;
uint32_t dummy2; uint32_t dummy2;

20
deps/v8/src/arm/assembler-arm.h

@ -1079,7 +1079,22 @@ class Assembler : public Malloced {
const Condition cond = al); const Condition cond = al);
// Pseudo instructions // Pseudo instructions
void nop(int type = 0);
// Different nop operations are used by the code generator to detect certain
// states of the generated code.
enum NopMarkerTypes {
NON_MARKING_NOP = 0,
DEBUG_BREAK_NOP,
// IC markers.
PROPERTY_ACCESS_INLINED,
PROPERTY_ACCESS_INLINED_CONTEXT,
PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
// Helper values.
LAST_CODE_MARKER,
FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
};
void nop(int type = 0); // 0 is the default non-marking type.
void push(Register src, Condition cond = al) { void push(Register src, Condition cond = al) {
str(src, MemOperand(sp, 4, NegPreIndex), cond); str(src, MemOperand(sp, 4, NegPreIndex), cond);
@ -1151,7 +1166,6 @@ class Assembler : public Malloced {
static void instr_at_put(byte* pc, Instr instr) { static void instr_at_put(byte* pc, Instr instr) {
*reinterpret_cast<Instr*>(pc) = instr; *reinterpret_cast<Instr*>(pc) = instr;
} }
static bool IsNop(Instr instr, int type = 0);
static bool IsBranch(Instr instr); static bool IsBranch(Instr instr);
static int GetBranchOffset(Instr instr); static int GetBranchOffset(Instr instr);
static bool IsLdrRegisterImmediate(Instr instr); static bool IsLdrRegisterImmediate(Instr instr);
@ -1168,6 +1182,8 @@ class Assembler : public Malloced {
static bool IsLdrRegFpOffset(Instr instr); static bool IsLdrRegFpOffset(Instr instr);
static bool IsStrRegFpNegOffset(Instr instr); static bool IsStrRegFpNegOffset(Instr instr);
static bool IsLdrRegFpNegOffset(Instr instr); static bool IsLdrRegFpNegOffset(Instr instr);
static bool IsLdrPcImmediateOffset(Instr instr);
static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
protected: protected:

125
deps/v8/src/arm/builtins-arm.cc

@ -482,9 +482,128 @@ void Builtins::Generate_ArrayConstructCode(MacroAssembler* masm) {
void Builtins::Generate_StringConstructCode(MacroAssembler* masm) { void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
// TODO(849): implement custom construct stub. // ----------- S t a t e -------------
// Generate a copy of the generic stub for now. // -- r0 : number of arguments
Generate_JSConstructStubGeneric(masm); // -- r1 : constructor function
// -- lr : return address
// -- sp[(argc - n - 1) * 4] : arg[n] (zero based)
// -- sp[argc * 4] : receiver
// -----------------------------------
__ IncrementCounter(&Counters::string_ctor_calls, 1, r2, r3);
Register function = r1;
if (FLAG_debug_code) {
__ LoadGlobalFunction(Context::STRING_FUNCTION_INDEX, r2);
__ cmp(function, Operand(r2));
__ Assert(eq, "Unexpected String function");
}
// Load the first arguments in r0 and get rid of the rest.
Label no_arguments;
__ cmp(r0, Operand(0));
__ b(eq, &no_arguments);
// First args = sp[(argc - 1) * 4].
__ sub(r0, r0, Operand(1));
__ ldr(r0, MemOperand(sp, r0, LSL, kPointerSizeLog2, PreIndex));
// sp now point to args[0], drop args[0] + receiver.
__ Drop(2);
Register argument = r2;
Label not_cached, argument_is_string;
NumberToStringStub::GenerateLookupNumberStringCache(
masm,
r0, // Input.
argument, // Result.
r3, // Scratch.
r4, // Scratch.
r5, // Scratch.
false, // Is it a Smi?
&not_cached);
__ IncrementCounter(&Counters::string_ctor_cached_number, 1, r3, r4);
__ bind(&argument_is_string);
// ----------- S t a t e -------------
// -- r2 : argument converted to string
// -- r1 : constructor function
// -- lr : return address
// -----------------------------------
Label gc_required;
__ AllocateInNewSpace(JSValue::kSize,
r0, // Result.
r3, // Scratch.
r4, // Scratch.
&gc_required,
TAG_OBJECT);
// Initialising the String Object.
Register map = r3;
__ LoadGlobalFunctionInitialMap(function, map, r4);
if (FLAG_debug_code) {
__ ldrb(r4, FieldMemOperand(map, Map::kInstanceSizeOffset));
__ cmp(r4, Operand(JSValue::kSize >> kPointerSizeLog2));
__ Assert(eq, "Unexpected string wrapper instance size");
__ ldrb(r4, FieldMemOperand(map, Map::kUnusedPropertyFieldsOffset));
__ cmp(r4, Operand(0));
__ Assert(eq, "Unexpected unused properties of string wrapper");
}
__ str(map, FieldMemOperand(r0, HeapObject::kMapOffset));
__ LoadRoot(r3, Heap::kEmptyFixedArrayRootIndex);
__ str(r3, FieldMemOperand(r0, JSObject::kPropertiesOffset));
__ str(r3, FieldMemOperand(r0, JSObject::kElementsOffset));
__ str(argument, FieldMemOperand(r0, JSValue::kValueOffset));
// Ensure the object is fully initialized.
STATIC_ASSERT(JSValue::kSize == 4 * kPointerSize);
__ Ret();
// The argument was not found in the number to string cache. Check
// if it's a string already before calling the conversion builtin.
Label convert_argument;
__ bind(&not_cached);
__ BranchOnSmi(r0, &convert_argument);
// Is it a String?
__ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset));
__ ldrb(r3, FieldMemOperand(r2, Map::kInstanceTypeOffset));
ASSERT(kNotStringTag != 0);
__ tst(r3, Operand(kIsNotStringMask));
__ b(ne, &convert_argument);
__ mov(argument, r0);
__ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4);
__ b(&argument_is_string);
// Invoke the conversion builtin and put the result into r2.
__ bind(&convert_argument);
__ push(function); // Preserve the function.
__ IncrementCounter(&Counters::string_ctor_conversions, 1, r3, r4);
__ EnterInternalFrame();
__ push(r0);
__ InvokeBuiltin(Builtins::TO_STRING, CALL_JS);
__ LeaveInternalFrame();
__ pop(function);
__ mov(argument, r0);
__ b(&argument_is_string);
// Load the empty string into r2, remove the receiver from the
// stack, and jump back to the case where the argument is a string.
__ bind(&no_arguments);
__ LoadRoot(argument, Heap::kEmptyStringRootIndex);
__ Drop(1);
__ b(&argument_is_string);
// At this point the argument is already a string. Call runtime to
// create a string wrapper.
__ bind(&gc_required);
__ IncrementCounter(&Counters::string_ctor_gc_required, 1, r3, r4);
__ EnterInternalFrame();
__ push(argument);
__ CallRuntime(Runtime::kNewStringWrapper, 1);
__ LeaveInternalFrame();
__ Ret();
} }

270
deps/v8/src/arm/codegen-arm.cc

@ -6024,6 +6024,68 @@ void CodeGenerator::VisitUnaryOperation(UnaryOperation* node) {
} }
class DeferredCountOperation: public DeferredCode {
public:
DeferredCountOperation(Register value,
bool is_increment,
bool is_postfix,
int target_size)
: value_(value),
is_increment_(is_increment),
is_postfix_(is_postfix),
target_size_(target_size) {}
virtual void Generate() {
VirtualFrame copied_frame(*frame_state()->frame());
Label slow;
// Check for smi operand.
__ tst(value_, Operand(kSmiTagMask));
__ b(ne, &slow);
// Revert optimistic increment/decrement.
if (is_increment_) {
__ sub(value_, value_, Operand(Smi::FromInt(1)));
} else {
__ add(value_, value_, Operand(Smi::FromInt(1)));
}
// Slow case: Convert to number. At this point the
// value to be incremented is in the value register..
__ bind(&slow);
// Convert the operand to a number.
copied_frame.EmitPush(value_);
copied_frame.InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1);
if (is_postfix_) {
// Postfix: store to result (on the stack).
__ str(r0, MemOperand(sp, target_size_ * kPointerSize));
}
copied_frame.EmitPush(r0);
copied_frame.EmitPush(Operand(Smi::FromInt(1)));
if (is_increment_) {
copied_frame.CallRuntime(Runtime::kNumberAdd, 2);
} else {
copied_frame.CallRuntime(Runtime::kNumberSub, 2);
}
__ Move(value_, r0);
copied_frame.MergeTo(frame_state()->frame());
}
private:
Register value_;
bool is_increment_;
bool is_postfix_;
int target_size_;
};
void CodeGenerator::VisitCountOperation(CountOperation* node) { void CodeGenerator::VisitCountOperation(CountOperation* node) {
#ifdef DEBUG #ifdef DEBUG
int original_height = frame_->height(); int original_height = frame_->height();
@ -6083,9 +6145,7 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
// the target. It also pushes the current value of the target. // the target. It also pushes the current value of the target.
target.GetValue(); target.GetValue();
JumpTarget slow; bool value_is_known_smi = frame_->KnownSmiAt(0);
JumpTarget exit;
Register value = frame_->PopToRegister(); Register value = frame_->PopToRegister();
// Postfix: Store the old value as the result. // Postfix: Store the old value as the result.
@ -6097,9 +6157,27 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
value = VirtualFrame::scratch0(); value = VirtualFrame::scratch0();
} }
// We can't use any type information here since the virtual frame from the
// deferred code may have lost information and we can't merge a virtual
// frame with less specific type knowledge to a virtual frame with more
// specific knowledge that has already used that specific knowledge to
// generate code.
frame_->ForgetTypeInfo();
// The constructor here will capture the current virtual frame and use it to
// merge to after the deferred code has run. No virtual frame changes are
// allowed from here until the 'BindExit' below.
DeferredCode* deferred =
new DeferredCountOperation(value,
is_increment,
is_postfix,
target.size());
if (!value_is_known_smi) {
// Check for smi operand. // Check for smi operand.
__ tst(value, Operand(kSmiTagMask)); __ tst(value, Operand(kSmiTagMask));
slow.Branch(ne);
deferred->Branch(ne);
}
// Perform optimistic increment/decrement. // Perform optimistic increment/decrement.
if (is_increment) { if (is_increment) {
@ -6108,46 +6186,13 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
__ sub(value, value, Operand(Smi::FromInt(1)), SetCC); __ sub(value, value, Operand(Smi::FromInt(1)), SetCC);
} }
// If the increment/decrement didn't overflow, we're done. // If increment/decrement overflows, go to deferred code.
exit.Branch(vc); deferred->Branch(vs);
// Revert optimistic increment/decrement.
if (is_increment) {
__ sub(value, value, Operand(Smi::FromInt(1)));
} else {
__ add(value, value, Operand(Smi::FromInt(1)));
}
// Slow case: Convert to number. At this point the
// value to be incremented is in the value register..
slow.Bind();
// Convert the operand to a number.
frame_->EmitPush(value);
{
VirtualFrame::SpilledScope spilled(frame_);
frame_->InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS, 1);
if (is_postfix) {
// Postfix: store to result (on the stack).
__ str(r0, frame_->ElementAt(target.size()));
}
// Compute the new value. deferred->BindExit();
frame_->EmitPush(r0);
frame_->EmitPush(Operand(Smi::FromInt(1)));
if (is_increment) {
frame_->CallRuntime(Runtime::kNumberAdd, 2);
} else {
frame_->CallRuntime(Runtime::kNumberSub, 2);
}
}
__ Move(value, r0);
// Store the new value in the target if not const. // Store the new value in the target if not const.
// At this point the answer is in the value register. // At this point the answer is in the value register.
exit.Bind();
frame_->EmitPush(value); frame_->EmitPush(value);
// Set the target with the result, leaving the result on // Set the target with the result, leaving the result on
// top of the stack. Removes the target from the stack if // top of the stack. Removes the target from the stack if
@ -6537,16 +6582,29 @@ void CodeGenerator::VisitCompareToNull(CompareToNull* node) {
class DeferredReferenceGetNamedValue: public DeferredCode { class DeferredReferenceGetNamedValue: public DeferredCode {
public: public:
explicit DeferredReferenceGetNamedValue(Register receiver, explicit DeferredReferenceGetNamedValue(Register receiver,
Handle<String> name) Handle<String> name,
: receiver_(receiver), name_(name) { bool is_contextual)
set_comment("[ DeferredReferenceGetNamedValue"); : receiver_(receiver),
name_(name),
is_contextual_(is_contextual),
is_dont_delete_(false) {
set_comment(is_contextual
? "[ DeferredReferenceGetNamedValue (contextual)"
: "[ DeferredReferenceGetNamedValue");
} }
virtual void Generate(); virtual void Generate();
void set_is_dont_delete(bool value) {
ASSERT(is_contextual_);
is_dont_delete_ = value;
}
private: private:
Register receiver_; Register receiver_;
Handle<String> name_; Handle<String> name_;
bool is_contextual_;
bool is_dont_delete_;
}; };
@ -6573,10 +6631,20 @@ void DeferredReferenceGetNamedValue::Generate() {
// The rest of the instructions in the deferred code must be together. // The rest of the instructions in the deferred code must be together.
{ Assembler::BlockConstPoolScope block_const_pool(masm_); { Assembler::BlockConstPoolScope block_const_pool(masm_);
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
__ Call(ic, RelocInfo::CODE_TARGET); RelocInfo::Mode mode = is_contextual_
// The call must be followed by a nop(1) instruction to indicate that the ? RelocInfo::CODE_TARGET_CONTEXT
// in-object has been inlined. : RelocInfo::CODE_TARGET;
__ nop(PROPERTY_ACCESS_INLINED); __ Call(ic, mode);
// We must mark the code just after the call with the correct marker.
MacroAssembler::NopMarkerTypes code_marker;
if (is_contextual_) {
code_marker = is_dont_delete_
? MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE
: MacroAssembler::PROPERTY_ACCESS_INLINED_CONTEXT;
} else {
code_marker = MacroAssembler::PROPERTY_ACCESS_INLINED;
}
__ MarkCode(code_marker);
// At this point the answer is in r0. We move it to the expected register // At this point the answer is in r0. We move it to the expected register
// if necessary. // if necessary.
@ -6640,7 +6708,7 @@ void DeferredReferenceGetKeyedValue::Generate() {
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
// The call must be followed by a nop instruction to indicate that the // The call must be followed by a nop instruction to indicate that the
// keyed load has been inlined. // keyed load has been inlined.
__ nop(PROPERTY_ACCESS_INLINED); __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
// Now go back to the frame that we entered with. This will not overwrite // Now go back to the frame that we entered with. This will not overwrite
// the receiver or key registers since they were not in use when we came // the receiver or key registers since they were not in use when we came
@ -6697,7 +6765,7 @@ void DeferredReferenceSetKeyedValue::Generate() {
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
// The call must be followed by a nop instruction to indicate that the // The call must be followed by a nop instruction to indicate that the
// keyed store has been inlined. // keyed store has been inlined.
__ nop(PROPERTY_ACCESS_INLINED); __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
// Block the constant pool for one more instruction after leaving this // Block the constant pool for one more instruction after leaving this
// constant pool block scope to include the branch instruction ending the // constant pool block scope to include the branch instruction ending the
@ -6745,7 +6813,7 @@ void DeferredReferenceSetNamedValue::Generate() {
__ Call(ic, RelocInfo::CODE_TARGET); __ Call(ic, RelocInfo::CODE_TARGET);
// The call must be followed by a nop instruction to indicate that the // The call must be followed by a nop instruction to indicate that the
// named store has been inlined. // named store has been inlined.
__ nop(PROPERTY_ACCESS_INLINED); __ MarkCode(MacroAssembler::PROPERTY_ACCESS_INLINED);
// Go back to the frame we entered with. The instructions // Go back to the frame we entered with. The instructions
// generated by this merge are skipped over by the inline store // generated by this merge are skipped over by the inline store
@ -6763,7 +6831,14 @@ void DeferredReferenceSetNamedValue::Generate() {
// Consumes the top of stack (the receiver) and pushes the result instead. // Consumes the top of stack (the receiver) and pushes the result instead.
void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) { void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) { bool contextual_load_in_builtin =
is_contextual &&
(Bootstrapper::IsActive() ||
(!info_->closure().is_null() && info_->closure()->IsBuiltin()));
if (scope()->is_global_scope() ||
loop_nesting() == 0 ||
contextual_load_in_builtin) {
Comment cmnt(masm(), "[ Load from named Property"); Comment cmnt(masm(), "[ Load from named Property");
// Setup the name register and call load IC. // Setup the name register and call load IC.
frame_->CallLoadIC(name, frame_->CallLoadIC(name,
@ -6773,12 +6848,19 @@ void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
frame_->EmitPush(r0); // Push answer. frame_->EmitPush(r0); // Push answer.
} else { } else {
// Inline the in-object property case. // Inline the in-object property case.
Comment cmnt(masm(), "[ Inlined named property load"); Comment cmnt(masm(), is_contextual
? "[ Inlined contextual property load"
: "[ Inlined named property load");
// Counter will be decremented in the deferred code. Placed here to avoid // Counter will be decremented in the deferred code. Placed here to avoid
// having it in the instruction stream below where patching will occur. // having it in the instruction stream below where patching will occur.
if (is_contextual) {
__ IncrementCounter(&Counters::named_load_global_inline, 1,
frame_->scratch0(), frame_->scratch1());
} else {
__ IncrementCounter(&Counters::named_load_inline, 1, __ IncrementCounter(&Counters::named_load_inline, 1,
frame_->scratch0(), frame_->scratch1()); frame_->scratch0(), frame_->scratch1());
}
// The following instructions are the inlined load of an in-object property. // The following instructions are the inlined load of an in-object property.
// Parts of this code is patched, so the exact instructions generated needs // Parts of this code is patched, so the exact instructions generated needs
@ -6789,18 +6871,56 @@ void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
Register receiver = frame_->PopToRegister(); Register receiver = frame_->PopToRegister();
DeferredReferenceGetNamedValue* deferred = DeferredReferenceGetNamedValue* deferred =
new DeferredReferenceGetNamedValue(receiver, name); new DeferredReferenceGetNamedValue(receiver, name, is_contextual);
#ifdef DEBUG bool is_dont_delete = false;
int kInlinedNamedLoadInstructions = 7; if (is_contextual) {
Label check_inlined_codesize; if (!info_->closure().is_null()) {
masm_->bind(&check_inlined_codesize); // When doing lazy compilation we can check if the global cell
#endif // already exists and use its "don't delete" status as a hint.
AssertNoAllocation no_gc;
v8::internal::GlobalObject* global_object =
info_->closure()->context()->global();
LookupResult lookup;
global_object->LocalLookupRealNamedProperty(*name, &lookup);
if (lookup.IsProperty() && lookup.type() == NORMAL) {
ASSERT(lookup.holder() == global_object);
ASSERT(global_object->property_dictionary()->ValueAt(
lookup.GetDictionaryEntry())->IsJSGlobalPropertyCell());
is_dont_delete = lookup.IsDontDelete();
}
}
if (is_dont_delete) {
__ IncrementCounter(&Counters::dont_delete_hint_hit, 1,
frame_->scratch0(), frame_->scratch1());
}
}
{ Assembler::BlockConstPoolScope block_const_pool(masm_); { Assembler::BlockConstPoolScope block_const_pool(masm_);
if (!is_contextual) {
// Check that the receiver is a heap object. // Check that the receiver is a heap object.
__ tst(receiver, Operand(kSmiTagMask)); __ tst(receiver, Operand(kSmiTagMask));
deferred->Branch(eq); deferred->Branch(eq);
}
// Check for the_hole_value if necessary.
// Below we rely on the number of instructions generated, and we can't
// cope with the Check macro which does not generate a fixed number of
// instructions.
Label skip, check_the_hole, cont;
if (FLAG_debug_code && is_contextual && is_dont_delete) {
__ b(&skip);
__ bind(&check_the_hole);
__ Check(ne, "DontDelete cells can't contain the hole");
__ b(&cont);
__ bind(&skip);
}
#ifdef DEBUG
int InlinedNamedLoadInstructions = 5;
Label check_inlined_codesize;
masm_->bind(&check_inlined_codesize);
#endif
Register scratch = VirtualFrame::scratch0(); Register scratch = VirtualFrame::scratch0();
Register scratch2 = VirtualFrame::scratch1(); Register scratch2 = VirtualFrame::scratch1();
@ -6812,12 +6932,42 @@ void CodeGenerator::EmitNamedLoad(Handle<String> name, bool is_contextual) {
__ cmp(scratch, scratch2); __ cmp(scratch, scratch2);
deferred->Branch(ne); deferred->Branch(ne);
if (is_contextual) {
#ifdef DEBUG
InlinedNamedLoadInstructions += 1;
#endif
// Load the (initially invalid) cell and get its value.
masm()->mov(receiver, Operand(Factory::null_value()));
__ ldr(receiver,
FieldMemOperand(receiver, JSGlobalPropertyCell::kValueOffset));
deferred->set_is_dont_delete(is_dont_delete);
if (!is_dont_delete) {
#ifdef DEBUG
InlinedNamedLoadInstructions += 3;
#endif
__ cmp(receiver, Operand(Factory::the_hole_value()));
deferred->Branch(eq);
} else if (FLAG_debug_code) {
#ifdef DEBUG
InlinedNamedLoadInstructions += 3;
#endif
__ cmp(receiver, Operand(Factory::the_hole_value()));
__ b(&check_the_hole, eq);
__ bind(&cont);
}
} else {
// Initially use an invalid index. The index will be patched by the // Initially use an invalid index. The index will be patched by the
// inline cache code. // inline cache code.
__ ldr(receiver, MemOperand(receiver, 0)); __ ldr(receiver, MemOperand(receiver, 0));
}
// Make sure that the expected number of instructions are generated. // Make sure that the expected number of instructions are generated.
ASSERT_EQ(kInlinedNamedLoadInstructions, // If the code before is updated, the offsets in ic-arm.cc
// LoadIC::PatchInlinedContextualLoad and PatchInlinedLoad need
// to be updated.
ASSERT_EQ(InlinedNamedLoadInstructions,
masm_->InstructionsGeneratedSince(&check_inlined_codesize)); masm_->InstructionsGeneratedSince(&check_inlined_codesize));
} }

8
deps/v8/src/arm/codegen-arm.h

@ -194,14 +194,6 @@ enum ArgumentsAllocationMode {
}; };
// Different nop operations are used by the code generator to detect certain
// states of the generated code.
enum NopMarkerTypes {
NON_MARKING_NOP = 0,
PROPERTY_ACCESS_INLINED
};
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// CodeGenerator // CodeGenerator

2
deps/v8/src/arm/debug-arm.cc

@ -279,7 +279,7 @@ void Debug::GenerateSlot(MacroAssembler* masm) {
__ bind(&check_codesize); __ bind(&check_codesize);
__ RecordDebugBreakSlot(); __ RecordDebugBreakSlot();
for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) { for (int i = 0; i < Assembler::kDebugBreakSlotInstructions; i++) {
__ nop(2); __ nop(MacroAssembler::DEBUG_BREAK_NOP);
} }
ASSERT_EQ(Assembler::kDebugBreakSlotInstructions, ASSERT_EQ(Assembler::kDebugBreakSlotInstructions,
masm->InstructionsGeneratedSince(&check_codesize)); masm->InstructionsGeneratedSince(&check_codesize));

75
deps/v8/src/arm/ic-arm.cc

@ -904,8 +904,8 @@ void LoadIC::GenerateMiss(MacroAssembler* masm) {
__ TailCallExternalReference(ref, 2, 1); __ TailCallExternalReference(ref, 2, 1);
} }
// Returns the code marker, or the 0 if the code is not marked.
static inline bool IsInlinedICSite(Address address, static inline int InlinedICSiteMarker(Address address,
Address* inline_end_address) { Address* inline_end_address) {
// If the instruction after the call site is not the pseudo instruction nop1 // If the instruction after the call site is not the pseudo instruction nop1
// then this is not related to an inlined in-object property load. The nop1 // then this is not related to an inlined in-object property load. The nop1
@ -914,9 +914,11 @@ static inline bool IsInlinedICSite(Address address,
// a branch instruction for jumping back from the deferred code. // a branch instruction for jumping back from the deferred code.
Address address_after_call = address + Assembler::kCallTargetAddressOffset; Address address_after_call = address + Assembler::kCallTargetAddressOffset;
Instr instr_after_call = Assembler::instr_at(address_after_call); Instr instr_after_call = Assembler::instr_at(address_after_call);
if (!Assembler::IsNop(instr_after_call, PROPERTY_ACCESS_INLINED)) { int code_marker = MacroAssembler::GetCodeMarker(instr_after_call);
return false;
} // A negative result means the code is not marked.
if (code_marker <= 0) return 0;
Address address_after_nop = address_after_call + Assembler::kInstrSize; Address address_after_nop = address_after_call + Assembler::kInstrSize;
Instr instr_after_nop = Assembler::instr_at(address_after_nop); Instr instr_after_nop = Assembler::instr_at(address_after_nop);
// There may be some reg-reg move and frame merging code to skip over before // There may be some reg-reg move and frame merging code to skip over before
@ -933,7 +935,7 @@ static inline bool IsInlinedICSite(Address address,
ASSERT(b_offset < 0); // Jumping back from deferred code. ASSERT(b_offset < 0); // Jumping back from deferred code.
*inline_end_address = address_after_nop + b_offset; *inline_end_address = address_after_nop + b_offset;
return true; return code_marker;
} }
@ -941,7 +943,10 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
// Find the end of the inlined code for handling the load if this is an // Find the end of the inlined code for handling the load if this is an
// inlined IC call site. // inlined IC call site.
Address inline_end_address; Address inline_end_address;
if (!IsInlinedICSite(address, &inline_end_address)) return false; if (InlinedICSiteMarker(address, &inline_end_address)
!= Assembler::PROPERTY_ACCESS_INLINED) {
return false;
}
// Patch the offset of the property load instruction (ldr r0, [r1, #+XXX]). // Patch the offset of the property load instruction (ldr r0, [r1, #+XXX]).
// The immediate must be representable in 12 bits. // The immediate must be representable in 12 bits.
@ -959,8 +964,12 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
CPU::FlushICache(ldr_property_instr_address, 1 * Assembler::kInstrSize); CPU::FlushICache(ldr_property_instr_address, 1 * Assembler::kInstrSize);
// Patch the map check. // Patch the map check.
// For PROPERTY_ACCESS_INLINED, the load map instruction is generated
// 4 instructions before the end of the inlined code.
// See codgen-arm.cc CodeGenerator::EmitNamedLoad.
int ldr_map_offset = -4;
Address ldr_map_instr_address = Address ldr_map_instr_address =
inline_end_address - 4 * Assembler::kInstrSize; inline_end_address + ldr_map_offset * Assembler::kInstrSize;
Assembler::set_target_address_at(ldr_map_instr_address, Assembler::set_target_address_at(ldr_map_instr_address,
reinterpret_cast<Address>(map)); reinterpret_cast<Address>(map));
return true; return true;
@ -971,8 +980,41 @@ bool LoadIC::PatchInlinedContextualLoad(Address address,
Object* map, Object* map,
Object* cell, Object* cell,
bool is_dont_delete) { bool is_dont_delete) {
// TODO(<bug#>): implement this. // Find the end of the inlined code for handling the contextual load if
// this is inlined IC call site.
Address inline_end_address;
int marker = InlinedICSiteMarker(address, &inline_end_address);
if (!((marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT) ||
(marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE))) {
return false; return false;
}
// On ARM we don't rely on the is_dont_delete argument as the hint is already
// embedded in the code marker.
bool marker_is_dont_delete =
marker == Assembler::PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE;
// These are the offsets from the end of the inlined code.
// See codgen-arm.cc CodeGenerator::EmitNamedLoad.
int ldr_map_offset = marker_is_dont_delete ? -5: -8;
int ldr_cell_offset = marker_is_dont_delete ? -2: -5;
if (FLAG_debug_code && marker_is_dont_delete) {
// Three extra instructions were generated to check for the_hole_value.
ldr_map_offset -= 3;
ldr_cell_offset -= 3;
}
Address ldr_map_instr_address =
inline_end_address + ldr_map_offset * Assembler::kInstrSize;
Address ldr_cell_instr_address =
inline_end_address + ldr_cell_offset * Assembler::kInstrSize;
// Patch the map check.
Assembler::set_target_address_at(ldr_map_instr_address,
reinterpret_cast<Address>(map));
// Patch the cell address.
Assembler::set_target_address_at(ldr_cell_instr_address,
reinterpret_cast<Address>(cell));
return true;
} }
@ -980,7 +1022,10 @@ bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) {
// Find the end of the inlined code for the store if there is an // Find the end of the inlined code for the store if there is an
// inlined version of the store. // inlined version of the store.
Address inline_end_address; Address inline_end_address;
if (!IsInlinedICSite(address, &inline_end_address)) return false; if (InlinedICSiteMarker(address, &inline_end_address)
!= Assembler::PROPERTY_ACCESS_INLINED) {
return false;
}
// Compute the address of the map load instruction. // Compute the address of the map load instruction.
Address ldr_map_instr_address = Address ldr_map_instr_address =
@ -1025,7 +1070,10 @@ bool StoreIC::PatchInlinedStore(Address address, Object* map, int offset) {
bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) { bool KeyedLoadIC::PatchInlinedLoad(Address address, Object* map) {
Address inline_end_address; Address inline_end_address;
if (!IsInlinedICSite(address, &inline_end_address)) return false; if (InlinedICSiteMarker(address, &inline_end_address)
!= Assembler::PROPERTY_ACCESS_INLINED) {
return false;
}
// Patch the map check. // Patch the map check.
Address ldr_map_instr_address = Address ldr_map_instr_address =
@ -1042,7 +1090,10 @@ bool KeyedStoreIC::PatchInlinedStore(Address address, Object* map) {
// Find the end of the inlined code for handling the store if this is an // Find the end of the inlined code for handling the store if this is an
// inlined IC call site. // inlined IC call site.
Address inline_end_address; Address inline_end_address;
if (!IsInlinedICSite(address, &inline_end_address)) return false; if (InlinedICSiteMarker(address, &inline_end_address)
!= Assembler::PROPERTY_ACCESS_INLINED) {
return false;
}
// Patch the map check. // Patch the map check.
Address ldr_map_instr_address = Address ldr_map_instr_address =

27
deps/v8/src/arm/macro-assembler-arm.cc

@ -1693,6 +1693,33 @@ void MacroAssembler::LoadContext(Register dst, int context_chain_length) {
} }
void MacroAssembler::LoadGlobalFunction(int index, Register function) {
// Load the global or builtins object from the current context.
ldr(function, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
// Load the global context from the global or builtins object.
ldr(function, FieldMemOperand(function,
GlobalObject::kGlobalContextOffset));
// Load the function from the global context.
ldr(function, MemOperand(function, Context::SlotOffset(index)));
}
void MacroAssembler::LoadGlobalFunctionInitialMap(Register function,
Register map,
Register scratch) {
// Load the initial map. The global functions all have initial maps.
ldr(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
if (FLAG_debug_code) {
Label ok, fail;
CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, false);
b(&ok);
bind(&fail);
Abort("Global functions must have initial map");
bind(&ok);
}
}
void MacroAssembler::JumpIfNotBothSmi(Register reg1, void MacroAssembler::JumpIfNotBothSmi(Register reg1,
Register reg2, Register reg2,
Label* on_not_both_smi) { Label* on_not_both_smi) {

42
deps/v8/src/arm/macro-assembler-arm.h

@ -264,6 +264,14 @@ class MacroAssembler: public Assembler {
void LoadContext(Register dst, int context_chain_length); void LoadContext(Register dst, int context_chain_length);
void LoadGlobalFunction(int index, Register function);
// Load the initial map from the global function. The registers
// function and map can be the same, function is then overwritten.
void LoadGlobalFunctionInitialMap(Register function,
Register map,
Register scratch);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// JavaScript invokes // JavaScript invokes
@ -319,6 +327,40 @@ class MacroAssembler: public Assembler {
Register scratch, Register scratch,
Label* miss); Label* miss);
inline void MarkCode(NopMarkerTypes type) {
nop(type);
}
// Check if the given instruction is a 'type' marker.
// ie. check if is is a mov r<type>, r<type> (referenced as nop(type))
// These instructions are generated to mark special location in the code,
// like some special IC code.
static inline bool IsMarkedCode(Instr instr, int type) {
ASSERT((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER));
return IsNop(instr, type);
}
static inline int GetCodeMarker(Instr instr) {
int dst_reg_offset = 12;
int dst_mask = 0xf << dst_reg_offset;
int src_mask = 0xf;
int dst_reg = (instr & dst_mask) >> dst_reg_offset;
int src_reg = instr & src_mask;
uint32_t non_register_mask = ~(dst_mask | src_mask);
uint32_t mov_mask = al | 13 << 21;
// Return <n> if we have a mov rn rn, else return -1.
int type = ((instr & non_register_mask) == mov_mask) &&
(dst_reg == src_reg) &&
(FIRST_IC_MARKER <= dst_reg) && (dst_reg < LAST_CODE_MARKER)
? src_reg
: -1;
ASSERT((type == -1) ||
((FIRST_IC_MARKER <= type) && (type < LAST_CODE_MARKER)));
return type;
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Allocation support // Allocation support

7
deps/v8/src/arm/stub-cache-arm.cc

@ -2902,8 +2902,7 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
} }
MaybeObject* ConstructStubCompiler::CompileConstructStub( MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
SharedFunctionInfo* shared) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : argc // -- r0 : argc
// -- r1 : constructor // -- r1 : constructor
@ -2987,6 +2986,7 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(
// r7: undefined // r7: undefined
// Fill the initialized properties with a constant value or a passed argument // Fill the initialized properties with a constant value or a passed argument
// depending on the this.x = ...; assignment in the function. // depending on the this.x = ...; assignment in the function.
SharedFunctionInfo* shared = function->shared();
for (int i = 0; i < shared->this_property_assignments_count(); i++) { for (int i = 0; i < shared->this_property_assignments_count(); i++) {
if (shared->IsThisPropertyAssignmentArgument(i)) { if (shared->IsThisPropertyAssignmentArgument(i)) {
Label not_passed, next; Label not_passed, next;
@ -3011,8 +3011,9 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(
} }
// Fill the unused in-object property fields with undefined. // Fill the unused in-object property fields with undefined.
ASSERT(function->has_initial_map());
for (int i = shared->this_property_assignments_count(); for (int i = shared->this_property_assignments_count();
i < shared->CalculateInObjectProperties(); i < function->initial_map()->inobject_properties();
i++) { i++) {
__ str(r7, MemOperand(r5, kPointerSize, PostIndex)); __ str(r7, MemOperand(r5, kPointerSize, PostIndex));
} }

1
deps/v8/src/checks.cc

@ -107,3 +107,4 @@ namespace v8 { namespace internal {
intptr_t HeapObjectTagMask() { return kHeapObjectTagMask; } intptr_t HeapObjectTagMask() { return kHeapObjectTagMask; }
} } // namespace v8::internal } } // namespace v8::internal

34
deps/v8/src/checks.h

@ -31,7 +31,6 @@
#include <string.h> #include <string.h>
extern "C" void V8_Fatal(const char* file, int line, const char* format, ...); extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
void API_Fatal(const char* location, const char* format, ...);
// The FATAL, UNREACHABLE and UNIMPLEMENTED macros are useful during // The FATAL, UNREACHABLE and UNIMPLEMENTED macros are useful during
// development, but they should not be relied on in the final product. // development, but they should not be relied on in the final product.
@ -222,28 +221,6 @@ static inline void CheckNonEqualsHelper(const char* file,
} }
namespace v8 {
class Value;
template <class T> class Handle;
}
void CheckNonEqualsHelper(const char* file,
int line,
const char* unexpected_source,
v8::Handle<v8::Value> unexpected,
const char* value_source,
v8::Handle<v8::Value> value);
void CheckEqualsHelper(const char* file,
int line,
const char* expected_source,
v8::Handle<v8::Value> expected,
const char* value_source,
v8::Handle<v8::Value> value);
#define CHECK_EQ(expected, value) CheckEqualsHelper(__FILE__, __LINE__, \ #define CHECK_EQ(expected, value) CheckEqualsHelper(__FILE__, __LINE__, \
#expected, expected, #value, value) #expected, expected, #value, value)
@ -307,17 +284,6 @@ bool EnableSlowAsserts();
// and release compilation modes behaviour. // and release compilation modes behaviour.
#define STATIC_ASSERT(test) STATIC_CHECK(test) #define STATIC_ASSERT(test) STATIC_CHECK(test)
namespace v8 { namespace internal {
intptr_t HeapObjectTagMask();
} } // namespace v8::internal
#define ASSERT_TAG_ALIGNED(address) \
ASSERT((reinterpret_cast<intptr_t>(address) & HeapObjectTagMask()) == 0)
#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & HeapObjectTagMask()) == 0)
#define ASSERT_NOT_NULL(p) ASSERT_NE(NULL, p) #define ASSERT_NOT_NULL(p) ASSERT_NE(NULL, p)
#endif // V8_CHECKS_H_ #endif // V8_CHECKS_H_

6
deps/v8/src/conversions.cc

@ -448,12 +448,12 @@ static double InternalStringToDouble(Iterator current,
bool sign = false; bool sign = false;
if (*current == '+') { if (*current == '+') {
// Ignore leading sign; skip following spaces. // Ignore leading sign.
++current; ++current;
if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE; if (current == end) return JUNK_STRING_VALUE;
} else if (*current == '-') { } else if (*current == '-') {
++current; ++current;
if (!AdvanceToNonspace(&current, end)) return JUNK_STRING_VALUE; if (current == end) return JUNK_STRING_VALUE;
sign = true; sign = true;
} }

2
deps/v8/src/dateparser-inl.h

@ -59,7 +59,7 @@ bool DateParser::Parse(Vector<Char> str, FixedArray* out) {
} else if (in.Skip('.') && time.IsExpecting(n)) { } else if (in.Skip('.') && time.IsExpecting(n)) {
time.Add(n); time.Add(n);
if (!in.IsAsciiDigit()) return false; if (!in.IsAsciiDigit()) return false;
int n = in.ReadUnsignedNumber(); int n = in.ReadMilliseconds();
time.AddFinal(n); time.AddFinal(n);
} else if (tz.IsExpecting(n)) { } else if (tz.IsExpecting(n)) {
tz.SetAbsoluteMinute(n); tz.SetAbsoluteMinute(n);

12
deps/v8/src/dateparser.h

@ -87,6 +87,18 @@ class DateParser : public AllStatic {
return n; return n;
} }
// Read a string of digits, take the first three or fewer as an unsigned
// number of milliseconds, and ignore any digits after the first three.
int ReadMilliseconds() {
has_read_number_ = true;
int n = 0;
int power;
for (power = 100; IsAsciiDigit(); Next(), power = power / 10) {
n = n + power * (ch_ - '0');
}
return n;
}
// Read a word (sequence of chars. >= 'A'), fill the given buffer with a // Read a word (sequence of chars. >= 'A'), fill the given buffer with a
// lower-case prefix, and pad any remainder of the buffer with zeroes. // lower-case prefix, and pad any remainder of the buffer with zeroes.
// Return word length. // Return word length.

2
deps/v8/src/handles.cc

@ -143,7 +143,7 @@ Handle<JSGlobalProxy> ReinitializeJSGlobalProxy(
void SetExpectedNofProperties(Handle<JSFunction> func, int nof) { void SetExpectedNofProperties(Handle<JSFunction> func, int nof) {
// If objects constructed from this function exist then changing // If objects constructed from this function exist then changing
// 'estimated_nof_properties' is dangerous since the previois value might // 'estimated_nof_properties' is dangerous since the previous value might
// have been compiled into the fast construct stub. More over, the inobject // have been compiled into the fast construct stub. More over, the inobject
// slack tracking logic might have adjusted the previous value, so even // slack tracking logic might have adjusted the previous value, so even
// passing the same value is risky. // passing the same value is risky.

8
deps/v8/src/hashmap.cc

@ -25,7 +25,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h" #include "../include/v8stdint.h"
#include "globals.h"
#include "checks.h"
#include "utils.h"
#include "allocation.h"
#include "hashmap.h" #include "hashmap.h"
@ -195,7 +199,7 @@ void HashMap::Initialize(uint32_t capacity) {
ASSERT(IsPowerOf2(capacity)); ASSERT(IsPowerOf2(capacity));
map_ = reinterpret_cast<Entry*>(allocator_->New(capacity * sizeof(Entry))); map_ = reinterpret_cast<Entry*>(allocator_->New(capacity * sizeof(Entry)));
if (map_ == NULL) { if (map_ == NULL) {
V8::FatalProcessOutOfMemory("HashMap::Initialize"); v8::internal::FatalProcessOutOfMemory("HashMap::Initialize");
return; return;
} }
capacity_ = capacity; capacity_ = capacity;

10
deps/v8/src/heap-profiler.cc

@ -69,7 +69,8 @@ class Clusterizer : public AllStatic {
JSObjectsCluster Clusterizer::Clusterize(HeapObject* obj, bool fine_grain) { JSObjectsCluster Clusterizer::Clusterize(HeapObject* obj, bool fine_grain) {
if (obj->IsJSObject()) { if (obj->IsJSObject()) {
JSObject* js_obj = JSObject::cast(obj); JSObject* js_obj = JSObject::cast(obj);
String* constructor = JSObject::cast(js_obj)->constructor_name(); String* constructor = GetConstructorNameForHeapProfile(
JSObject::cast(js_obj));
// Differentiate Object and Array instances. // Differentiate Object and Array instances.
if (fine_grain && (constructor == Heap::Object_symbol() || if (fine_grain && (constructor == Heap::Object_symbol() ||
constructor == Heap::Array_symbol())) { constructor == Heap::Array_symbol())) {
@ -714,7 +715,7 @@ static void StackWeakReferenceCallback(Persistent<Value> object,
static void PrintProducerStackTrace(Object* obj, void* trace) { static void PrintProducerStackTrace(Object* obj, void* trace) {
if (!obj->IsJSObject()) return; if (!obj->IsJSObject()) return;
String* constructor = JSObject::cast(obj)->constructor_name(); String* constructor = GetConstructorNameForHeapProfile(JSObject::cast(obj));
SmartPointer<char> s_name( SmartPointer<char> s_name(
constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL)); constructor->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL));
LOG(HeapSampleJSProducerEvent(GetConstructorName(*s_name), LOG(HeapSampleJSProducerEvent(GetConstructorName(*s_name),
@ -886,7 +887,8 @@ static JSObjectsCluster HeapObjectAsCluster(HeapObject* object) {
return JSObjectsCluster(String::cast(object)); return JSObjectsCluster(String::cast(object));
} else { } else {
JSObject* js_obj = JSObject::cast(object); JSObject* js_obj = JSObject::cast(object);
String* constructor = JSObject::cast(js_obj)->constructor_name(); String* constructor = GetConstructorNameForHeapProfile(
JSObject::cast(js_obj));
return JSObjectsCluster(constructor, object); return JSObjectsCluster(constructor, object);
} }
} }
@ -1064,6 +1066,8 @@ void AggregatedHeapSnapshotGenerator::FillHeapSnapshot(HeapSnapshot* snapshot) {
// Fill up references. // Fill up references.
IterateRetainers<AllocatingRetainersIterator>(&entries_map); IterateRetainers<AllocatingRetainersIterator>(&entries_map);
snapshot->SetDominatorsToSelf();
} }

8
deps/v8/src/ia32/macro-assembler-ia32.cc

@ -537,7 +537,6 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
void MacroAssembler::LoadAllocationTopHelper(Register result, void MacroAssembler::LoadAllocationTopHelper(Register result,
Register result_end,
Register scratch, Register scratch,
AllocationFlags flags) { AllocationFlags flags) {
ExternalReference new_space_allocation_top = ExternalReference new_space_allocation_top =
@ -559,7 +558,6 @@ void MacroAssembler::LoadAllocationTopHelper(Register result,
if (scratch.is(no_reg)) { if (scratch.is(no_reg)) {
mov(result, Operand::StaticVariable(new_space_allocation_top)); mov(result, Operand::StaticVariable(new_space_allocation_top));
} else { } else {
ASSERT(!scratch.is(result_end));
mov(Operand(scratch), Immediate(new_space_allocation_top)); mov(Operand(scratch), Immediate(new_space_allocation_top));
mov(result, Operand(scratch, 0)); mov(result, Operand(scratch, 0));
} }
@ -608,7 +606,7 @@ void MacroAssembler::AllocateInNewSpace(int object_size,
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
LoadAllocationTopHelper(result, result_end, scratch, flags); LoadAllocationTopHelper(result, scratch, flags);
Register top_reg = result_end.is_valid() ? result_end : result; Register top_reg = result_end.is_valid() ? result_end : result;
@ -664,7 +662,7 @@ void MacroAssembler::AllocateInNewSpace(int header_size,
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
LoadAllocationTopHelper(result, result_end, scratch, flags); LoadAllocationTopHelper(result, scratch, flags);
// Calculate new top and bail out if new space is exhausted. // Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit = ExternalReference new_space_allocation_limit =
@ -705,7 +703,7 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
LoadAllocationTopHelper(result, result_end, scratch, flags); LoadAllocationTopHelper(result, scratch, flags);
// Calculate new top and bail out if new space is exhausted. // Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit = ExternalReference new_space_allocation_limit =

1
deps/v8/src/ia32/macro-assembler-ia32.h

@ -631,7 +631,6 @@ class MacroAssembler: public Assembler {
// Allocation support helpers. // Allocation support helpers.
void LoadAllocationTopHelper(Register result, void LoadAllocationTopHelper(Register result,
Register result_end,
Register scratch, Register scratch,
AllocationFlags flags); AllocationFlags flags);
void UpdateAllocationTopHelper(Register result_end, Register scratch); void UpdateAllocationTopHelper(Register result_end, Register scratch);

7
deps/v8/src/ia32/stub-cache-ia32.cc

@ -3021,8 +3021,7 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
// Specialized stub for constructing objects from functions which only have only // Specialized stub for constructing objects from functions which only have only
// simple assignments of the form this.x = ...; in their body. // simple assignments of the form this.x = ...; in their body.
MaybeObject* ConstructStubCompiler::CompileConstructStub( MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
SharedFunctionInfo* shared) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : argc // -- eax : argc
// -- edi : constructor // -- edi : constructor
@ -3098,6 +3097,7 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(
// edi: undefined // edi: undefined
// Fill the initialized properties with a constant value or a passed argument // Fill the initialized properties with a constant value or a passed argument
// depending on the this.x = ...; assignment in the function. // depending on the this.x = ...; assignment in the function.
SharedFunctionInfo* shared = function->shared();
for (int i = 0; i < shared->this_property_assignments_count(); i++) { for (int i = 0; i < shared->this_property_assignments_count(); i++) {
if (shared->IsThisPropertyAssignmentArgument(i)) { if (shared->IsThisPropertyAssignmentArgument(i)) {
// Check if the argument assigned to the property is actually passed. // Check if the argument assigned to the property is actually passed.
@ -3125,8 +3125,9 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(
} }
// Fill the unused in-object property fields with undefined. // Fill the unused in-object property fields with undefined.
ASSERT(function->has_initial_map());
for (int i = shared->this_property_assignments_count(); for (int i = shared->this_property_assignments_count();
i < shared->CalculateInObjectProperties(); i < function->initial_map()->inobject_properties();
i++) { i++) {
__ mov(Operand(edx, i * kPointerSize), edi); __ mov(Operand(edx, i * kPointerSize), edi);
} }

11
deps/v8/src/log.cc

@ -194,11 +194,6 @@ class Ticker: public Sampler {
~Ticker() { if (IsActive()) Stop(); } ~Ticker() { if (IsActive()) Stop(); }
virtual void SampleStack(TickSample* sample) {
ASSERT(IsSynchronous());
StackTracer::Trace(sample);
}
virtual void Tick(TickSample* sample) { virtual void Tick(TickSample* sample) {
if (profiler_) profiler_->Insert(sample); if (profiler_) profiler_->Insert(sample);
if (window_) window_->AddState(sample->state); if (window_) window_->AddState(sample->state);
@ -224,6 +219,12 @@ class Ticker: public Sampler {
if (!window_ && IsActive()) Stop(); if (!window_ && IsActive()) Stop();
} }
protected:
virtual void DoSampleStack(TickSample* sample) {
ASSERT(IsSynchronous());
StackTracer::Trace(sample);
}
private: private:
SlidingStateWindow* window_; SlidingStateWindow* window_;
Profiler* profiler_; Profiler* profiler_;

3
deps/v8/src/objects.cc

@ -1166,9 +1166,6 @@ String* JSObject::class_name() {
String* JSObject::constructor_name() { String* JSObject::constructor_name() {
if (IsJSFunction()) {
return Heap::closure_symbol();
}
if (map()->constructor()->IsJSFunction()) { if (map()->constructor()->IsJSFunction()) {
JSFunction* constructor = JSFunction::cast(map()->constructor()); JSFunction* constructor = JSFunction::cast(map()->constructor());
String* name = String::cast(constructor->shared()->name()); String* name = String::cast(constructor->shared()->name());

193
deps/v8/src/parser.cc

@ -356,65 +356,6 @@ Handle<String> Parser::LookupCachedSymbol(int symbol_id,
} }
Vector<unsigned> PartialParserRecorder::ExtractData() {
int function_size = function_store_.size();
int total_size = ScriptDataImpl::kHeaderSize + function_size;
Vector<unsigned> data = Vector<unsigned>::New(total_size);
preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size;
preamble_[ScriptDataImpl::kSymbolCountOffset] = 0;
memcpy(data.start(), preamble_, sizeof(preamble_));
int symbol_start = ScriptDataImpl::kHeaderSize + function_size;
if (function_size > 0) {
function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize,
symbol_start));
}
return data;
}
void CompleteParserRecorder::LogSymbol(int start, Vector<const char> literal) {
if (!is_recording_) return;
int hash = vector_hash(literal);
HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
if (id == 0) {
// Put (symbol_id_ + 1) into entry and increment it.
id = ++symbol_id_;
entry->value = reinterpret_cast<void*>(id);
Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
entry->key = &symbol[0];
}
WriteNumber(id - 1);
}
Vector<unsigned> CompleteParserRecorder::ExtractData() {
int function_size = function_store_.size();
// Add terminator to symbols, then pad to unsigned size.
int symbol_size = symbol_store_.size();
int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned));
symbol_store_.AddBlock(padding, ScriptDataImpl::kNumberTerminator);
symbol_size += padding;
int total_size = ScriptDataImpl::kHeaderSize + function_size
+ (symbol_size / sizeof(unsigned));
Vector<unsigned> data = Vector<unsigned>::New(total_size);
preamble_[ScriptDataImpl::kFunctionsSizeOffset] = function_size;
preamble_[ScriptDataImpl::kSymbolCountOffset] = symbol_id_;
memcpy(data.start(), preamble_, sizeof(preamble_));
int symbol_start = ScriptDataImpl::kHeaderSize + function_size;
if (function_size > 0) {
function_store_.WriteTo(data.SubVector(ScriptDataImpl::kHeaderSize,
symbol_start));
}
if (!has_error()) {
symbol_store_.WriteTo(
Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
}
return data;
}
FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) { FunctionEntry ScriptDataImpl::GetFunctionEntry(int start) {
// The current pre-data entry must be a FunctionEntry with the given // The current pre-data entry must be a FunctionEntry with the given
// start position. // start position.
@ -437,92 +378,52 @@ int ScriptDataImpl::GetSymbolIdentifier() {
bool ScriptDataImpl::SanityCheck() { bool ScriptDataImpl::SanityCheck() {
// Check that the header data is valid and doesn't specify // Check that the header data is valid and doesn't specify
// point to positions outside the store. // point to positions outside the store.
if (store_.length() < ScriptDataImpl::kHeaderSize) return false; if (store_.length() < PreparseDataConstants::kHeaderSize) return false;
if (magic() != ScriptDataImpl::kMagicNumber) return false; if (magic() != PreparseDataConstants::kMagicNumber) return false;
if (version() != ScriptDataImpl::kCurrentVersion) return false; if (version() != PreparseDataConstants::kCurrentVersion) return false;
if (has_error()) { if (has_error()) {
// Extra sane sanity check for error message encoding. // Extra sane sanity check for error message encoding.
if (store_.length() <= kHeaderSize + kMessageTextPos) return false; if (store_.length() <= PreparseDataConstants::kHeaderSize
if (Read(kMessageStartPos) > Read(kMessageEndPos)) return false; + PreparseDataConstants::kMessageTextPos) {
unsigned arg_count = Read(kMessageArgCountPos); return false;
int pos = kMessageTextPos; }
if (Read(PreparseDataConstants::kMessageStartPos) >
Read(PreparseDataConstants::kMessageEndPos)) {
return false;
}
unsigned arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
int pos = PreparseDataConstants::kMessageTextPos;
for (unsigned int i = 0; i <= arg_count; i++) { for (unsigned int i = 0; i <= arg_count; i++) {
if (store_.length() <= kHeaderSize + pos) return false; if (store_.length() <= PreparseDataConstants::kHeaderSize + pos) {
return false;
}
int length = static_cast<int>(Read(pos)); int length = static_cast<int>(Read(pos));
if (length < 0) return false; if (length < 0) return false;
pos += 1 + length; pos += 1 + length;
} }
if (store_.length() < kHeaderSize + pos) return false; if (store_.length() < PreparseDataConstants::kHeaderSize + pos) {
return false;
}
return true; return true;
} }
// Check that the space allocated for function entries is sane. // Check that the space allocated for function entries is sane.
int functions_size = int functions_size =
static_cast<int>(store_[ScriptDataImpl::kFunctionsSizeOffset]); static_cast<int>(store_[PreparseDataConstants::kFunctionsSizeOffset]);
if (functions_size < 0) return false; if (functions_size < 0) return false;
if (functions_size % FunctionEntry::kSize != 0) return false; if (functions_size % FunctionEntry::kSize != 0) return false;
// Check that the count of symbols is non-negative. // Check that the count of symbols is non-negative.
int symbol_count = int symbol_count =
static_cast<int>(store_[ScriptDataImpl::kSymbolCountOffset]); static_cast<int>(store_[PreparseDataConstants::kSymbolCountOffset]);
if (symbol_count < 0) return false; if (symbol_count < 0) return false;
// Check that the total size has room for header and function entries. // Check that the total size has room for header and function entries.
int minimum_size = int minimum_size =
ScriptDataImpl::kHeaderSize + functions_size; PreparseDataConstants::kHeaderSize + functions_size;
if (store_.length() < minimum_size) return false; if (store_.length() < minimum_size) return false;
return true; return true;
} }
PartialParserRecorder::PartialParserRecorder()
: function_store_(0),
is_recording_(true),
pause_count_(0) {
preamble_[ScriptDataImpl::kMagicOffset] = ScriptDataImpl::kMagicNumber;
preamble_[ScriptDataImpl::kVersionOffset] = ScriptDataImpl::kCurrentVersion;
preamble_[ScriptDataImpl::kHasErrorOffset] = false;
preamble_[ScriptDataImpl::kFunctionsSizeOffset] = 0;
preamble_[ScriptDataImpl::kSymbolCountOffset] = 0;
preamble_[ScriptDataImpl::kSizeOffset] = 0;
ASSERT_EQ(6, ScriptDataImpl::kHeaderSize);
#ifdef DEBUG
prev_start_ = -1;
#endif
}
CompleteParserRecorder::CompleteParserRecorder()
: PartialParserRecorder(),
symbol_store_(0),
symbol_entries_(0),
symbol_table_(vector_compare),
symbol_id_(0) {
}
void PartialParserRecorder::WriteString(Vector<const char> str) {
function_store_.Add(str.length());
for (int i = 0; i < str.length(); i++) {
function_store_.Add(str[i]);
}
}
void CompleteParserRecorder::WriteNumber(int number) {
ASSERT(number >= 0);
int mask = (1 << 28) - 1;
for (int i = 28; i > 0; i -= 7) {
if (number > mask) {
symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u);
number &= mask;
}
mask >>= 7;
}
symbol_store_.Add(static_cast<byte>(number));
}
const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) { const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
int length = start[0]; int length = start[0];
char* result = NewArray<char>(length + 1); char* result = NewArray<char>(length + 1);
@ -534,47 +435,26 @@ const char* ScriptDataImpl::ReadString(unsigned* start, int* chars) {
return result; return result;
} }
void PartialParserRecorder::LogMessage(Scanner::Location loc,
const char* message,
Vector<const char*> args) {
if (has_error()) return;
preamble_[ScriptDataImpl::kHasErrorOffset] = true;
function_store_.Reset();
STATIC_ASSERT(ScriptDataImpl::kMessageStartPos == 0);
function_store_.Add(loc.beg_pos);
STATIC_ASSERT(ScriptDataImpl::kMessageEndPos == 1);
function_store_.Add(loc.end_pos);
STATIC_ASSERT(ScriptDataImpl::kMessageArgCountPos == 2);
function_store_.Add(args.length());
STATIC_ASSERT(ScriptDataImpl::kMessageTextPos == 3);
WriteString(CStrVector(message));
for (int i = 0; i < args.length(); i++) {
WriteString(CStrVector(args[i]));
}
is_recording_ = false;
}
Scanner::Location ScriptDataImpl::MessageLocation() { Scanner::Location ScriptDataImpl::MessageLocation() {
int beg_pos = Read(kMessageStartPos); int beg_pos = Read(PreparseDataConstants::kMessageStartPos);
int end_pos = Read(kMessageEndPos); int end_pos = Read(PreparseDataConstants::kMessageEndPos);
return Scanner::Location(beg_pos, end_pos); return Scanner::Location(beg_pos, end_pos);
} }
const char* ScriptDataImpl::BuildMessage() { const char* ScriptDataImpl::BuildMessage() {
unsigned* start = ReadAddress(kMessageTextPos); unsigned* start = ReadAddress(PreparseDataConstants::kMessageTextPos);
return ReadString(start, NULL); return ReadString(start, NULL);
} }
Vector<const char*> ScriptDataImpl::BuildArgs() { Vector<const char*> ScriptDataImpl::BuildArgs() {
int arg_count = Read(kMessageArgCountPos); int arg_count = Read(PreparseDataConstants::kMessageArgCountPos);
const char** array = NewArray<const char*>(arg_count); const char** array = NewArray<const char*>(arg_count);
// Position after text found by skipping past length field and // Position after text found by skipping past length field and
// length field content words. // length field content words.
int pos = kMessageTextPos + 1 + Read(kMessageTextPos); int pos = PreparseDataConstants::kMessageTextPos + 1
+ Read(PreparseDataConstants::kMessageTextPos);
for (int i = 0; i < arg_count; i++) { for (int i = 0; i < arg_count; i++) {
int count = 0; int count = 0;
array[i] = ReadString(ReadAddress(pos), &count); array[i] = ReadString(ReadAddress(pos), &count);
@ -585,12 +465,12 @@ Vector<const char*> ScriptDataImpl::BuildArgs() {
unsigned ScriptDataImpl::Read(int position) { unsigned ScriptDataImpl::Read(int position) {
return store_[ScriptDataImpl::kHeaderSize + position]; return store_[PreparseDataConstants::kHeaderSize + position];
} }
unsigned* ScriptDataImpl::ReadAddress(int position) { unsigned* ScriptDataImpl::ReadAddress(int position) {
return &store_[ScriptDataImpl::kHeaderSize + position]; return &store_[PreparseDataConstants::kHeaderSize + position];
} }
@ -4601,9 +4481,10 @@ bool ScriptDataImpl::HasError() {
void ScriptDataImpl::Initialize() { void ScriptDataImpl::Initialize() {
// Prepares state for use. // Prepares state for use.
if (store_.length() >= kHeaderSize) { if (store_.length() >= PreparseDataConstants::kHeaderSize) {
function_index_ = kHeaderSize; function_index_ = PreparseDataConstants::kHeaderSize;
int symbol_data_offset = kHeaderSize + store_[kFunctionsSizeOffset]; int symbol_data_offset = PreparseDataConstants::kHeaderSize
+ store_[PreparseDataConstants::kFunctionsSizeOffset];
if (store_.length() > symbol_data_offset) { if (store_.length() > symbol_data_offset) {
symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]); symbol_data_ = reinterpret_cast<byte*>(&store_[symbol_data_offset]);
} else { } else {
@ -4625,7 +4506,7 @@ int ScriptDataImpl::ReadNumber(byte** source) {
byte* data = *source; byte* data = *source;
if (data >= symbol_data_end_) return -1; if (data >= symbol_data_end_) return -1;
byte input = *data; byte input = *data;
if (input == kNumberTerminator) { if (input == PreparseDataConstants::kNumberTerminator) {
// End of stream marker. // End of stream marker.
return -1; return -1;
} }
@ -4646,11 +4527,11 @@ int ScriptDataImpl::ReadNumber(byte** source) {
static ScriptDataImpl* DoPreParse(Handle<String> source, static ScriptDataImpl* DoPreParse(Handle<String> source,
unibrow::CharacterStream* stream, unibrow::CharacterStream* stream,
bool allow_lazy, bool allow_lazy,
PartialParserRecorder* recorder, ParserRecorder* recorder,
int literal_flags) { int literal_flags) {
V8JavaScriptScanner scanner; V8JavaScriptScanner scanner;
scanner.Initialize(source, stream, literal_flags); scanner.Initialize(source, stream, literal_flags);
preparser::PreParser<JavaScriptScanner, PartialParserRecorder> preparser; preparser::PreParser preparser;
if (!preparser.PreParseProgram(&scanner, recorder, allow_lazy)) { if (!preparser.PreParseProgram(&scanner, recorder, allow_lazy)) {
Top::StackOverflow(); Top::StackOverflow();
return NULL; return NULL;

151
deps/v8/src/parser.h

@ -32,6 +32,7 @@
#include "ast.h" #include "ast.h"
#include "scanner.h" #include "scanner.h"
#include "scopes.h" #include "scopes.h"
#include "preparse-data.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -123,32 +124,15 @@ class ScriptDataImpl : public ScriptData {
Vector<const char*> BuildArgs(); Vector<const char*> BuildArgs();
int symbol_count() { int symbol_count() {
return (store_.length() > kHeaderSize) ? store_[kSymbolCountOffset] : 0; return (store_.length() > PreparseDataConstants::kHeaderSize)
? store_[PreparseDataConstants::kSymbolCountOffset]
: 0;
} }
// The following functions should only be called if SanityCheck has // The following functions should only be called if SanityCheck has
// returned true. // returned true.
bool has_error() { return store_[kHasErrorOffset]; } bool has_error() { return store_[PreparseDataConstants::kHasErrorOffset]; }
unsigned magic() { return store_[kMagicOffset]; } unsigned magic() { return store_[PreparseDataConstants::kMagicOffset]; }
unsigned version() { return store_[kVersionOffset]; } unsigned version() { return store_[PreparseDataConstants::kVersionOffset]; }
static const unsigned kMagicNumber = 0xBadDead;
static const unsigned kCurrentVersion = 5;
static const int kMagicOffset = 0;
static const int kVersionOffset = 1;
static const int kHasErrorOffset = 2;
static const int kFunctionsSizeOffset = 3;
static const int kSymbolCountOffset = 4;
static const int kSizeOffset = 5;
static const int kHeaderSize = 6;
// If encoding a message, the following positions are fixed.
static const int kMessageStartPos = 0;
static const int kMessageEndPos = 1;
static const int kMessageArgCountPos = 2;
static const int kMessageTextPos = 3;
static const byte kNumberTerminator = 0x80u;
private: private:
Vector<unsigned> store_; Vector<unsigned> store_;
@ -177,127 +161,6 @@ class ScriptDataImpl : public ScriptData {
}; };
// Record only functions.
class PartialParserRecorder {
public:
PartialParserRecorder();
virtual ~PartialParserRecorder() {}
void LogFunction(int start, int end, int literals, int properties) {
function_store_.Add(start);
function_store_.Add(end);
function_store_.Add(literals);
function_store_.Add(properties);
}
virtual void LogSymbol(int start, const char* symbol, int length) { }
// Logs an error message and marks the log as containing an error.
// Further logging will be ignored, and ExtractData will return a vector
// representing the error only.
void LogMessage(int start,
int end,
const char* message,
const char* argument_opt) {
Scanner::Location location(start, end);
Vector<const char*> arguments;
if (argument_opt != NULL) {
arguments = Vector<const char*>(&argument_opt, 1);
}
this->LogMessage(location, message, arguments);
}
int function_position() { return function_store_.size(); }
void LogMessage(Scanner::Location loc,
const char* message,
Vector<const char*> args);
virtual Vector<unsigned> ExtractData();
void PauseRecording() {
pause_count_++;
is_recording_ = false;
}
void ResumeRecording() {
ASSERT(pause_count_ > 0);
if (--pause_count_ == 0) is_recording_ = !has_error();
}
int symbol_position() { return 0; }
int symbol_ids() { return 0; }
protected:
bool has_error() {
return static_cast<bool>(preamble_[ScriptDataImpl::kHasErrorOffset]);
}
bool is_recording() {
return is_recording_;
}
void WriteString(Vector<const char> str);
Collector<unsigned> function_store_;
unsigned preamble_[ScriptDataImpl::kHeaderSize];
bool is_recording_;
int pause_count_;
#ifdef DEBUG
int prev_start_;
#endif
};
// Record both functions and symbols.
class CompleteParserRecorder: public PartialParserRecorder {
public:
CompleteParserRecorder();
virtual ~CompleteParserRecorder() { }
void LogSymbol(int start, Vector<const char> literal);
virtual void LogSymbol(int start, const char* symbol, int length) {
LogSymbol(start, Vector<const char>(symbol, length));
}
virtual Vector<unsigned> ExtractData();
int symbol_position() { return symbol_store_.size(); }
int symbol_ids() { return symbol_id_; }
private:
static int vector_hash(Vector<const char> string) {
int hash = 0;
for (int i = 0; i < string.length(); i++) {
int c = string[i];
hash += c;
hash += (hash << 10);
hash ^= (hash >> 6);
}
return hash;
}
static bool vector_compare(void* a, void* b) {
Vector<const char>* string1 = reinterpret_cast<Vector<const char>* >(a);
Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(b);
int length = string1->length();
if (string2->length() != length) return false;
return memcmp(string1->start(), string2->start(), length) == 0;
}
// Write a non-negative number to the symbol store.
void WriteNumber(int number);
Collector<byte> symbol_store_;
Collector<Vector<const char> > symbol_entries_;
HashMap symbol_table_;
int symbol_id_;
};
class ParserApi { class ParserApi {
public: public:
// Parses the source code represented by the compilation info and sets its // Parses the source code represented by the compilation info and sets its

3
deps/v8/src/platform-freebsd.cc

@ -620,7 +620,8 @@ Sampler::Sampler(int interval, bool profiling)
: interval_(interval), : interval_(interval),
profiling_(profiling), profiling_(profiling),
synchronous_(profiling), synchronous_(profiling),
active_(false) { active_(false),
samples_taken_(0) {
data_ = new PlatformData(); data_ = new PlatformData();
} }

3
deps/v8/src/platform-linux.cc

@ -865,7 +865,8 @@ Sampler::Sampler(int interval, bool profiling)
: interval_(interval), : interval_(interval),
profiling_(profiling), profiling_(profiling),
synchronous_(profiling), synchronous_(profiling),
active_(false) { active_(false),
samples_taken_(0) {
data_ = new PlatformData(this); data_ = new PlatformData(this);
} }

3
deps/v8/src/platform-macos.cc

@ -634,7 +634,8 @@ Sampler::Sampler(int interval, bool profiling)
: interval_(interval), : interval_(interval),
profiling_(profiling), profiling_(profiling),
synchronous_(profiling), synchronous_(profiling),
active_(false) { active_(false),
samples_taken_(0) {
data_ = new PlatformData(this); data_ = new PlatformData(this);
} }

6
deps/v8/src/platform-openbsd.cc

@ -572,7 +572,11 @@ class Sampler::PlatformData : public Malloced {
Sampler::Sampler(int interval, bool profiling) Sampler::Sampler(int interval, bool profiling)
: interval_(interval), profiling_(profiling), active_(false) { : interval_(interval),
profiling_(profiling),
synchronous_(profiling),
active_(false),
samples_taken_(0) {
data_ = new PlatformData(); data_ = new PlatformData();
} }

3
deps/v8/src/platform-solaris.cc

@ -605,7 +605,8 @@ Sampler::Sampler(int interval, bool profiling)
: interval_(interval), : interval_(interval),
profiling_(profiling), profiling_(profiling),
synchronous_(profiling), synchronous_(profiling),
active_(false) { active_(false),
samples_taken_(0) {
data_ = new PlatformData(); data_ = new PlatformData();
} }

3
deps/v8/src/platform-win32.cc

@ -1903,7 +1903,8 @@ Sampler::Sampler(int interval, bool profiling)
: interval_(interval), : interval_(interval),
profiling_(profiling), profiling_(profiling),
synchronous_(profiling), synchronous_(profiling),
active_(false) { active_(false),
samples_taken_(0) {
data_ = new PlatformData(this); data_ = new PlatformData(this);
} }

17
deps/v8/src/platform.h

@ -559,11 +559,14 @@ class TickSample {
class Sampler { class Sampler {
public: public:
// Initialize sampler. // Initialize sampler.
explicit Sampler(int interval, bool profiling); Sampler(int interval, bool profiling);
virtual ~Sampler(); virtual ~Sampler();
// Performs stack sampling. // Performs stack sampling.
virtual void SampleStack(TickSample* sample) = 0; void SampleStack(TickSample* sample) {
DoSampleStack(sample);
IncSamplesTaken();
}
// This method is called for each sampling period with the current // This method is called for each sampling period with the current
// program counter. // program counter.
@ -585,14 +588,24 @@ class Sampler {
// Whether the sampler is running (that is, consumes resources). // Whether the sampler is running (that is, consumes resources).
bool IsActive() const { return active_; } bool IsActive() const { return active_; }
// Used in tests to make sure that stack sampling is performed.
int samples_taken() const { return samples_taken_; }
void ResetSamplesTaken() { samples_taken_ = 0; }
class PlatformData; class PlatformData;
protected:
virtual void DoSampleStack(TickSample* sample) = 0;
private: private:
void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
const int interval_; const int interval_;
const bool profiling_; const bool profiling_;
const bool synchronous_; const bool synchronous_;
bool active_; bool active_;
PlatformData* data_; // Platform specific data. PlatformData* data_; // Platform specific data.
int samples_taken_; // Counts stack samples taken.
DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler); DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
}; };

180
deps/v8/src/preparse-data.cc

@ -0,0 +1,180 @@
// Copyright 2010 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 "../include/v8stdint.h"
#include "globals.h"
#include "checks.h"
#include "allocation.h"
#include "utils.h"
#include "list-inl.h"
#include "hashmap.h"
#include "preparse-data.h"
namespace v8 {
namespace internal {
// ----------------------------------------------------------------------------
// FunctionLoggingParserRecorder
FunctionLoggingParserRecorder::FunctionLoggingParserRecorder()
: function_store_(0),
is_recording_(true),
pause_count_(0) {
preamble_[PreparseDataConstants::kMagicOffset] =
PreparseDataConstants::kMagicNumber;
preamble_[PreparseDataConstants::kVersionOffset] =
PreparseDataConstants::kCurrentVersion;
preamble_[PreparseDataConstants::kHasErrorOffset] = false;
preamble_[PreparseDataConstants::kFunctionsSizeOffset] = 0;
preamble_[PreparseDataConstants::kSymbolCountOffset] = 0;
preamble_[PreparseDataConstants::kSizeOffset] = 0;
ASSERT_EQ(6, PreparseDataConstants::kHeaderSize);
#ifdef DEBUG
prev_start_ = -1;
#endif
}
void FunctionLoggingParserRecorder::LogMessage(int start_pos,
int end_pos,
const char* message,
const char* arg_opt) {
if (has_error()) return;
preamble_[PreparseDataConstants::kHasErrorOffset] = true;
function_store_.Reset();
STATIC_ASSERT(PreparseDataConstants::kMessageStartPos == 0);
function_store_.Add(start_pos);
STATIC_ASSERT(PreparseDataConstants::kMessageEndPos == 1);
function_store_.Add(end_pos);
STATIC_ASSERT(PreparseDataConstants::kMessageArgCountPos == 2);
function_store_.Add((arg_opt == NULL) ? 0 : 1);
STATIC_ASSERT(PreparseDataConstants::kMessageTextPos == 3);
WriteString(CStrVector(message));
if (arg_opt) WriteString(CStrVector(arg_opt));
is_recording_ = false;
}
void FunctionLoggingParserRecorder::WriteString(Vector<const char> str) {
function_store_.Add(str.length());
for (int i = 0; i < str.length(); i++) {
function_store_.Add(str[i]);
}
}
// ----------------------------------------------------------------------------
// PartialParserRecorder - Record both function entries and symbols.
Vector<unsigned> PartialParserRecorder::ExtractData() {
int function_size = function_store_.size();
int total_size = PreparseDataConstants::kHeaderSize + function_size;
Vector<unsigned> data = Vector<unsigned>::New(total_size);
preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
preamble_[PreparseDataConstants::kSymbolCountOffset] = 0;
memcpy(data.start(), preamble_, sizeof(preamble_));
int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
if (function_size > 0) {
function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
symbol_start));
}
return data;
}
// ----------------------------------------------------------------------------
// CompleteParserRecorder - Record both function entries and symbols.
CompleteParserRecorder::CompleteParserRecorder()
: FunctionLoggingParserRecorder(),
symbol_store_(0),
symbol_entries_(0),
symbol_table_(vector_compare),
symbol_id_(0) {
}
void CompleteParserRecorder::LogSymbol(
int start, const char* literal_chars, int length) {
if (!is_recording_) return;
Vector<const char> literal(literal_chars, length);
int hash = vector_hash(literal);
HashMap::Entry* entry = symbol_table_.Lookup(&literal, hash, true);
int id = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
if (id == 0) {
// Put (symbol_id_ + 1) into entry and increment it.
id = ++symbol_id_;
entry->value = reinterpret_cast<void*>(id);
Vector<Vector<const char> > symbol = symbol_entries_.AddBlock(1, literal);
entry->key = &symbol[0];
}
WriteNumber(id - 1);
}
Vector<unsigned> CompleteParserRecorder::ExtractData() {
int function_size = function_store_.size();
// Add terminator to symbols, then pad to unsigned size.
int symbol_size = symbol_store_.size();
int padding = sizeof(unsigned) - (symbol_size % sizeof(unsigned));
symbol_store_.AddBlock(padding, PreparseDataConstants::kNumberTerminator);
symbol_size += padding;
int total_size = PreparseDataConstants::kHeaderSize + function_size
+ (symbol_size / sizeof(unsigned));
Vector<unsigned> data = Vector<unsigned>::New(total_size);
preamble_[PreparseDataConstants::kFunctionsSizeOffset] = function_size;
preamble_[PreparseDataConstants::kSymbolCountOffset] = symbol_id_;
memcpy(data.start(), preamble_, sizeof(preamble_));
int symbol_start = PreparseDataConstants::kHeaderSize + function_size;
if (function_size > 0) {
function_store_.WriteTo(data.SubVector(PreparseDataConstants::kHeaderSize,
symbol_start));
}
if (!has_error()) {
symbol_store_.WriteTo(
Vector<byte>::cast(data.SubVector(symbol_start, total_size)));
}
return data;
}
void CompleteParserRecorder::WriteNumber(int number) {
ASSERT(number >= 0);
int mask = (1 << 28) - 1;
for (int i = 28; i > 0; i -= 7) {
if (number > mask) {
symbol_store_.Add(static_cast<byte>(number >> i) | 0x80u);
number &= mask;
}
mask >>= 7;
}
symbol_store_.Add(static_cast<byte>(number));
}
} } // namespace v8::internal.

223
deps/v8/src/preparse-data.h

@ -0,0 +1,223 @@
// Copyright 2010 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_PREPARSER_DATA_H_
#define V8_PREPARSER_DATA_H_
#include "hashmap.h"
namespace v8 {
namespace internal {
// Generic and general data used by preparse data recorders and readers.
class PreparseDataConstants : public AllStatic {
public:
// Layout and constants of the preparse data exchange format.
static const unsigned kMagicNumber = 0xBadDead;
static const unsigned kCurrentVersion = 5;
static const int kMagicOffset = 0;
static const int kVersionOffset = 1;
static const int kHasErrorOffset = 2;
static const int kFunctionsSizeOffset = 3;
static const int kSymbolCountOffset = 4;
static const int kSizeOffset = 5;
static const int kHeaderSize = 6;
// If encoding a message, the following positions are fixed.
static const int kMessageStartPos = 0;
static const int kMessageEndPos = 1;
static const int kMessageArgCountPos = 2;
static const int kMessageTextPos = 3;
static const byte kNumberTerminator = 0x80u;
};
// ----------------------------------------------------------------------------
// ParserRecorder - Logging of preparser data.
// Abstract interface for preparse data recorder.
class ParserRecorder {
public:
ParserRecorder() { }
virtual ~ParserRecorder() { }
// Logs the scope and some details of a function literal in the source.
virtual void LogFunction(int start,
int end,
int literals,
int properties) = 0;
// Logs a symbol creation of a literal or identifier.
virtual void LogSymbol(int start, const char* symbol, int length) = 0;
// Logs an error message and marks the log as containing an error.
// Further logging will be ignored, and ExtractData will return a vector
// representing the error only.
virtual void LogMessage(int start,
int end,
const char* message,
const char* argument_opt) = 0;
virtual int function_position() = 0;
virtual int symbol_position() = 0;
virtual int symbol_ids() = 0;
virtual Vector<unsigned> ExtractData() = 0;
virtual void PauseRecording() = 0;
virtual void ResumeRecording() = 0;
};
// ----------------------------------------------------------------------------
// FunctionLoggingParserRecorder - Record only function entries
class FunctionLoggingParserRecorder : public ParserRecorder {
public:
FunctionLoggingParserRecorder();
virtual ~FunctionLoggingParserRecorder() {}
virtual void LogFunction(int start, int end, int literals, int properties) {
function_store_.Add(start);
function_store_.Add(end);
function_store_.Add(literals);
function_store_.Add(properties);
}
// Logs an error message and marks the log as containing an error.
// Further logging will be ignored, and ExtractData will return a vector
// representing the error only.
virtual void LogMessage(int start,
int end,
const char* message,
const char* argument_opt);
virtual int function_position() { return function_store_.size(); }
virtual Vector<unsigned> ExtractData() = 0;
virtual void PauseRecording() {
pause_count_++;
is_recording_ = false;
}
virtual void ResumeRecording() {
ASSERT(pause_count_ > 0);
if (--pause_count_ == 0) is_recording_ = !has_error();
}
protected:
bool has_error() {
return static_cast<bool>(preamble_[PreparseDataConstants::kHasErrorOffset]);
}
bool is_recording() {
return is_recording_;
}
void WriteString(Vector<const char> str);
Collector<unsigned> function_store_;
unsigned preamble_[PreparseDataConstants::kHeaderSize];
bool is_recording_;
int pause_count_;
#ifdef DEBUG
int prev_start_;
#endif
};
// ----------------------------------------------------------------------------
// PartialParserRecorder - Record only function entries
class PartialParserRecorder : public FunctionLoggingParserRecorder {
public:
PartialParserRecorder() : FunctionLoggingParserRecorder() { }
virtual void LogSymbol(int start, const char* symbol, int length) { }
virtual ~PartialParserRecorder() { }
virtual Vector<unsigned> ExtractData();
virtual int symbol_position() { return 0; }
virtual int symbol_ids() { return 0; }
};
// ----------------------------------------------------------------------------
// CompleteParserRecorder - Record both function entries and symbols.
class CompleteParserRecorder: public FunctionLoggingParserRecorder {
public:
CompleteParserRecorder();
virtual ~CompleteParserRecorder() { }
virtual void LogSymbol(int start, const char* symbol, int length);
virtual Vector<unsigned> ExtractData();
virtual int symbol_position() { return symbol_store_.size(); }
virtual int symbol_ids() { return symbol_id_; }
private:
static int vector_hash(Vector<const char> string) {
int hash = 0;
for (int i = 0; i < string.length(); i++) {
int c = string[i];
hash += c;
hash += (hash << 10);
hash ^= (hash >> 6);
}
return hash;
}
static bool vector_compare(void* a, void* b) {
Vector<const char>* string1 = reinterpret_cast<Vector<const char>* >(a);
Vector<const char>* string2 = reinterpret_cast<Vector<const char>* >(b);
int length = string1->length();
if (string2->length() != length) return false;
return memcmp(string1->start(), string2->start(), length) == 0;
}
// Write a non-negative number to the symbol store.
void WriteNumber(int number);
Collector<byte> symbol_store_;
Collector<Vector<const char> > symbol_entries_;
HashMap symbol_table_;
int symbol_id_;
};
} } // namespace v8::internal.
#endif // V8_PREPARSER_DATA_H_

1184
deps/v8/src/preparser.cc

File diff suppressed because it is too large

1188
deps/v8/src/preparser.h

File diff suppressed because it is too large

23
deps/v8/src/profile-generator.cc

@ -1295,8 +1295,8 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
} else if (object->IsJSObject()) { } else if (object->IsJSObject()) {
return AddEntry(object, return AddEntry(object,
HeapEntry::kObject, HeapEntry::kObject,
collection_->GetName( collection_->GetName(GetConstructorNameForHeapProfile(
JSObject::cast(object)->constructor_name()), JSObject::cast(object))),
children_count, children_count,
retainers_count); retainers_count);
} else if (object->IsString()) { } else if (object->IsString()) {
@ -1462,6 +1462,14 @@ void HeapSnapshot::BuildDominatorTree(const Vector<HeapEntry*>& entries,
} }
void HeapSnapshot::SetDominatorsToSelf() {
for (int i = 0; i < entries_.length(); ++i) {
HeapEntry* entry = entries_[i];
if (entry->dominator() == NULL) entry->set_dominator(entry);
}
}
void HeapSnapshot::SetEntriesDominators() { void HeapSnapshot::SetEntriesDominators() {
// This array is used for maintaining reverse postorder of nodes. // This array is used for maintaining reverse postorder of nodes.
ScopedVector<HeapEntry*> ordered_entries(entries_.length()); ScopedVector<HeapEntry*> ordered_entries(entries_.length());
@ -1473,10 +1481,7 @@ void HeapSnapshot::SetEntriesDominators() {
ordered_entries[i]->set_dominator(dominators[i]); ordered_entries[i]->set_dominator(dominators[i]);
} }
// For nodes unreachable from root, set dominator to itself. // For nodes unreachable from root, set dominator to itself.
for (int i = 0; i < entries_.length(); ++i) { SetDominatorsToSelf();
HeapEntry* entry = entries_[i];
if (entry->dominator() == NULL) entry->set_dominator(entry);
}
} }
@ -2764,6 +2769,12 @@ void HeapSnapshotJSONSerializer::SortHashMap(
sorted_entries->Sort(SortUsingEntryValue); sorted_entries->Sort(SortUsingEntryValue);
} }
String* GetConstructorNameForHeapProfile(JSObject* object) {
if (object->IsJSFunction()) return Heap::closure_symbol();
return object->constructor_name();
}
} } // namespace v8::internal } } // namespace v8::internal
#endif // ENABLE_LOGGING_AND_PROFILING #endif // ENABLE_LOGGING_AND_PROFILING

4
deps/v8/src/profile-generator.h

@ -700,6 +700,7 @@ class HeapSnapshot {
List<HeapEntry*>* GetSortedEntriesList(); List<HeapEntry*>* GetSortedEntriesList();
template<class Visitor> template<class Visitor>
void IterateEntries(Visitor* visitor) { entries_.Iterate(visitor); } void IterateEntries(Visitor* visitor) { entries_.Iterate(visitor); }
void SetDominatorsToSelf();
void Print(int max_depth); void Print(int max_depth);
void PrintEntriesSize(); void PrintEntriesSize();
@ -1072,6 +1073,9 @@ class HeapSnapshotJSONSerializer {
DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer); DISALLOW_COPY_AND_ASSIGN(HeapSnapshotJSONSerializer);
}; };
String* GetConstructorNameForHeapProfile(JSObject* object);
} } // namespace v8::internal } } // namespace v8::internal
#endif // ENABLE_LOGGING_AND_PROFILING #endif // ENABLE_LOGGING_AND_PROFILING

8
deps/v8/src/runtime.cc

@ -5020,11 +5020,12 @@ static int CopyCachedAsciiCharsToArray(const char* chars,
// For example, "foo" => ["f", "o", "o"]. // For example, "foo" => ["f", "o", "o"].
static MaybeObject* Runtime_StringToArray(Arguments args) { static MaybeObject* Runtime_StringToArray(Arguments args) {
HandleScope scope; HandleScope scope;
ASSERT(args.length() == 1); ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(String, s, 0); CONVERT_ARG_CHECKED(String, s, 0);
CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
s->TryFlatten(); s->TryFlatten();
const int length = s->length(); const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
Handle<FixedArray> elements; Handle<FixedArray> elements;
if (s->IsFlat() && s->IsAsciiRepresentation()) { if (s->IsFlat() && s->IsAsciiRepresentation()) {
@ -6391,7 +6392,7 @@ static void TrySettingInlineConstructStub(Handle<JSFunction> function) {
} }
if (function->shared()->CanGenerateInlineConstructor(*prototype)) { if (function->shared()->CanGenerateInlineConstructor(*prototype)) {
ConstructStubCompiler compiler; ConstructStubCompiler compiler;
MaybeObject* code = compiler.CompileConstructStub(function->shared()); MaybeObject* code = compiler.CompileConstructStub(*function);
if (!code->IsFailure()) { if (!code->IsFailure()) {
function->shared()->set_construct_stub( function->shared()->set_construct_stub(
Code::cast(code->ToObjectUnchecked())); Code::cast(code->ToObjectUnchecked()));
@ -6459,7 +6460,6 @@ static MaybeObject* Runtime_NewObject(Arguments args) {
// track one initial_map at a time, so we force the completion before the // track one initial_map at a time, so we force the completion before the
// function is called as a constructor for the first time. // function is called as a constructor for the first time.
shared->CompleteInobjectSlackTracking(); shared->CompleteInobjectSlackTracking();
TrySettingInlineConstructStub(function);
} }
bool first_allocation = !shared->live_objects_may_exist(); bool first_allocation = !shared->live_objects_may_exist();

2
deps/v8/src/runtime.h

@ -175,7 +175,7 @@ namespace internal {
F(StringReplaceRegExpWithString, 4, 1) \ F(StringReplaceRegExpWithString, 4, 1) \
F(StringMatch, 3, 1) \ F(StringMatch, 3, 1) \
F(StringTrim, 3, 1) \ F(StringTrim, 3, 1) \
F(StringToArray, 1, 1) \ F(StringToArray, 2, 1) \
F(NewStringWrapper, 1, 1) \ F(NewStringWrapper, 1, 1) \
\ \
/* Numbers */ \ /* Numbers */ \

2
deps/v8/src/string.js

@ -552,7 +552,7 @@ function StringSplit(separator, limit) {
var separator_length = separator.length; var separator_length = separator.length;
// If the separator string is empty then return the elements in the subject. // If the separator string is empty then return the elements in the subject.
if (separator_length === 0) return %StringToArray(subject); if (separator_length === 0) return %StringToArray(subject, limit);
var result = %StringSplit(subject, separator, limit); var result = %StringSplit(subject, separator, limit);

2
deps/v8/src/stub-cache.h

@ -740,7 +740,7 @@ class ConstructStubCompiler: public StubCompiler {
public: public:
explicit ConstructStubCompiler() {} explicit ConstructStubCompiler() {}
MUST_USE_RESULT MaybeObject* CompileConstructStub(SharedFunctionInfo* shared); MUST_USE_RESULT MaybeObject* CompileConstructStub(JSFunction* function);
private: private:
MaybeObject* GetCode(); MaybeObject* GetCode();

3
deps/v8/src/token.cc

@ -25,8 +25,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "v8.h" #include "../include/v8stdint.h"
#include "token.h" #include "token.h"
namespace v8 { namespace v8 {

2
deps/v8/src/v8.h

@ -54,7 +54,7 @@
// Basic includes // Basic includes
#include "../include/v8.h" #include "../include/v8.h"
#include "v8globals.h" #include "v8globals.h"
#include "checks.h" #include "v8checks.h"
#include "allocation.h" #include "allocation.h"
#include "v8utils.h" #include "v8utils.h"
#include "flags.h" #include "flags.h"

64
deps/v8/src/v8checks.h

@ -0,0 +1,64 @@
// Copyright 2006-2008 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_V8CHECKS_H_
#define V8_V8CHECKS_H_
#include "checks.h"
void API_Fatal(const char* location, const char* format, ...);
namespace v8 {
class Value;
template <class T> class Handle;
namespace internal {
intptr_t HeapObjectTagMask();
} } // namespace v8::internal
void CheckNonEqualsHelper(const char* file,
int line,
const char* unexpected_source,
v8::Handle<v8::Value> unexpected,
const char* value_source,
v8::Handle<v8::Value> value);
void CheckEqualsHelper(const char* file,
int line,
const char* expected_source,
v8::Handle<v8::Value> expected,
const char* value_source,
v8::Handle<v8::Value> value);
#define ASSERT_TAG_ALIGNED(address) \
ASSERT((reinterpret_cast<intptr_t>(address) & HeapObjectTagMask()) == 0)
#define ASSERT_SIZE_TAG_ALIGNED(size) ASSERT((size & HeapObjectTagMask()) == 0)
#endif // V8_V8CHECKS_H_

4
deps/v8/src/version.cc

@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script. // cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2 #define MAJOR_VERSION 2
#define MINOR_VERSION 5 #define MINOR_VERSION 5
#define BUILD_NUMBER 8 #define BUILD_NUMBER 9
#define PATCH_LEVEL 0 #define PATCH_LEVEL 1
#define CANDIDATE_VERSION false #define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the // Define SONAME to have the SCons build the put a specific SONAME into the

8
deps/v8/src/x64/macro-assembler-x64.cc

@ -1889,7 +1889,6 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
void MacroAssembler::LoadAllocationTopHelper(Register result, void MacroAssembler::LoadAllocationTopHelper(Register result,
Register result_end,
Register scratch, Register scratch,
AllocationFlags flags) { AllocationFlags flags) {
ExternalReference new_space_allocation_top = ExternalReference new_space_allocation_top =
@ -1911,7 +1910,6 @@ void MacroAssembler::LoadAllocationTopHelper(Register result,
// Move address of new object to result. Use scratch register if available, // Move address of new object to result. Use scratch register if available,
// and keep address in scratch until call to UpdateAllocationTopHelper. // and keep address in scratch until call to UpdateAllocationTopHelper.
if (scratch.is_valid()) { if (scratch.is_valid()) {
ASSERT(!scratch.is(result_end));
movq(scratch, new_space_allocation_top); movq(scratch, new_space_allocation_top);
movq(result, Operand(scratch, 0)); movq(result, Operand(scratch, 0));
} else if (result.is(rax)) { } else if (result.is(rax)) {
@ -1972,7 +1970,7 @@ void MacroAssembler::AllocateInNewSpace(int object_size,
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
LoadAllocationTopHelper(result, result_end, scratch, flags); LoadAllocationTopHelper(result, scratch, flags);
// Calculate new top and bail out if new space is exhausted. // Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit = ExternalReference new_space_allocation_limit =
@ -2029,7 +2027,7 @@ void MacroAssembler::AllocateInNewSpace(int header_size,
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
LoadAllocationTopHelper(result, result_end, scratch, flags); LoadAllocationTopHelper(result, scratch, flags);
// Calculate new top and bail out if new space is exhausted. // Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit = ExternalReference new_space_allocation_limit =
@ -2071,7 +2069,7 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
LoadAllocationTopHelper(result, result_end, scratch, flags); LoadAllocationTopHelper(result, scratch, flags);
// Calculate new top and bail out if new space is exhausted. // Calculate new top and bail out if new space is exhausted.
ExternalReference new_space_allocation_limit = ExternalReference new_space_allocation_limit =

3
deps/v8/src/x64/macro-assembler-x64.h

@ -950,12 +950,9 @@ class MacroAssembler: public Assembler {
// Allocation support helpers. // Allocation support helpers.
// Loads the top of new-space into the result register. // Loads the top of new-space into the result register.
// If flags contains RESULT_CONTAINS_TOP then result_end is valid and
// already contains the top of new-space, and scratch is invalid.
// Otherwise the address of the new-space top is loaded into scratch (if // Otherwise the address of the new-space top is loaded into scratch (if
// scratch is valid), and the new-space top is loaded into result. // scratch is valid), and the new-space top is loaded into result.
void LoadAllocationTopHelper(Register result, void LoadAllocationTopHelper(Register result,
Register result_end,
Register scratch, Register scratch,
AllocationFlags flags); AllocationFlags flags);
// Update allocation top with value in result_end register. // Update allocation top with value in result_end register.

7
deps/v8/src/x64/stub-cache-x64.cc

@ -2890,8 +2890,7 @@ void StubCompiler::GenerateLoadConstant(JSObject* object,
// Specialized stub for constructing objects from functions which only have only // Specialized stub for constructing objects from functions which only have only
// simple assignments of the form this.x = ...; in their body. // simple assignments of the form this.x = ...; in their body.
MaybeObject* ConstructStubCompiler::CompileConstructStub( MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
SharedFunctionInfo* shared) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : argc // -- rax : argc
// -- rdi : constructor // -- rdi : constructor
@ -2964,6 +2963,7 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(
// r9: first in-object property of the JSObject // r9: first in-object property of the JSObject
// Fill the initialized properties with a constant value or a passed argument // Fill the initialized properties with a constant value or a passed argument
// depending on the this.x = ...; assignment in the function. // depending on the this.x = ...; assignment in the function.
SharedFunctionInfo* shared = function->shared();
for (int i = 0; i < shared->this_property_assignments_count(); i++) { for (int i = 0; i < shared->this_property_assignments_count(); i++) {
if (shared->IsThisPropertyAssignmentArgument(i)) { if (shared->IsThisPropertyAssignmentArgument(i)) {
// Check if the argument assigned to the property is actually passed. // Check if the argument assigned to the property is actually passed.
@ -2983,8 +2983,9 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(
} }
// Fill the unused in-object property fields with undefined. // Fill the unused in-object property fields with undefined.
ASSERT(function->has_initial_map());
for (int i = shared->this_property_assignments_count(); for (int i = shared->this_property_assignments_count();
i < shared->CalculateInObjectProperties(); i < function->initial_map()->inobject_properties();
i++) { i++) {
__ movq(Operand(r9, i * kPointerSize), r8); __ movq(Operand(r9, i * kPointerSize), r8);
} }

27
deps/v8/test/cctest/test-api.cc

@ -7819,6 +7819,31 @@ THREADED_TEST(ObjectProtoToString) {
} }
THREADED_TEST(ObjectGetConstructorName) {
v8::HandleScope scope;
LocalContext context;
v8_compile("function Parent() {};"
"function Child() {};"
"Child.prototype = new Parent();"
"var outer = { inner: function() { } };"
"var p = new Parent();"
"var c = new Child();"
"var x = new outer.inner();")->Run();
Local<v8::Value> p = context->Global()->Get(v8_str("p"));
CHECK(p->IsObject() && p->ToObject()->GetConstructorName()->Equals(
v8_str("Parent")));
Local<v8::Value> c = context->Global()->Get(v8_str("c"));
CHECK(c->IsObject() && c->ToObject()->GetConstructorName()->Equals(
v8_str("Child")));
Local<v8::Value> x = context->Global()->Get(v8_str("x"));
CHECK(x->IsObject() && x->ToObject()->GetConstructorName()->Equals(
v8_str("outer.inner")));
}
bool ApiTestFuzzer::fuzzing_ = false; bool ApiTestFuzzer::fuzzing_ = false;
i::Semaphore* ApiTestFuzzer::all_tests_done_= i::Semaphore* ApiTestFuzzer::all_tests_done_=
i::OS::CreateSemaphore(0); i::OS::CreateSemaphore(0);
@ -8734,7 +8759,7 @@ TEST(PreCompileInvalidPreparseDataError) {
v8::ScriptData::PreCompile(script, i::StrLength(script)); v8::ScriptData::PreCompile(script, i::StrLength(script));
CHECK(!sd->HasError()); CHECK(!sd->HasError());
// ScriptDataImpl private implementation details // ScriptDataImpl private implementation details
const int kHeaderSize = i::ScriptDataImpl::kHeaderSize; const int kHeaderSize = i::PreparseDataConstants::kHeaderSize;
const int kFunctionEntrySize = i::FunctionEntry::kSize; const int kFunctionEntrySize = i::FunctionEntry::kSize;
const int kFunctionEntryStartOffset = 0; const int kFunctionEntryStartOffset = 0;
const int kFunctionEntryEndOffset = 1; const int kFunctionEntryEndOffset = 1;

6
deps/v8/test/cctest/test-conversions.cc

@ -104,8 +104,10 @@ TEST(IntegerStrLiteral) {
CHECK_EQ(0.0, StringToDouble("000", NO_FLAGS)); CHECK_EQ(0.0, StringToDouble("000", NO_FLAGS));
CHECK_EQ(1.0, StringToDouble("1", NO_FLAGS)); CHECK_EQ(1.0, StringToDouble("1", NO_FLAGS));
CHECK_EQ(-1.0, StringToDouble("-1", NO_FLAGS)); CHECK_EQ(-1.0, StringToDouble("-1", NO_FLAGS));
CHECK_EQ(-1.0, StringToDouble(" - 1 ", NO_FLAGS)); CHECK_EQ(-1.0, StringToDouble(" -1 ", NO_FLAGS));
CHECK_EQ(1.0, StringToDouble(" + 1 ", NO_FLAGS)); CHECK_EQ(1.0, StringToDouble(" +1 ", NO_FLAGS));
CHECK(isnan(StringToDouble(" - 1 ", NO_FLAGS)));
CHECK(isnan(StringToDouble(" + 1 ", NO_FLAGS)));
CHECK_EQ(0.0, StringToDouble("0e0", ALLOW_HEX | ALLOW_OCTALS)); CHECK_EQ(0.0, StringToDouble("0e0", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble("0e1", ALLOW_HEX | ALLOW_OCTALS)); CHECK_EQ(0.0, StringToDouble("0e1", ALLOW_HEX | ALLOW_OCTALS));

15
deps/v8/test/cctest/test-heap-profiler.cc

@ -1178,4 +1178,19 @@ TEST(HeapSnapshotJSONSerializationAborting) {
CHECK_EQ(0, stream.eos_signaled()); CHECK_EQ(0, stream.eos_signaled());
} }
// Must not crash in debug mode.
TEST(AggregatedHeapSnapshotJSONSerialization) {
v8::HandleScope scope;
LocalContext env;
const v8::HeapSnapshot* snapshot =
v8::HeapProfiler::TakeSnapshot(
v8::String::New("agg"), v8::HeapSnapshot::kAggregated);
TestJSONStream stream;
snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON);
CHECK_GT(stream.size(), 0);
CHECK_EQ(1, stream.eos_signaled());
}
#endif // ENABLE_LOGGING_AND_PROFILING #endif // ENABLE_LOGGING_AND_PROFILING

42
deps/v8/test/cctest/test-log.cc

@ -139,6 +139,12 @@ namespace internal {
class LoggerTestHelper : public AllStatic { class LoggerTestHelper : public AllStatic {
public: public:
static bool IsSamplerActive() { return Logger::IsProfilerSamplerActive(); } static bool IsSamplerActive() { return Logger::IsProfilerSamplerActive(); }
static void ResetSamplesTaken() {
reinterpret_cast<Sampler*>(Logger::ticker_)->ResetSamplesTaken();
}
static bool has_samples_taken() {
return reinterpret_cast<Sampler*>(Logger::ticker_)->samples_taken() > 0;
}
}; };
} // namespace v8::internal } // namespace v8::internal
@ -147,24 +153,6 @@ class LoggerTestHelper : public AllStatic {
using v8::internal::LoggerTestHelper; using v8::internal::LoggerTestHelper;
// Under Linux, we need to check if signals were delivered to avoid false
// positives. Under other platforms profiling is done via a high-priority
// thread, so this case never happen.
static bool was_sigprof_received = true;
#ifdef __linux__
struct sigaction old_sigprof_handler;
pthread_t our_thread;
static void SigProfSignalHandler(int signal, siginfo_t* info, void* context) {
if (signal != SIGPROF || !pthread_equal(pthread_self(), our_thread)) return;
was_sigprof_received = true;
old_sigprof_handler.sa_sigaction(signal, info, context);
}
#endif // __linux__
namespace { namespace {
class ScopedLoggerInitializer { class ScopedLoggerInitializer {
@ -258,6 +246,9 @@ class LogBufferMatcher {
static void CheckThatProfilerWorks(LogBufferMatcher* matcher) { static void CheckThatProfilerWorks(LogBufferMatcher* matcher) {
CHECK(!LoggerTestHelper::IsSamplerActive());
LoggerTestHelper::ResetSamplesTaken();
Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 0); Logger::ResumeProfiler(v8::PROFILER_MODULE_CPU, 0);
CHECK(LoggerTestHelper::IsSamplerActive()); CHECK(LoggerTestHelper::IsSamplerActive());
@ -266,19 +257,6 @@ static void CheckThatProfilerWorks(LogBufferMatcher* matcher) {
const char* code_creation = "\ncode-creation,"; // eq. to /^code-creation,/ const char* code_creation = "\ncode-creation,"; // eq. to /^code-creation,/
CHECK_NE(NULL, matcher->Find(code_creation)); CHECK_NE(NULL, matcher->Find(code_creation));
#ifdef __linux__
// Intercept SIGPROF handler to make sure that the test process
// had received it. Under load, system can defer it causing test failure.
// It is important to execute this after 'ResumeProfiler'.
our_thread = pthread_self();
was_sigprof_received = false;
struct sigaction sa;
sa.sa_sigaction = SigProfSignalHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
CHECK_EQ(0, sigaction(SIGPROF, &sa, &old_sigprof_handler));
#endif // __linux__
// Force compiler to generate new code by parametrizing source. // Force compiler to generate new code by parametrizing source.
EmbeddedVector<char, 100> script_src; EmbeddedVector<char, 100> script_src;
i::OS::SNPrintF(script_src, i::OS::SNPrintF(script_src,
@ -306,7 +284,7 @@ static void CheckThatProfilerWorks(LogBufferMatcher* matcher) {
CHECK_NE(NULL, matcher->Find(code_creation)); CHECK_NE(NULL, matcher->Find(code_creation));
const char* tick = "\ntick,"; const char* tick = "\ntick,";
const bool ticks_found = matcher->Find(tick) != NULL; const bool ticks_found = matcher->Find(tick) != NULL;
CHECK_EQ(was_sigprof_received, ticks_found); CHECK_EQ(LoggerTestHelper::has_samples_taken(), ticks_found);
} }

3
deps/v8/test/cctest/test-parsing.cc

@ -263,8 +263,7 @@ TEST(StandAlonePreParser) {
i::CompleteParserRecorder log; i::CompleteParserRecorder log;
i::V8JavaScriptScanner scanner; i::V8JavaScriptScanner scanner;
scanner.Initialize(i::Handle<i::String>::null(), &stream); scanner.Initialize(i::Handle<i::String>::null(), &stream);
v8::preparser::PreParser<i::V8JavaScriptScanner, v8::preparser::PreParser preparser;
i::CompleteParserRecorder> preparser;
bool result = preparser.PreParseProgram(&scanner, &log, true); bool result = preparser.PreParseProgram(&scanner, &log, true);
CHECK(result); CHECK(result);
i::ScriptDataImpl data(log.ExtractData()); i::ScriptDataImpl data(log.ExtractData());

46
deps/v8/test/mjsunit/regress/regress-944.js

@ -0,0 +1,46 @@
// Copyright 2010 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.
// Check for parsing of proper ES5 15.9.1.15 (ISO 8601 / RFC 3339) time
// strings that contain millisecond values with exactly 3 digits (as is
// required by the spec format if the string has milliseconds at all).
assertEquals(1290722550521, Date.parse("2010-11-25T22:02:30.521Z"));
// Check for parsing of extension/generalization of the ES5 15.9.1.15 spec
// format where millisecond values have only 1 or 2 digits.
assertEquals(1290722550500, Date.parse("2010-11-25T22:02:30.5Z"));
assertEquals(1290722550520, Date.parse("2010-11-25T22:02:30.52Z"));
assertFalse(Date.parse("2010-11-25T22:02:30.5Z") === Date.parse("2010-11-25T22:02:30.005Z"));
// Check that we truncate millisecond values having more than 3 digits.
assertEquals(Date.parse("2010-11-25T22:02:30.1005Z"), Date.parse("2010-11-25T22:02:30.100Z"));
// Check that we accept lots of digits.
assertEquals(Date.parse("2010-11-25T22:02:30.999Z"), Date.parse("2010-11-25T22:02:30.99999999999999999999999999999999999999999999999999999999999999999999999999999999999999Z"));
// Fail if there's a decimal point but zero digits for (expected) milliseconds.
assertTrue(isNaN(Date.parse("2010-11-25T22:02:30.Z")));

19
deps/v8/test/mjsunit/string-split.js

@ -97,3 +97,22 @@ assertEquals([""], ''.split(/./));
assertEquals([], ''.split(/.?/)); assertEquals([], ''.split(/.?/));
assertEquals([], ''.split(/.??/)); assertEquals([], ''.split(/.??/));
assertEquals([], ''.split(/()()/)); assertEquals([], ''.split(/()()/));
// Issue http://code.google.com/p/v8/issues/detail?id=929
// (Splitting with empty separator and a limit.)
function numberObj(num) {
return {valueOf: function() { return num; }};
}
assertEquals([], "abc".split("", 0));
assertEquals([], "abc".split("", numberObj(0)));
assertEquals(["a"], "abc".split("", 1));
assertEquals(["a"], "abc".split("", numberObj(1)));
assertEquals(["a", "b"], "abc".split("", 2));
assertEquals(["a", "b"], "abc".split("", numberObj(2)));
assertEquals(["a", "b", "c"], "abc".split("", 3));
assertEquals(["a", "b", "c"], "abc".split("", numberObj(3)));
assertEquals(["a", "b", "c"], "abc".split("", 4));
assertEquals(["a", "b", "c"], "abc".split("", numberObj(4)));

7
deps/v8/tools/gyp/v8.gyp

@ -406,6 +406,10 @@
'../../src/parser.cc', '../../src/parser.cc',
'../../src/parser.h', '../../src/parser.h',
'../../src/platform.h', '../../src/platform.h',
'../../src/preparse-data.cc',
'../../src/preparse-data.h',
'../../src/preparser.cc',
'../../src/preparser.h',
'../../src/prettyprinter.cc', '../../src/prettyprinter.cc',
'../../src/prettyprinter.h', '../../src/prettyprinter.h',
'../../src/property.cc', '../../src/property.cc',
@ -471,8 +475,11 @@
'../../src/v8-counters.h', '../../src/v8-counters.h',
'../../src/v8.cc', '../../src/v8.cc',
'../../src/v8.h', '../../src/v8.h',
'../../src/v8checks.h',
'../../src/v8globals.h',
'../../src/v8threads.cc', '../../src/v8threads.cc',
'../../src/v8threads.h', '../../src/v8threads.h',
'../../src/v8utils.h',
'../../src/variables.cc', '../../src/variables.cc',
'../../src/variables.h', '../../src/variables.h',
'../../src/version.cc', '../../src/version.cc',

2
deps/v8/tools/presubmit.py

@ -195,7 +195,7 @@ class CppLintProcessor(SourceFileProcessor):
or (name in CppLintProcessor.IGNORE_LINT)) or (name in CppLintProcessor.IGNORE_LINT))
def GetPathsToSearch(self): def GetPathsToSearch(self):
return ['src', 'include', 'samples', join('test', 'cctest')] return ['src', 'preparser', 'include', 'samples', join('test', 'cctest')]
def ProcessFiles(self, files, path): def ProcessFiles(self, files, path):
good_files_cache = FileContentsCache('.cpplint-cache') good_files_cache = FileContentsCache('.cpplint-cache')

32
deps/v8/tools/visual_studio/v8_base.vcproj

@ -761,6 +761,22 @@
RelativePath="..\..\src\parser.h" RelativePath="..\..\src\parser.h"
> >
</File> </File>
<File
RelativePath="..\..\src\preparser.cc"
>
</File>
<File
RelativePath="..\..\src\preparser.h"
>
</File>
<File
RelativePath="..\..\src\preparse-data.cc"
>
</File>
<File
RelativePath="..\..\src\preparse-data.h"
>
</File>
<File <File
RelativePath="..\..\src\profile-generator.cc" RelativePath="..\..\src\profile-generator.cc"
> >
@ -1033,6 +1049,14 @@
RelativePath="..\..\src\v8.h" RelativePath="..\..\src\v8.h"
> >
</File> </File>
<File
RelativePath="..\..\src\v8checks.h"
>
</File>
<File
RelativePath="..\..\src\v8globals.h"
>
</File>
<File <File
RelativePath="..\..\src\v8threads.cc" RelativePath="..\..\src\v8threads.cc"
> >
@ -1041,6 +1065,10 @@
RelativePath="..\..\src\v8threads.h" RelativePath="..\..\src\v8threads.h"
> >
</File> </File>
<File
RelativePath="..\..\src\v8utils.h"
>
</File>
<File <File
RelativePath="..\..\src\variables.cc" RelativePath="..\..\src\variables.cc"
> >
@ -1157,6 +1185,10 @@
RelativePath="..\..\include\v8.h" RelativePath="..\..\include\v8.h"
> >
</File> </File>
<File
RelativePath="..\..\include\v8stdint.h"
>
</File>
</Filter> </Filter>
</Files> </Files>
<Globals> <Globals>

Loading…
Cancel
Save