Browse Source

Upgrade v8 to 1.3.5

v0.7.4-release
Ryan 15 years ago
parent
commit
0cec74d03d
  1. 27
      deps/v8/ChangeLog
  2. 11
      deps/v8/SConstruct
  3. 7
      deps/v8/include/v8-debug.h
  4. 42
      deps/v8/include/v8.h
  5. 44
      deps/v8/src/SConscript
  6. 88
      deps/v8/src/api.cc
  7. 5
      deps/v8/src/arm/assembler-arm.h
  8. 2
      deps/v8/src/arm/builtins-arm.cc
  9. 9
      deps/v8/src/arm/codegen-arm.cc
  10. 9
      deps/v8/src/arm/codegen-arm.h
  11. 2
      deps/v8/src/arm/macro-assembler-arm.cc
  12. 3
      deps/v8/src/assembler.h
  13. 20
      deps/v8/src/ast.h
  14. 6
      deps/v8/src/builtins.cc
  15. 33
      deps/v8/src/codegen.cc
  16. 1
      deps/v8/src/compilation-cache.cc
  17. 9
      deps/v8/src/compiler.cc
  18. 10
      deps/v8/src/debug.cc
  19. 4
      deps/v8/src/debug.h
  20. 7
      deps/v8/src/execution.cc
  21. 5
      deps/v8/src/execution.h
  22. 6
      deps/v8/src/factory.cc
  23. 3
      deps/v8/src/factory.h
  24. 2
      deps/v8/src/handles-inl.h
  25. 19
      deps/v8/src/handles.h
  26. 61
      deps/v8/src/heap.cc
  27. 4
      deps/v8/src/heap.h
  28. 5
      deps/v8/src/ia32/assembler-ia32.h
  29. 9
      deps/v8/src/ia32/builtins-ia32.cc
  30. 16
      deps/v8/src/ia32/codegen-ia32.cc
  31. 19
      deps/v8/src/ia32/codegen-ia32.h
  32. 4
      deps/v8/src/ia32/debug-ia32.cc
  33. 4
      deps/v8/src/ia32/ic-ia32.cc
  34. 4
      deps/v8/src/ia32/macro-assembler-ia32.cc
  35. 254
      deps/v8/src/ia32/regexp-macro-assembler-ia32.cc
  36. 64
      deps/v8/src/ia32/regexp-macro-assembler-ia32.h
  37. 2
      deps/v8/src/ic-inl.h
  38. 2
      deps/v8/src/ic.cc
  39. 2
      deps/v8/src/ic.h
  40. 79
      deps/v8/src/jsregexp.cc
  41. 2
      deps/v8/src/math.js
  42. 13
      deps/v8/src/objects-debug.cc
  43. 34
      deps/v8/src/objects-inl.h
  44. 44
      deps/v8/src/objects.cc
  45. 52
      deps/v8/src/objects.h
  46. 283
      deps/v8/src/parser.cc
  47. 3
      deps/v8/src/parser.h
  48. 4
      deps/v8/src/platform-win32.cc
  49. 31
      deps/v8/src/regexp-macro-assembler-irregexp.cc
  50. 12
      deps/v8/src/regexp-macro-assembler-irregexp.h
  51. 58
      deps/v8/src/regexp-macro-assembler-tracer.cc
  52. 14
      deps/v8/src/regexp-macro-assembler-tracer.h
  53. 190
      deps/v8/src/regexp-macro-assembler.cc
  54. 102
      deps/v8/src/regexp-macro-assembler.h
  55. 4
      deps/v8/src/regexp-stack.h
  56. 28
      deps/v8/src/runtime.cc
  57. 2
      deps/v8/src/runtime.h
  58. 97
      deps/v8/src/scanner.cc
  59. 57
      deps/v8/src/scanner.h
  60. 23
      deps/v8/src/scopes.cc
  61. 7
      deps/v8/src/scopes.h
  62. 73
      deps/v8/src/spaces.cc
  63. 20
      deps/v8/src/spaces.h
  64. 2
      deps/v8/src/v8-counters.h
  65. 7
      deps/v8/src/v8natives.js
  66. 2
      deps/v8/src/version.cc
  67. 24
      deps/v8/src/x64/assembler-x64-inl.h
  68. 136
      deps/v8/src/x64/assembler-x64.cc
  69. 96
      deps/v8/src/x64/assembler-x64.h
  70. 22
      deps/v8/src/x64/builtins-x64.cc
  71. 4
      deps/v8/src/x64/cfg-x64.cc
  72. 44
      deps/v8/src/x64/codegen-x64.cc
  73. 21
      deps/v8/src/x64/codegen-x64.h
  74. 150
      deps/v8/src/x64/debug-x64.cc
  75. 4
      deps/v8/src/x64/ic-x64.cc
  76. 17
      deps/v8/src/x64/macro-assembler-x64.cc
  77. 1274
      deps/v8/src/x64/regexp-macro-assembler-x64.cc
  78. 268
      deps/v8/src/x64/regexp-macro-assembler-x64.h
  79. 58
      deps/v8/test/cctest/cctest.status
  80. 28
      deps/v8/test/cctest/test-api.cc
  81. 25
      deps/v8/test/cctest/test-debug.cc
  82. 5
      deps/v8/test/cctest/test-decls.cc
  83. 12
      deps/v8/test/cctest/test-heap.cc
  84. 443
      deps/v8/test/cctest/test-regexp.cc
  85. 13
      deps/v8/test/message/message.status
  86. 9
      deps/v8/test/mjsunit/div-mod.js
  87. 8
      deps/v8/test/mjsunit/mjsunit.js
  88. 30
      deps/v8/test/mjsunit/mjsunit.status
  89. 78
      deps/v8/test/mjsunit/simple-constructor.js
  90. 63
      deps/v8/test/mjsunit/stack-traces.js
  91. 16
      deps/v8/test/mjsunit/tools/logreader.js
  92. 72
      deps/v8/test/mjsunit/tools/tickprocessor.js
  93. 12
      deps/v8/test/mozilla/mozilla.status
  94. 18
      deps/v8/tools/gyp/v8.gyp
  95. 7
      deps/v8/tools/logreader.js
  96. 4
      deps/v8/tools/mac-nm
  97. 33
      deps/v8/tools/tickprocessor.js
  98. 2
      deps/v8/tools/visual_studio/common.vsprops
  99. 199
      deps/v8/tools/visual_studio/d8_x64.vcproj
  100. 2
      deps/v8/tools/visual_studio/ia32.vsprops

27
deps/v8/ChangeLog

@ -1,3 +1,30 @@
2009-08-19: Version 1.3.5
Optimize initialization of some arrays in the builtins.
Fix mac-nm script to support filenames with spaces.
Support for using the V8 profiler when V8 is embedded in a Windows DLL.
Changed typeof RegExp from 'object' to 'function' for compatibility.
Fixed bug where regexps were not callable across contexts.
Added context independent script compilation to the API.
Added API call to get the stack trace for an exception.
Added API for getting object mirrors.
Make sure that SSE3 instructions are used whenever possible even when
running off a snapshot generated without using SSE3 instructions.
Tweaked the handling of the initial size and growth policy of the heap.
Added native code generation for RegExp to 64-bit version.
Added JavaScript debugger support to 64-bit version.
2009-08-13: Version 1.3.4
Added a readline() command to the d8 shell.

11
deps/v8/SConstruct

@ -101,6 +101,9 @@ LIBRARY_FLAGS = {
'regexp:native': {
'arch:ia32' : {
'CPPDEFINES': ['V8_NATIVE_REGEXP']
},
'arch:x64' : {
'CPPDEFINES': ['V8_NATIVE_REGEXP']
}
}
},
@ -166,7 +169,7 @@ LIBRARY_FLAGS = {
},
'arch:x64': {
'CPPDEFINES': ['V8_TARGET_ARCH_X64'],
'CCFLAGS': ['-fno-strict-aliasing', '-m64'],
'CCFLAGS': ['-m64'],
'LINKFLAGS': ['-m64'],
},
'prof:oprofile': {
@ -716,7 +719,11 @@ class BuildContext(object):
result = []
result += source.get('all', [])
for (name, value) in self.options.iteritems():
result += source.get(name + ':' + value, [])
source_value = source.get(name + ':' + value, [])
if type(source_value) == dict:
result += self.GetRelevantSources(source_value)
else:
result += source_value
return sorted(result)
def AppendFlags(self, options, added):

7
deps/v8/include/v8-debug.h

@ -228,9 +228,14 @@ class EXPORT Debug {
* }
* \endcode
*/
static Handle<Value> Call(v8::Handle<v8::Function> fun,
static Local<Value> Call(v8::Handle<v8::Function> fun,
Handle<Value> data = Handle<Value>());
/**
* Returns a mirror object for the given object.
*/
static Local<Value> GetMirror(v8::Handle<v8::Value> obj);
/**
* Enable the V8 builtin debug agent. The debugger agent will listen on the
* supplied TCP/IP port for remote debugger connection.

42
deps/v8/include/v8.h

@ -513,10 +513,36 @@ class V8EXPORT ScriptOrigin {
class V8EXPORT Script {
public:
/**
* Compiles the specified script. The ScriptOrigin* and ScriptData*
* parameters are owned by the caller of Script::Compile. No
* references to these objects are kept after compilation finishes.
*
* The script object returned is context independent; when run it
* will use the currently entered context.
*/
static Local<Script> New(Handle<String> source,
ScriptOrigin* origin = NULL,
ScriptData* pre_data = NULL);
/**
* Compiles the specified script using the specified file name
* object (typically a string) as the script's origin.
*
* The script object returned is context independent; when run it
* will use the currently entered context.
*/
static Local<Script> New(Handle<String> source,
Handle<Value> file_name);
/**
* Compiles the specified script. The ScriptOrigin* and ScriptData*
* parameters are owned by the caller of Script::Compile. No
* references to these objects are kept after compilation finishes.
*
* The script object returned is bound to the context that was active
* when this function was called. When run it will always use this
* context.
*/
static Local<Script> Compile(Handle<String> source,
ScriptOrigin* origin = NULL,
@ -525,12 +551,20 @@ class V8EXPORT Script {
/**
* Compiles the specified script using the specified file name
* object (typically a string) as the script's origin.
*
* The script object returned is bound to the context that was active
* when this function was called. When run it will always use this
* context.
*/
static Local<Script> Compile(Handle<String> source,
Handle<Value> file_name);
/**
* Runs the script returning the resulting value.
* Runs the script returning the resulting value. If the script is
* context independent (created using ::New) it will be run in the
* currently entered context. If it is context specific (created
* using ::Compile) it will be run in the context in which it was
* compiled.
*/
Local<Value> Run();
@ -2255,6 +2289,12 @@ class V8EXPORT TryCatch {
*/
Local<Value> Exception() const;
/**
* Returns the .stack property of the thrown object. If no .stack
* property is present an empty handle is returned.
*/
Local<Value> StackTrace() const;
/**
* Returns the message associated with this exception. If there is
* no message associated an empty handle is returned.

44
deps/v8/src/SConscript

@ -63,24 +63,32 @@ SOURCES = {
'arm/register-allocator-arm.cc', 'arm/stub-cache-arm.cc',
'arm/virtual-frame-arm.cc'
],
'arch:ia32': [
'ia32/assembler-ia32.cc', 'ia32/builtins-ia32.cc', 'ia32/cfg-ia32.cc',
'ia32/codegen-ia32.cc', 'ia32/cpu-ia32.cc', 'ia32/disasm-ia32.cc',
'ia32/debug-ia32.cc', 'ia32/frames-ia32.cc', 'ia32/ic-ia32.cc',
'ia32/jump-target-ia32.cc', 'ia32/macro-assembler-ia32.cc',
'ia32/regexp-macro-assembler-ia32.cc',
'ia32/register-allocator-ia32.cc', 'ia32/stub-cache-ia32.cc',
'ia32/virtual-frame-ia32.cc'
],
'arch:x64': [
'x64/assembler-x64.cc', 'x64/builtins-x64.cc', 'x64/cfg-x64.cc',
'x64/codegen-x64.cc', 'x64/cpu-x64.cc', 'x64/disasm-x64.cc',
'x64/debug-x64.cc', 'x64/frames-x64.cc', 'x64/ic-x64.cc',
'x64/jump-target-x64.cc', 'x64/macro-assembler-x64.cc',
# 'x64/regexp-macro-assembler-x64.cc',
'x64/register-allocator-x64.cc',
'x64/stub-cache-x64.cc', 'x64/virtual-frame-x64.cc'
],
'arch:ia32': {
'all': [
'ia32/assembler-ia32.cc', 'ia32/builtins-ia32.cc', 'ia32/cfg-ia32.cc',
'ia32/codegen-ia32.cc', 'ia32/cpu-ia32.cc', 'ia32/disasm-ia32.cc',
'ia32/debug-ia32.cc', 'ia32/frames-ia32.cc', 'ia32/ic-ia32.cc',
'ia32/jump-target-ia32.cc', 'ia32/macro-assembler-ia32.cc',
'ia32/register-allocator-ia32.cc', 'ia32/stub-cache-ia32.cc',
'ia32/virtual-frame-ia32.cc'
],
'regexp:native': [
'ia32/regexp-macro-assembler-ia32.cc',
]
},
'arch:x64': {
'all': [
'x64/assembler-x64.cc', 'x64/builtins-x64.cc', 'x64/cfg-x64.cc',
'x64/codegen-x64.cc', 'x64/cpu-x64.cc', 'x64/disasm-x64.cc',
'x64/debug-x64.cc', 'x64/frames-x64.cc', 'x64/ic-x64.cc',
'x64/jump-target-x64.cc', 'x64/macro-assembler-x64.cc',
'x64/register-allocator-x64.cc',
'x64/stub-cache-x64.cc', 'x64/virtual-frame-x64.cc'
],
'regexp:native': [
'x64/regexp-macro-assembler-x64.cc'
]
},
'simulator:arm': ['arm/simulator-arm.cc'],
'os:freebsd': ['platform-freebsd.cc', 'platform-posix.cc'],
'os:linux': ['platform-linux.cc', 'platform-posix.cc'],

88
deps/v8/src/api.cc

@ -1046,7 +1046,7 @@ void ObjectTemplate::SetInternalFieldCount(int value) {
ScriptData* ScriptData::PreCompile(const char* input, int length) {
unibrow::Utf8InputBuffer<> buf(input, length);
return i::PreParse(&buf, NULL);
return i::PreParse(i::Handle<i::String>(), &buf, NULL);
}
@ -1058,11 +1058,11 @@ ScriptData* ScriptData::New(unsigned* data, int length) {
// --- S c r i p t ---
Local<Script> Script::Compile(v8::Handle<String> source,
v8::ScriptOrigin* origin,
v8::ScriptData* script_data) {
ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
LOG_API("Script::Compile");
Local<Script> Script::New(v8::Handle<String> source,
v8::ScriptOrigin* origin,
v8::ScriptData* script_data) {
ON_BAILOUT("v8::Script::New()", return Local<Script>());
LOG_API("Script::New");
ENTER_V8;
i::Handle<i::String> str = Utils::OpenHandle(*source);
i::Handle<i::Object> name_obj;
@ -1096,6 +1096,27 @@ Local<Script> Script::Compile(v8::Handle<String> source,
pre_data);
has_pending_exception = boilerplate.is_null();
EXCEPTION_BAILOUT_CHECK(Local<Script>());
return Local<Script>(ToApi<Script>(boilerplate));
}
Local<Script> Script::New(v8::Handle<String> source,
v8::Handle<Value> file_name) {
ScriptOrigin origin(file_name);
return New(source, &origin);
}
Local<Script> Script::Compile(v8::Handle<String> source,
v8::ScriptOrigin* origin,
v8::ScriptData* script_data) {
ON_BAILOUT("v8::Script::Compile()", return Local<Script>());
LOG_API("Script::Compile");
ENTER_V8;
Local<Script> generic = New(source, origin, script_data);
if (generic.IsEmpty())
return generic;
i::Handle<i::JSFunction> boilerplate = Utils::OpenHandle(*generic);
i::Handle<i::JSFunction> result =
i::Factory::NewFunctionFromBoilerplate(boilerplate,
i::Top::global_context());
@ -1118,6 +1139,10 @@ Local<Value> Script::Run() {
{
HandleScope scope;
i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
if (fun->IsBoilerplate()) {
fun = i::Factory::NewFunctionFromBoilerplate(fun,
i::Top::global_context());
}
EXCEPTION_PREAMBLE();
i::Handle<i::Object> receiver(i::Top::context()->global_proxy());
i::Handle<i::Object> result =
@ -1194,6 +1219,22 @@ v8::Local<Value> v8::TryCatch::Exception() const {
}
v8::Local<Value> v8::TryCatch::StackTrace() const {
if (HasCaught()) {
i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
if (!raw_obj->IsJSObject()) return v8::Local<Value>();
v8::HandleScope scope;
i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj));
i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("stack");
if (!obj->HasProperty(*name))
return v8::Local<Value>();
return scope.Close(v8::Utils::ToLocal(i::GetProperty(obj, name)));
} else {
return v8::Local<Value>();
}
}
v8::Local<v8::Message> v8::TryCatch::Message() const {
if (HasCaught() && message_ != i::Smi::FromInt(0)) {
i::Object* message = reinterpret_cast<i::Object*>(message_);
@ -2593,8 +2634,13 @@ Persistent<Context> v8::Context::New(
i::Handle<i::Context> env;
{
ENTER_V8;
#if defined(ANDROID)
// On mobile device, full GC is expensive, leave it to the system to
// decide when should make a full GC.
#else
// Give the heap a chance to cleanup if we've disposed contexts.
i::Heap::CollectAllGarbageIfContextDisposed();
#endif
v8::Handle<ObjectTemplate> proxy_template = global_template;
i::Handle<i::FunctionTemplateInfo> proxy_constructor;
i::Handle<i::FunctionTemplateInfo> global_constructor;
@ -3549,10 +3595,10 @@ void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
}
Handle<Value> Debug::Call(v8::Handle<v8::Function> fun,
v8::Handle<v8::Value> data) {
if (!i::V8::IsRunning()) return Handle<Value>();
ON_BAILOUT("v8::Debug::Call()", return Handle<Value>());
Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
v8::Handle<v8::Value> data) {
if (!i::V8::IsRunning()) return Local<Value>();
ON_BAILOUT("v8::Debug::Call()", return Local<Value>());
ENTER_V8;
i::Handle<i::Object> result;
EXCEPTION_PREAMBLE();
@ -3570,6 +3616,28 @@ Handle<Value> Debug::Call(v8::Handle<v8::Function> fun,
}
Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
if (!i::V8::IsRunning()) return Local<Value>();
ON_BAILOUT("v8::Debug::GetMirror()", return Local<Value>());
ENTER_V8;
v8::HandleScope scope;
i::Debug::Load();
i::Handle<i::JSObject> debug(i::Debug::debug_context()->global());
i::Handle<i::String> name = i::Factory::LookupAsciiSymbol("MakeMirror");
i::Handle<i::Object> fun_obj = i::GetProperty(debug, name);
i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
const int kArgc = 1;
v8::Handle<v8::Value> argv[kArgc] = { obj };
EXCEPTION_PREAMBLE();
v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
kArgc,
argv);
EXCEPTION_BAILOUT_CHECK(Local<Value>());
return scope.Close(result);
}
bool Debug::EnableAgent(const char* name, int port) {
return i::Debugger::StartAgent(name, port);
}

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

@ -430,7 +430,10 @@ class Assembler : public Malloced {
// Distance between the instruction referring to the address of the call
// target (ldr pc, [target addr in const pool]) and the return address
static const int kTargetAddrToReturnAddrDist = sizeof(Instr);
static const int kPatchReturnSequenceLength = sizeof(Instr);
// Distance between start of patched return sequence and the emitted address
// to jump to.
static const int kPatchReturnSequenceAddressOffset = 1;
// ---------------------------------------------------------------------------

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

@ -39,7 +39,7 @@ namespace internal {
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
// TODO(1238487): Don't pass the function in a static variable.
// TODO(428): Don't pass the function in a static variable.
__ mov(ip, Operand(ExternalReference::builtin_passed_function()));
__ str(r1, MemOperand(ip, 0));

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

@ -5890,16 +5890,11 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
Label throw_out_of_memory_exception;
Label throw_normal_exception;
// Call into the runtime system. Collect garbage before the call if
// running with --gc-greedy set.
if (FLAG_gc_greedy) {
Failure* failure = Failure::RetryAfterGC(0);
__ mov(r0, Operand(reinterpret_cast<intptr_t>(failure)));
}
// Call into the runtime system.
GenerateCore(masm, &throw_normal_exception,
&throw_out_of_memory_exception,
frame_type,
FLAG_gc_greedy,
false,
false);
// Do space-specific GC and retry runtime call.

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

@ -152,14 +152,9 @@ class CodeGenerator: public AstVisitor {
#endif
static void SetFunctionInfo(Handle<JSFunction> fun,
int length,
int function_token_position,
int start_position,
int end_position,
bool is_expression,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script,
Handle<String> inferred_name);
Handle<Script> script);
// Accessors
MacroAssembler* masm() { return masm_; }

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

@ -132,7 +132,7 @@ void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode,
// and the target address of the call would be referenced by the first
// instruction rather than the second one, which would make it harder to patch
// (two instructions before the return address, instead of one).
ASSERT(kTargetAddrToReturnAddrDist == sizeof(Instr));
ASSERT(kPatchReturnSequenceLength == sizeof(Instr));
}

3
deps/v8/src/assembler.h

@ -216,6 +216,9 @@ class RelocInfo BASE_EMBEDDED {
// Patch the code with a call.
void PatchCodeWithCall(Address target, int guard_bytes);
// Check whether the current instruction is currently a call
// sequence (whether naturally or a return sequence overwritten
// to enter the debugger).
INLINE(bool IsCallInstruction());
#ifdef ENABLE_DISASSEMBLER

20
deps/v8/src/ast.h

@ -111,6 +111,7 @@ AST_NODE_LIST(DEF_FORWARD_DECLARATION)
// Typedef only introduced to avoid unreadable code.
// Please do appreciate the required space in "> >".
typedef ZoneList<Handle<String> > ZoneStringList;
typedef ZoneList<Handle<Object> > ZoneObjectList;
class AstNode: public ZoneObject {
@ -1226,6 +1227,9 @@ class FunctionLiteral: public Expression {
int materialized_literal_count,
bool contains_array_literal,
int expected_property_count,
bool has_only_this_property_assignments,
bool has_only_simple_this_property_assignments,
Handle<FixedArray> this_property_assignments,
int num_parameters,
int start_position,
int end_position,
@ -1236,6 +1240,10 @@ class FunctionLiteral: public Expression {
materialized_literal_count_(materialized_literal_count),
contains_array_literal_(contains_array_literal),
expected_property_count_(expected_property_count),
has_only_this_property_assignments_(has_only_this_property_assignments),
has_only_simple_this_property_assignments_(
has_only_simple_this_property_assignments),
this_property_assignments_(this_property_assignments),
num_parameters_(num_parameters),
start_position_(start_position),
end_position_(end_position),
@ -1265,6 +1273,15 @@ class FunctionLiteral: public Expression {
int materialized_literal_count() { return materialized_literal_count_; }
bool contains_array_literal() { return contains_array_literal_; }
int expected_property_count() { return expected_property_count_; }
bool has_only_this_property_assignments() {
return has_only_this_property_assignments_;
}
bool has_only_simple_this_property_assignments() {
return has_only_simple_this_property_assignments_;
}
Handle<FixedArray> this_property_assignments() {
return this_property_assignments_;
}
int num_parameters() { return num_parameters_; }
bool AllowsLazyCompilation();
@ -1291,6 +1308,9 @@ class FunctionLiteral: public Expression {
int materialized_literal_count_;
bool contains_array_literal_;
int expected_property_count_;
bool has_only_this_property_assignments_;
bool has_only_simple_this_property_assignments_;
Handle<FixedArray> this_property_assignments_;
int num_parameters_;
int start_position_;
int end_position_;

6
deps/v8/src/builtins.cc

@ -61,7 +61,7 @@ namespace internal {
// ----------------------------------------------------------------------------
// TODO(1238487): We should consider passing whether or not the
// TODO(428): We should consider passing whether or not the
// builtin was invoked as a constructor as part of the
// arguments. Maybe we also want to pass the called function?
#define BUILTIN(name) \
@ -336,9 +336,7 @@ BUILTIN(HandleApiCall) {
HandleScope scope;
bool is_construct = CalledAsConstructor();
// TODO(1238487): This is not nice. We need to get rid of this
// kludgy behavior and start handling API calls in a more direct
// way - maybe compile specialized stubs lazily?.
// TODO(428): Remove use of static variable, handle API callbacks directly.
Handle<JSFunction> function =
Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function));

33
deps/v8/src/codegen.cc

@ -243,23 +243,22 @@ bool CodeGenerator::ShouldGenerateLog(Expression* type) {
// in the full script source. When counting characters in the script source the
// the first character is number 0 (not 1).
void CodeGenerator::SetFunctionInfo(Handle<JSFunction> fun,
int length,
int function_token_position,
int start_position,
int end_position,
bool is_expression,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script,
Handle<String> inferred_name) {
fun->shared()->set_length(length);
fun->shared()->set_formal_parameter_count(length);
Handle<Script> script) {
fun->shared()->set_length(lit->num_parameters());
fun->shared()->set_formal_parameter_count(lit->num_parameters());
fun->shared()->set_script(*script);
fun->shared()->set_function_token_position(function_token_position);
fun->shared()->set_start_position(start_position);
fun->shared()->set_end_position(end_position);
fun->shared()->set_is_expression(is_expression);
fun->shared()->set_function_token_position(lit->function_token_position());
fun->shared()->set_start_position(lit->start_position());
fun->shared()->set_end_position(lit->end_position());
fun->shared()->set_is_expression(lit->is_expression());
fun->shared()->set_is_toplevel(is_toplevel);
fun->shared()->set_inferred_name(*inferred_name);
fun->shared()->set_inferred_name(*lit->inferred_name());
fun->shared()->SetThisPropertyAssignmentsInfo(
lit->has_only_this_property_assignments(),
lit->has_only_simple_this_property_assignments(),
*lit->this_property_assignments());
}
@ -317,11 +316,7 @@ Handle<JSFunction> CodeGenerator::BuildBoilerplate(FunctionLiteral* node) {
node->materialized_literal_count(),
node->contains_array_literal(),
code);
CodeGenerator::SetFunctionInfo(function, node->num_parameters(),
node->function_token_position(),
node->start_position(), node->end_position(),
node->is_expression(), false, script_,
node->inferred_name());
CodeGenerator::SetFunctionInfo(function, node, false, script_);
#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger that a new function has been added.

1
deps/v8/src/compilation-cache.cc

@ -290,7 +290,6 @@ void CompilationCacheScript::Put(Handle<String> source,
HandleScope scope;
ASSERT(boilerplate->IsBoilerplate());
Handle<CompilationCacheTable> table = GetTable(0);
// TODO(X64): -fstrict-aliasing causes a problem with table. Fix it.
CALL_HEAP_FUNCTION_VOID(table->Put(*source, *boilerplate));
}

9
deps/v8/src/compiler.cc

@ -219,11 +219,8 @@ static Handle<JSFunction> MakeFunction(bool is_global,
lit->contains_array_literal(),
code);
CodeGenerator::SetFunctionInfo(fun, lit->scope()->num_parameters(),
RelocInfo::kNoPosition,
lit->start_position(), lit->end_position(),
lit->is_expression(), true, script,
lit->inferred_name());
ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
CodeGenerator::SetFunctionInfo(fun, lit, true, script);
// Hint to the runtime system used when allocating space for initial
// property space by setting the expected number of properties for
@ -269,7 +266,7 @@ Handle<JSFunction> Compiler::Compile(Handle<String> source,
if (pre_data == NULL && source_length >= FLAG_min_preparse_length) {
Access<SafeStringInputBuffer> buf(&safe_string_input_buffer);
buf->Reset(source.location());
pre_data = PreParse(buf.value(), extension);
pre_data = PreParse(source, buf.value(), extension);
}
// Create a script object describing the script to be compiled.

10
deps/v8/src/debug.cc

@ -1452,14 +1452,15 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
// Find the call address in the running code. This address holds the call to
// either a DebugBreakXXX or to the debug break return entry code if the
// break point is still active after processing the break point.
Address addr = frame->pc() - Assembler::kTargetAddrToReturnAddrDist;
Address addr = frame->pc() - Assembler::kPatchReturnSequenceLength;
// Check if the location is at JS exit.
bool at_js_exit = false;
RelocIterator it(debug_info->code());
while (!it.done()) {
if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
at_js_exit = it.rinfo()->pc() == addr - 1;
at_js_exit = (it.rinfo()->pc() ==
addr - Assembler::kPatchReturnSequenceAddressOffset);
}
it.next();
}
@ -1477,8 +1478,9 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
addr += original_code->instruction_start() - code->instruction_start();
}
// Move one byte back to where the call instruction was placed.
thread_local_.after_break_target_ = addr - 1;
// Move back to where the call instruction sequence started.
thread_local_.after_break_target_ =
addr - Assembler::kPatchReturnSequenceAddressOffset;
} else {
// Check if there still is a debug break call at the target address. If the
// break point has been removed it will have disappeared. If it have

4
deps/v8/src/debug.h

@ -238,7 +238,10 @@ class Debug {
// Returns whether the operation succeeded.
static bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
// Returns true if the current stub call is patched to call the debugger.
static bool IsDebugBreak(Address addr);
// Returns true if the current return statement has been patched to be
// a debugger breakpoint.
static bool IsDebugBreakAtReturn(RelocInfo* rinfo);
// Check whether a code stub with the specified major key is a possible break
@ -366,6 +369,7 @@ class Debug {
// The x64 JS return sequence is padded with int3 to make it large
// enough to hold a call instruction when the debugger patches it.
static const int kX64CallInstructionLength = 13;
static const int kX64JSReturnSequenceLength = 13;
// Code generator routines.

7
deps/v8/src/execution.cc

@ -174,12 +174,7 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
// Regular expressions can be called as functions in both Firefox
// and Safari so we allow it too.
bool is_regexp =
object->IsHeapObject() &&
(HeapObject::cast(*object)->map()->constructor() ==
*Top::regexp_function());
if (is_regexp) {
if (object->IsJSRegExp()) {
Handle<String> exec = Factory::exec_symbol();
return Handle<Object>(object->GetProperty(*exec));
}

5
deps/v8/src/execution.h

@ -206,8 +206,13 @@ class StackGuard BASE_EMBEDDED {
static void DisableInterrupts();
static const uintptr_t kLimitSize = kPointerSize * 128 * KB;
#ifdef V8_TARGET_ARCH_X64
static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
static const uintptr_t kIllegalLimit = V8_UINT64_C(0xffffffffffffffff);
#else
static const uintptr_t kInterruptLimit = 0xfffffffe;
static const uintptr_t kIllegalLimit = 0xffffffff;
#endif
class ThreadLocal {
public:

6
deps/v8/src/factory.cc

@ -87,8 +87,10 @@ Handle<String> Factory::NewStringFromUtf8(Vector<const char> string,
}
Handle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string) {
CALL_HEAP_FUNCTION(Heap::AllocateStringFromTwoByte(string), String);
Handle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(Heap::AllocateStringFromTwoByte(string, pretenure),
String);
}

3
deps/v8/src/factory.h

@ -92,7 +92,8 @@ class Factory : public AllStatic {
Vector<const char> str,
PretenureFlag pretenure = NOT_TENURED);
static Handle<String> NewStringFromTwoByte(Vector<const uc16> str);
static Handle<String> NewStringFromTwoByte(Vector<const uc16> str,
PretenureFlag pretenure = NOT_TENURED);
// Allocates and partially initializes a TwoByte String. The characters of
// the string are uninitialized. Currently used in regexp code only, where

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

@ -39,7 +39,7 @@ namespace internal {
template<class T>
Handle<T>::Handle(T* obj) {
ASSERT(!obj->IsFailure());
location_ = reinterpret_cast<T**>(HandleScope::CreateHandle(obj));
location_ = HandleScope::CreateHandle(obj);
}

19
deps/v8/src/handles.h

@ -82,7 +82,7 @@ class Handle {
}
static Handle<T> null() { return Handle<T>(); }
bool is_null() {return location_ == NULL; }
bool is_null() { return location_ == NULL; }
// Closes the given scope, but lets this handle escape. See
// implementation in api.h.
@ -119,15 +119,18 @@ class HandleScope {
static int NumberOfHandles();
// Creates a new handle with the given value.
static inline Object** CreateHandle(Object* value) {
void** result = current_.next;
if (result == current_.limit) result = Extend();
template <typename T>
static inline T** CreateHandle(T* value) {
void** cur = current_.next;
if (cur == current_.limit) cur = Extend();
// Update the current next field, set the value in the created
// handle, and return the result.
ASSERT(result < current_.limit);
current_.next = result + 1;
*reinterpret_cast<Object**>(result) = value;
return reinterpret_cast<Object**>(result);
ASSERT(cur < current_.limit);
current_.next = cur + 1;
T** result = reinterpret_cast<T**>(cur);
*result = value;
return result;
}
private:

61
deps/v8/src/heap.cc

@ -73,6 +73,10 @@ int Heap::amount_of_external_allocated_memory_at_last_global_gc_ = 0;
int Heap::semispace_size_ = 512*KB;
int Heap::old_generation_size_ = 128*MB;
int Heap::initial_semispace_size_ = 128*KB;
#elseif defined(V8_TARGET_ARCH_X64)
int Heap::semispace_size_ = 8*MB;
int Heap::old_generation_size_ = 1*GB;
int Heap::initial_semispace_size_ = 1*MB;
#else
int Heap::semispace_size_ = 4*MB;
int Heap::old_generation_size_ = 512*MB;
@ -277,7 +281,9 @@ void Heap::GarbageCollectionPrologue() {
int Heap::SizeOfObjects() {
int total = 0;
AllSpaces spaces;
while (Space* space = spaces.next()) total += space->Size();
while (Space* space = spaces.next()) {
total += space->Size();
}
return total;
}
@ -1048,6 +1054,7 @@ Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) {
map->set_constructor(null_value());
map->set_instance_size(instance_size);
map->set_inobject_properties(0);
map->set_pre_allocated_property_fields(0);
map->set_instance_descriptors(empty_descriptor_array());
map->set_code_cache(empty_fixed_array());
map->set_unused_property_fields(0);
@ -1605,6 +1612,9 @@ Object* Heap::AllocateSharedFunctionInfo(Object* name) {
share->set_start_position_and_type(0);
share->set_debug_info(undefined_value());
share->set_inferred_name(empty_string());
share->set_compiler_hints(0);
share->set_this_property_assignments_count(0);
share->set_this_property_assignments(undefined_value());
return result;
}
@ -2044,16 +2054,10 @@ Object* Heap::AllocateArgumentsObject(Object* callee, int length) {
Object* Heap::AllocateInitialMap(JSFunction* fun) {
ASSERT(!fun->has_initial_map());
// First create a new map with the expected number of properties being
// allocated in-object.
int expected_nof_properties = fun->shared()->expected_nof_properties();
int instance_size = JSObject::kHeaderSize +
expected_nof_properties * kPointerSize;
if (instance_size > JSObject::kMaxInstanceSize) {
instance_size = JSObject::kMaxInstanceSize;
expected_nof_properties = (instance_size - JSObject::kHeaderSize) /
kPointerSize;
}
// First create a new map with the size and number of in-object properties
// suggested by the function.
int instance_size = fun->shared()->CalculateInstanceSize();
int in_object_properties = fun->shared()->CalculateInObjectProperties();
Object* map_obj = Heap::AllocateMap(JS_OBJECT_TYPE, instance_size);
if (map_obj->IsFailure()) return map_obj;
@ -2066,9 +2070,33 @@ Object* Heap::AllocateInitialMap(JSFunction* fun) {
if (prototype->IsFailure()) return prototype;
}
Map* map = Map::cast(map_obj);
map->set_inobject_properties(expected_nof_properties);
map->set_unused_property_fields(expected_nof_properties);
map->set_inobject_properties(in_object_properties);
map->set_unused_property_fields(in_object_properties);
map->set_prototype(prototype);
// If the function has only simple this property assignments add field
// descriptors for these to the initial map as the object cannot be
// constructed without having these properties.
ASSERT(in_object_properties <= Map::kMaxPreAllocatedPropertyFields);
if (fun->shared()->has_only_this_property_assignments() &&
fun->shared()->this_property_assignments_count() > 0) {
int count = fun->shared()->this_property_assignments_count();
if (count > in_object_properties) {
count = in_object_properties;
}
DescriptorArray* descriptors = *Factory::NewDescriptorArray(count);
if (descriptors->IsFailure()) return descriptors;
for (int i = 0; i < count; i++) {
String* name = fun->shared()->GetThisPropertyAssignmentName(i);
ASSERT(name->IsSymbol());
FieldDescriptor field(name, i, NONE);
descriptors->Set(i, &field);
}
descriptors->Sort();
map->set_instance_descriptors(descriptors);
map->set_pre_allocated_property_fields(count);
map->set_unused_property_fields(in_object_properties - count);
}
return map;
}
@ -2100,7 +2128,11 @@ Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) {
ASSERT(map->instance_type() != JS_BUILTINS_OBJECT_TYPE);
// Allocate the backing storage for the properties.
int prop_size = map->unused_property_fields() - map->inobject_properties();
int prop_size =
map->pre_allocated_property_fields() +
map->unused_property_fields() -
map->inobject_properties();
ASSERT(prop_size >= 0);
Object* properties = AllocateFixedArray(prop_size, pretenure);
if (properties->IsFailure()) return properties;
@ -2593,6 +2625,7 @@ Object* Heap::CopyFixedArray(FixedArray* src) {
Object* Heap::AllocateFixedArray(int length) {
ASSERT(length >= 0);
if (length == 0) return empty_fixed_array();
Object* result = AllocateRawFixedArray(length);
if (!result->IsFailure()) {

4
deps/v8/src/heap.h

@ -852,7 +852,11 @@ class Heap : public AllStatic {
static const int kMaxMapSpaceSize = 8*MB;
#if defined(V8_TARGET_ARCH_X64)
static const int kMaxObjectSizeInNewSpace = 512*KB;
#else
static const int kMaxObjectSizeInNewSpace = 256*KB;
#endif
static NewSpace new_space_;
static OldSpace* old_pointer_space_;

5
deps/v8/src/ia32/assembler-ia32.h

@ -437,7 +437,10 @@ class Assembler : public Malloced {
// Distance between the address of the code target in the call instruction
// and the return address
static const int kTargetAddrToReturnAddrDist = kPointerSize;
static const int kPatchReturnSequenceLength = kPointerSize;
// Distance between start of patched return sequence and the emitted address
// to jump to.
static const int kPatchReturnSequenceAddressOffset = 1; // JMP imm32.
// ---------------------------------------------------------------------------

9
deps/v8/src/ia32/builtins-ia32.cc

@ -37,7 +37,7 @@ namespace internal {
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
// TODO(1238487): Don't pass the function in a static variable.
// TODO(428): Don't pass the function in a static variable.
ExternalReference passed = ExternalReference::builtin_passed_function();
__ mov(Operand::StaticVariable(passed), edi);
@ -180,12 +180,16 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// eax: initial map
// ebx: JSObject
// edi: start of next object
// Calculate the total number of properties described by the map.
__ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
__ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
__ movzx_b(ecx, FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
__ add(edx, Operand(ecx));
// Calculate unused properties past the end of the in-object properties.
__ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
__ sub(edx, Operand(ecx));
// Done if no extra properties are to be allocated.
__ j(zero, &allocated);
__ Assert(positive, "Property allocation count failed.");
// Scale the number of elements by pointer size and add the header for
// FixedArrays to the start of the next object calculation from above.
@ -321,6 +325,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ pop(ecx);
__ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize)); // 1 ~ receiver
__ push(ecx);
__ IncrementCounter(&Counters::constructed_objects, 1);
__ ret(0);
}

16
deps/v8/src/ia32/codegen-ia32.cc

@ -6752,11 +6752,10 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// Reserve space for converted numbers.
__ sub(Operand(esp), Immediate(2 * kPointerSize));
bool use_sse3 = CpuFeatures::IsSupported(CpuFeatures::SSE3);
if (use_sse3) {
if (use_sse3_) {
// Truncate the operands to 32-bit integers and check for
// exceptions in doing so.
CpuFeatures::Scope scope(CpuFeatures::SSE3);
CpuFeatures::Scope scope(CpuFeatures::SSE3);
__ fisttp_s(Operand(esp, 0 * kPointerSize));
__ fisttp_s(Operand(esp, 1 * kPointerSize));
__ fnstsw_ax();
@ -6841,7 +6840,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// the runtime system.
__ bind(&operand_conversion_failure);
__ add(Operand(esp), Immediate(2 * kPointerSize));
if (use_sse3) {
if (use_sse3_) {
// If we've used the SSE3 instructions for truncating the
// floating point values to integers and it failed, we have a
// pending #IA exception. Clear it.
@ -7671,16 +7670,11 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
Label throw_out_of_memory_exception;
Label throw_normal_exception;
// Call into the runtime system. Collect garbage before the call if
// running with --gc-greedy set.
if (FLAG_gc_greedy) {
Failure* failure = Failure::RetryAfterGC(0);
__ mov(eax, Immediate(reinterpret_cast<int32_t>(failure)));
}
// Call into the runtime system.
GenerateCore(masm, &throw_normal_exception,
&throw_out_of_memory_exception,
frame_type,
FLAG_gc_greedy,
false,
false);
// Do space-specific GC and retry runtime call.

19
deps/v8/src/ia32/codegen-ia32.h

@ -299,14 +299,9 @@ class CodeGenerator: public AstVisitor {
#endif
static void SetFunctionInfo(Handle<JSFunction> fun,
int length,
int function_token_position,
int start_position,
int end_position,
bool is_expression,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script,
Handle<String> inferred_name);
Handle<Script> script);
// Accessors
MacroAssembler* masm() { return masm_; }
@ -623,6 +618,7 @@ class GenericBinaryOpStub: public CodeStub {
OverwriteMode mode,
GenericBinaryFlags flags)
: op_(op), mode_(mode), flags_(flags) {
use_sse3_ = CpuFeatures::IsSupported(CpuFeatures::SSE3);
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
}
@ -632,6 +628,7 @@ class GenericBinaryOpStub: public CodeStub {
Token::Value op_;
OverwriteMode mode_;
GenericBinaryFlags flags_;
bool use_sse3_;
const char* GetName();
@ -644,9 +641,10 @@ class GenericBinaryOpStub: public CodeStub {
}
#endif
// Minor key encoding in 16 bits FOOOOOOOOOOOOOMM.
// Minor key encoding in 16 bits FSOOOOOOOOOOOOMM.
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
class OpBits: public BitField<Token::Value, 2, 13> {};
class OpBits: public BitField<Token::Value, 2, 12> {};
class SSE3Bits: public BitField<bool, 14, 1> {};
class FlagBits: public BitField<GenericBinaryFlags, 15, 1> {};
Major MajorKey() { return GenericBinaryOp; }
@ -654,7 +652,8 @@ class GenericBinaryOpStub: public CodeStub {
// Encode the parameters in a unique 16 bit value.
return OpBits::encode(op_)
| ModeBits::encode(mode_)
| FlagBits::encode(flags_);
| FlagBits::encode(flags_)
| SSE3Bits::encode(use_sse3_);
}
void Generate(MacroAssembler* masm);
};

4
deps/v8/src/ia32/debug-ia32.cc

@ -195,8 +195,8 @@ void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
void Debug::GenerateReturnDebugBreakEntry(MacroAssembler* masm) {
// OK to clobber ebx as we are returning from a JS function in the code
// generated by Ia32CodeGenerator::ExitJSFrame.
// OK to clobber ebx as we are returning from a JS function through the code
// generated by CodeGenerator::GenerateReturnSequence()
ExternalReference debug_break_return =
ExternalReference(Debug_Address::DebugBreakReturn());
__ mov(ebx, Operand::StaticVariable(debug_break_return));

4
deps/v8/src/ia32/ic-ia32.cc

@ -840,7 +840,7 @@ void KeyedStoreIC::RestoreInlinedVersion(Address address) {
bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
// The address of the instruction following the call.
Address test_instruction_address =
address + Assembler::kTargetAddrToReturnAddrDist;
address + Assembler::kPatchReturnSequenceLength;
// If the instruction following the call is not a test eax, nothing
// was inlined.
if (*test_instruction_address != kTestEaxByte) return false;
@ -867,7 +867,7 @@ bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
static bool PatchInlinedMapCheck(Address address, Object* map) {
Address test_instruction_address =
address + Assembler::kTargetAddrToReturnAddrDist;
address + Assembler::kPatchReturnSequenceLength;
// The keyed load has a fast inlined case if the IC call instruction
// is immediately followed by a test instruction.
if (*test_instruction_address != kTestEaxByte) return false;

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

@ -82,8 +82,8 @@ static void RecordWriteHelper(MacroAssembler* masm,
// page_start + kObjectStartOffset + objectSize
// where objectSize is FixedArray::kHeaderSize + kPointerSize * array_length.
// Add the delta between the end of the normal RSet and the start of the
// extra RSet to 'object', so that addressing the bit using 'pointer_offset'
// hits the extra RSet words.
// extra RSet to 'page_start', so that addressing the bit using
// 'pointer_offset' hits the extra RSet words.
masm->lea(page_start,
Operand(page_start, array_length, times_pointer_size,
Page::kObjectStartOffset + FixedArray::kHeaderSize

254
deps/v8/src/ia32/regexp-macro-assembler-ia32.cc

@ -38,6 +38,7 @@
namespace v8 {
namespace internal {
#ifdef V8_NATIVE_REGEXP
/*
* This assembler uses the following register assignment convention
* - edx : current character. Must be loaded using LoadCurrentCharacter
@ -54,7 +55,7 @@ namespace internal {
*
* Each call to a public method should retain this convention.
* The stack will have the following structure:
* - stack_area_top (High end of the memory area to use as
* - stack_area_base (High end of the memory area to use as
* backtracking stack)
* - at_start (if 1, start at start of string, if 0, don't)
* - int* capture_array (int[num_saved_registers_], for output).
@ -78,13 +79,13 @@ namespace internal {
* character of the string). The remaining registers starts out as garbage.
*
* The data up to the return address must be placed there by the calling
* code, e.g., by calling the code entry as cast to:
* code, by calling the code entry as cast to a function with the signature:
* int (*match)(String* input_string,
* Address start,
* Address end,
* int* capture_output_array,
* bool at_start,
* byte* stack_area_top)
* byte* stack_area_base)
*/
#define __ ACCESS_MASM(masm_)
@ -93,7 +94,6 @@ RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(
Mode mode,
int registers_to_save)
: masm_(new MacroAssembler(NULL, kRegExpCodeSize)),
constants_(kRegExpConstantsSize),
mode_(mode),
num_registers_(registers_to_save),
num_saved_registers_(registers_to_save),
@ -156,13 +156,6 @@ void RegExpMacroAssemblerIA32::Bind(Label* label) {
}
void RegExpMacroAssemblerIA32::CheckBitmap(uc16 start,
Label* bitmap,
Label* on_zero) {
UNIMPLEMENTED();
}
void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
__ cmp(current_character(), c);
BranchOrBacktrack(equal, on_equal);
@ -217,15 +210,9 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
BranchOrBacktrack(greater, on_failure);
}
Label backtrack;
if (on_failure == NULL) {
// Avoid inlining the Backtrack macro for each test.
Label skip_backtrack;
__ jmp(&skip_backtrack);
__ bind(&backtrack);
Backtrack();
__ bind(&skip_backtrack);
on_failure = &backtrack;
// Instead of inlining a backtrack, (re)use the global backtrack target.
on_failure = &backtrack_label_;
}
for (int i = 0; i < str.length(); i++) {
@ -581,34 +568,6 @@ bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
}
}
void RegExpMacroAssemblerIA32::DispatchHalfNibbleMap(
uc16 start,
Label* half_nibble_map,
const Vector<Label*>& destinations) {
UNIMPLEMENTED();
}
void RegExpMacroAssemblerIA32::DispatchByteMap(
uc16 start,
Label* byte_map,
const Vector<Label*>& destinations) {
UNIMPLEMENTED();
}
void RegExpMacroAssemblerIA32::DispatchHighByteMap(
byte start,
Label* byte_map,
const Vector<Label*>& destinations) {
UNIMPLEMENTED();
}
void RegExpMacroAssemblerIA32::EmitOrLink(Label* label) {
UNIMPLEMENTED(); // Has no use.
}
void RegExpMacroAssemblerIA32::Fail() {
ASSERT(FAILURE == 0); // Return value for failure is zero.
@ -668,17 +627,17 @@ Handle<Object> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
__ mov(edi, Operand(ebp, kInputStart));
// Set up edi to be negative offset from string end.
__ sub(edi, Operand(esi));
if (num_saved_registers_ > 0) {
// Set eax to address of char before start of input
// (effectively string position -1).
__ lea(eax, Operand(edi, -char_size()));
// Store this value in a local variable, for use when clearing
// position registers.
__ mov(Operand(ebp, kInputStartMinusOne), eax);
if (num_saved_registers_ > 0) { // Always is, if generated from a regexp.
// Fill saved registers with initial value = start offset - 1
// Fill in stack push order, to avoid accessing across an unwritten
// page (a problem on Windows).
__ mov(ecx, kRegisterZero);
// Set eax to address of char before start of input
// (effectively string position -1).
__ lea(eax, Operand(edi, -char_size()));
// Store this value in a local variable, for use when clearing
// position registers.
__ mov(Operand(ebp, kInputStartMinusOne), eax);
Label init_loop;
__ bind(&init_loop);
__ mov(Operand(ebp, ecx, times_1, +0), eax);
@ -942,139 +901,8 @@ void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
}
RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Match(
Handle<Code> regexp_code,
Handle<String> subject,
int* offsets_vector,
int offsets_vector_length,
int previous_index) {
ASSERT(subject->IsFlat());
ASSERT(previous_index >= 0);
ASSERT(previous_index <= subject->length());
// No allocations before calling the regexp, but we can't use
// AssertNoAllocation, since regexps might be preempted, and another thread
// might do allocation anyway.
String* subject_ptr = *subject;
// Character offsets into string.
int start_offset = previous_index;
int end_offset = subject_ptr->length();
bool is_ascii = subject->IsAsciiRepresentation();
if (StringShape(subject_ptr).IsCons()) {
subject_ptr = ConsString::cast(subject_ptr)->first();
} else if (StringShape(subject_ptr).IsSliced()) {
SlicedString* slice = SlicedString::cast(subject_ptr);
start_offset += slice->start();
end_offset += slice->start();
subject_ptr = slice->buffer();
}
// Ensure that an underlying string has the same ascii-ness.
ASSERT(subject_ptr->IsAsciiRepresentation() == is_ascii);
ASSERT(subject_ptr->IsExternalString() || subject_ptr->IsSeqString());
// String is now either Sequential or External
int char_size_shift = is_ascii ? 0 : 1;
int char_length = end_offset - start_offset;
const byte* input_start =
StringCharacterPosition(subject_ptr, start_offset);
int byte_length = char_length << char_size_shift;
const byte* input_end = input_start + byte_length;
RegExpMacroAssemblerIA32::Result res = Execute(*regexp_code,
subject_ptr,
start_offset,
input_start,
input_end,
offsets_vector,
previous_index == 0);
if (res == SUCCESS) {
// Capture values are relative to start_offset only.
// Convert them to be relative to start of string.
for (int i = 0; i < offsets_vector_length; i++) {
if (offsets_vector[i] >= 0) {
offsets_vector[i] += previous_index;
}
}
}
return res;
}
// Private methods:
static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize;
RegExpMacroAssemblerIA32::Result RegExpMacroAssemblerIA32::Execute(
Code* code,
String* input,
int start_offset,
const byte* input_start,
const byte* input_end,
int* output,
bool at_start) {
typedef int (*matcher)(String*, int, const byte*,
const byte*, int*, int, Address);
matcher matcher_func = FUNCTION_CAST<matcher>(code->entry());
int at_start_val = at_start ? 1 : 0;
// Ensure that the minimum stack has been allocated.
RegExpStack stack;
Address stack_top = RegExpStack::stack_top();
int result = matcher_func(input,
start_offset,
input_start,
input_end,
output,
at_start_val,
stack_top);
ASSERT(result <= SUCCESS);
ASSERT(result >= RETRY);
if (result == EXCEPTION && !Top::has_pending_exception()) {
// We detected a stack overflow (on the backtrack stack) in RegExp code,
// but haven't created the exception yet.
Top::StackOverflow();
}
return static_cast<Result>(result);
}
int RegExpMacroAssemblerIA32::CaseInsensitiveCompareUC16(Address byte_offset1,
Address byte_offset2,
size_t byte_length) {
// This function is not allowed to cause a garbage collection.
// A GC might move the calling generated code and invalidate the
// return address on the stack.
ASSERT(byte_length % 2 == 0);
uc16* substring1 = reinterpret_cast<uc16*>(byte_offset1);
uc16* substring2 = reinterpret_cast<uc16*>(byte_offset2);
size_t length = byte_length >> 1;
for (size_t i = 0; i < length; i++) {
unibrow::uchar c1 = substring1[i];
unibrow::uchar c2 = substring2[i];
if (c1 != c2) {
unibrow::uchar s1[1] = { c1 };
canonicalize.get(c1, '\0', s1);
if (s1[0] != c2) {
unibrow::uchar s2[1] = { c2 };
canonicalize.get(c2, '\0', s2);
if (s1[0] != s2[0]) {
return 0;
}
}
}
}
return 1;
}
void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
int num_arguments = 3;
FrameAlign(num_arguments, scratch);
@ -1096,35 +924,6 @@ static T& frame_entry(Address re_frame, int frame_offset) {
}
const byte* RegExpMacroAssemblerIA32::StringCharacterPosition(String* subject,
int start_index) {
// Not just flat, but ultra flat.
ASSERT(subject->IsExternalString() || subject->IsSeqString());
ASSERT(start_index >= 0);
ASSERT(start_index <= subject->length());
if (subject->IsAsciiRepresentation()) {
const byte* address;
if (StringShape(subject).IsExternal()) {
const char* data = ExternalAsciiString::cast(subject)->resource()->data();
address = reinterpret_cast<const byte*>(data);
} else {
ASSERT(subject->IsSeqAsciiString());
char* data = SeqAsciiString::cast(subject)->GetChars();
address = reinterpret_cast<const byte*>(data);
}
return address + start_index;
}
const uc16* data;
if (StringShape(subject).IsExternal()) {
data = ExternalTwoByteString::cast(subject)->resource()->data();
} else {
ASSERT(subject->IsSeqTwoByteString());
data = SeqTwoByteString::cast(subject)->GetChars();
}
return reinterpret_cast<const byte*>(data + start_index);
}
int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
Code* re_code,
Address re_frame) {
@ -1198,18 +997,18 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
Address RegExpMacroAssemblerIA32::GrowStack(Address stack_pointer,
Address* stack_top) {
Address* stack_base) {
size_t size = RegExpStack::stack_capacity();
Address old_stack_top = RegExpStack::stack_top();
ASSERT(old_stack_top == *stack_top);
ASSERT(stack_pointer <= old_stack_top);
ASSERT(static_cast<size_t>(old_stack_top - stack_pointer) <= size);
Address new_stack_top = RegExpStack::EnsureCapacity(size * 2);
if (new_stack_top == NULL) {
Address old_stack_base = RegExpStack::stack_base();
ASSERT(old_stack_base == *stack_base);
ASSERT(stack_pointer <= old_stack_base);
ASSERT(static_cast<size_t>(old_stack_base - stack_pointer) <= size);
Address new_stack_base = RegExpStack::EnsureCapacity(size * 2);
if (new_stack_base == NULL) {
return NULL;
}
*stack_top = new_stack_top;
return new_stack_top - (old_stack_top - stack_pointer);
*stack_base = new_stack_base;
return new_stack_base - (old_stack_base - stack_pointer);
}
@ -1373,11 +1172,8 @@ void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
}
void RegExpMacroAssemblerIA32::LoadConstantBufferAddress(Register reg,
ArraySlice* buffer) {
__ mov(reg, buffer->array());
__ add(Operand(reg), Immediate(buffer->base_offset()));
}
#undef __
#endif // V8_NATIVE_REGEXP
}} // namespace v8::internal

64
deps/v8/src/ia32/regexp-macro-assembler-ia32.h

@ -31,21 +31,16 @@
namespace v8 {
namespace internal {
#ifndef V8_NATIVE_REGEXP
class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
public:
// Type of input string to generate code for.
enum Mode { ASCII = 1, UC16 = 2 };
// Result of calling the generated RegExp code:
// RETRY: Something significant changed during execution, and the matching
// should be retried from scratch.
// EXCEPTION: Something failed during execution. If no exception has been
// thrown, it's an internal out-of-memory, and the caller should
// throw the exception.
// FAILURE: Matching failed.
// SUCCESS: Matching succeeded, and the output array has been filled with
// capture positions.
enum Result { RETRY = -2, EXCEPTION = -1, FAILURE = 0, SUCCESS = 1 };
RegExpMacroAssemblerIA32() { }
virtual ~RegExpMacroAssemblerIA32() { }
};
#else
class RegExpMacroAssemblerIA32: public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerIA32(Mode mode, int registers_to_save);
virtual ~RegExpMacroAssemblerIA32();
virtual int stack_limit_slack();
@ -54,7 +49,6 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
virtual void Backtrack();
virtual void Bind(Label* label);
virtual void CheckAtStart(Label* on_at_start);
virtual void CheckBitmap(uc16 start, Label* bitmap, Label* on_zero);
virtual void CheckCharacter(uint32_t c, Label* on_equal);
virtual void CheckCharacterAfterAnd(uint32_t c,
uint32_t mask,
@ -88,16 +82,6 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
int cp_offset,
bool check_offset,
Label* on_no_match);
virtual void DispatchByteMap(uc16 start,
Label* byte_map,
const Vector<Label*>& destinations);
virtual void DispatchHalfNibbleMap(uc16 start,
Label* half_nibble_map,
const Vector<Label*>& destinations);
virtual void DispatchHighByteMap(byte start,
Label* byte_map,
const Vector<Label*>& destinations);
virtual void EmitOrLink(Label* label);
virtual void Fail();
virtual Handle<Object> GetCode(Handle<String> source);
virtual void GoTo(Label* label);
@ -123,20 +107,6 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
virtual void ClearRegisters(int reg_from, int reg_to);
virtual void WriteStackPointerToRegister(int reg);
static Result Match(Handle<Code> regexp,
Handle<String> subject,
int* offsets_vector,
int offsets_vector_length,
int previous_index);
static Result Execute(Code* code,
String* input,
int start_offset,
const byte* input_start,
const byte* input_end,
int* output,
bool at_start);
private:
// Offsets from ebp of function parameters and stored registers.
static const int kFramePointer = 0;
@ -163,16 +133,6 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
// Initial size of code buffer.
static const size_t kRegExpCodeSize = 1024;
// Initial size of constant buffers allocated during compilation.
static const int kRegExpConstantsSize = 256;
static const byte* StringCharacterPosition(String* subject, int start_index);
// Compares two-byte strings case insensitively.
// Called from generated RegExp code.
static int CaseInsensitiveCompareUC16(Address byte_offset1,
Address byte_offset2,
size_t byte_length);
// Load a number of characters at the given offset from the
// current position, into the current-character register.
@ -218,11 +178,6 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
// is NULL, in which case it is a conditional Backtrack.
void BranchOrBacktrack(Condition condition, Label* to, Hint hint = no_hint);
// Load the address of a "constant buffer" (a slice of a byte array)
// into a register. The address is computed from the ByteArray* address
// and an offset. Uses no extra registers.
void LoadConstantBufferAddress(Register reg, ArraySlice* buffer);
// Call and return internally in the generated code in a way that
// is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
inline void SafeCall(Label* to);
@ -258,10 +213,6 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
MacroAssembler* masm_;
// Constant buffer provider. Allocates external storage for storing
// constants.
ByteArrayProvider constants_;
// Which mode to generate code for (ASCII or UC16).
Mode mode_;
@ -281,6 +232,7 @@ class RegExpMacroAssemblerIA32: public RegExpMacroAssembler {
Label check_preempt_label_;
Label stack_overflow_label_;
};
#endif // V8_NATIVE_REGEXP
}} // namespace v8::internal

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

@ -38,7 +38,7 @@ namespace internal {
Address IC::address() {
// Get the address of the call.
Address result = pc() - Assembler::kTargetAddrToReturnAddrDist;
Address result = pc() - Assembler::kPatchReturnSequenceLength;
#ifdef ENABLE_DEBUGGER_SUPPORT
// First check if any break points are active if not just return the address

2
deps/v8/src/ic.cc

@ -122,7 +122,7 @@ Address IC::OriginalCodeAddress() {
// Get the address of the call site in the active code. This is the
// place where the call to DebugBreakXXX is and where the IC
// normally would be.
Address addr = pc() - Assembler::kTargetAddrToReturnAddrDist;
Address addr = pc() - Assembler::kPatchReturnSequenceLength;
// Return the address in the original code. This is the place where
// the call which has been overwritten by the DebugBreakXXX resides
// and the place where the inline cache system should look.

2
deps/v8/src/ic.h

@ -390,7 +390,7 @@ class KeyedStoreIC: public IC {
// Support for patching the map that is checked in an inlined
// version of keyed store.
// The address is the patch point for the IC call
// (Assembler::kTargetAddrToReturnAddrDist before the end of
// (Assembler::kPatchReturnSequenceLength before the end of
// the call/return address).
// The map is the new map that the inlined code should check against.
static bool PatchInlinedStore(Address address, Object* map);

79
deps/v8/src/jsregexp.cc

@ -43,6 +43,7 @@
#include "regexp-macro-assembler-irregexp.h"
#include "regexp-stack.h"
#ifdef V8_NATIVE_REGEXP
#if V8_TARGET_ARCH_IA32
#include "ia32/macro-assembler-ia32.h"
#include "ia32/regexp-macro-assembler-ia32.h"
@ -54,6 +55,7 @@
#else
#error Unsupported target architecture.
#endif
#endif
#include "interpreter-irregexp.h"
@ -270,10 +272,11 @@ Handle<Object> RegExpImpl::AtomExec(Handle<JSRegExp> re,
// If compilation fails, an exception is thrown and this function
// returns false.
bool RegExpImpl::EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii) {
Object* compiled_code = re->DataAt(JSRegExp::code_index(is_ascii));
#ifdef V8_NATIVE_REGEXP
if (re->DataAt(JSRegExp::code_index(is_ascii))->IsCode()) return true;
if (compiled_code->IsCode()) return true;
#else // ! V8_NATIVE_REGEXP (RegExp interpreter code)
if (re->DataAt(JSRegExp::code_index(is_ascii))->IsByteArray()) return true;
if (compiled_code->IsByteArray()) return true;
#endif
return CompileIrregexp(re, is_ascii);
}
@ -414,33 +417,36 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
// Dispatch to the correct RegExp implementation.
Handle<FixedArray> regexp(FixedArray::cast(jsregexp->data()));
#ifdef V8_NATIVE_REGEXP
#if V8_TARGET_ARCH_IA32
#ifdef V8_TARGET_ARCH_ARM
UNIMPLEMENTED();
#else // Native regexp supported.
OffsetsVector captures(number_of_capture_registers);
int* captures_vector = captures.vector();
RegExpMacroAssemblerIA32::Result res;
NativeRegExpMacroAssembler::Result res;
do {
bool is_ascii = subject->IsAsciiRepresentation();
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
return Handle<Object>::null();
}
Handle<Code> code(RegExpImpl::IrregexpNativeCode(*regexp, is_ascii));
res = RegExpMacroAssemblerIA32::Match(code,
subject,
captures_vector,
captures.length(),
previous_index);
res = NativeRegExpMacroAssembler::Match(code,
subject,
captures_vector,
captures.length(),
previous_index);
// If result is RETRY, the string have changed representation, and we
// must restart from scratch.
} while (res == RegExpMacroAssemblerIA32::RETRY);
if (res == RegExpMacroAssemblerIA32::EXCEPTION) {
} while (res == NativeRegExpMacroAssembler::RETRY);
if (res == NativeRegExpMacroAssembler::EXCEPTION) {
ASSERT(Top::has_pending_exception());
return Handle<Object>::null();
}
ASSERT(res == RegExpMacroAssemblerIA32::SUCCESS
|| res == RegExpMacroAssemblerIA32::FAILURE);
ASSERT(res == NativeRegExpMacroAssembler::SUCCESS
|| res == NativeRegExpMacroAssembler::FAILURE);
if (res != RegExpMacroAssemblerIA32::SUCCESS) return Factory::null_value();
if (res != NativeRegExpMacroAssembler::SUCCESS) return Factory::null_value();
array = Handle<FixedArray>(FixedArray::cast(last_match_info->elements()));
ASSERT(array->length() >= number_of_capture_registers + kLastMatchOverhead);
@ -449,10 +455,9 @@ Handle<Object> RegExpImpl::IrregexpExec(Handle<JSRegExp> jsregexp,
SetCapture(*array, i, captures_vector[i]);
SetCapture(*array, i + 1, captures_vector[i + 1]);
}
#else // !V8_TARGET_ARCH_IA32
UNREACHABLE();
#endif // V8_TARGET_ARCH_IA32
#else // !V8_NATIVE_REGEXP
#endif // Native regexp supported.
#else // ! V8_NATIVE_REGEXP
bool is_ascii = subject->IsAsciiRepresentation();
if (!EnsureCompiledIrregexp(jsregexp, is_ascii)) {
return Handle<Object>::null();
@ -4457,38 +4462,36 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
NodeInfo info = *node->info();
// Create the correct assembler for the architecture.
#ifdef V8_NATIVE_REGEXP
#ifdef V8_TARGET_ARCH_ARM
// ARM native regexp not implemented yet.
UNREACHABLE();
#endif
#ifdef V8_TARGET_ARCH_X64
// X64 native regexp not implemented yet.
UNREACHABLE();
#endif
// Native regexp implementation.
NativeRegExpMacroAssembler::Mode mode =
is_ascii ? NativeRegExpMacroAssembler::ASCII
: NativeRegExpMacroAssembler::UC16;
#ifdef V8_TARGET_ARCH_IA32
RegExpMacroAssemblerIA32::Mode mode;
if (is_ascii) {
mode = RegExpMacroAssemblerIA32::ASCII;
} else {
mode = RegExpMacroAssemblerIA32::UC16;
}
RegExpMacroAssemblerIA32 macro_assembler(mode,
(data->capture_count + 1) * 2);
return compiler.Assemble(&macro_assembler,
node,
data->capture_count,
pattern);
#endif
#ifdef V8_TARGET_ARCH_X64
RegExpMacroAssemblerX64 macro_assembler(mode,
(data->capture_count + 1) * 2);
#endif
#ifdef V8_TARGET_ARCH_ARM
UNIMPLEMENTED();
#endif
#else // ! V8_NATIVE_REGEXP
// Interpreted regexp.
// Interpreted regexp implementation.
EmbeddedVector<byte, 1024> codes;
RegExpMacroAssemblerIrregexp macro_assembler(codes);
#endif
return compiler.Assemble(&macro_assembler,
node,
data->capture_count,
pattern);
#endif // V8_NATIVE_REGEXP
}
}} // namespace v8::internal

2
deps/v8/src/math.js

@ -184,6 +184,7 @@ function MathTan(x) {
function SetupMath() {
// Setup math constants.
// ECMA-262, section 15.8.1.1.
%OptimizeObjectForAddingMultipleProperties($Math, 8);
%SetProperty($Math,
"E",
2.7182818284590452354,
@ -219,6 +220,7 @@ function SetupMath() {
"SQRT2",
1.4142135623730951,
DONT_ENUM | DONT_DELETE | READ_ONLY);
%TransformToFastProperties($Math);
// Setup non-enumerable functions of the Math object and
// set their names.

13
deps/v8/src/objects-debug.cc

@ -371,9 +371,9 @@ void JSObject::JSObjectVerify() {
VerifyHeapPointer(properties());
VerifyHeapPointer(elements());
if (HasFastProperties()) {
CHECK(map()->unused_property_fields() ==
(map()->inobject_properties() + properties()->length() -
map()->NextFreePropertyIndex()));
CHECK_EQ(map()->unused_property_fields(),
(map()->inobject_properties() + properties()->length() -
map()->NextFreePropertyIndex()));
}
}
@ -462,6 +462,7 @@ void Map::MapPrint() {
HeapObject::PrintHeader("Map");
PrintF(" - type: %s\n", TypeToString(instance_type()));
PrintF(" - instance size: %d\n", instance_size());
PrintF(" - inobject properties: %d\n", inobject_properties());
PrintF(" - unused property fields: %d\n", unused_property_fields());
if (is_hidden_prototype()) {
PrintF(" - hidden_prototype\n");
@ -619,6 +620,12 @@ void SharedFunctionInfo::SharedFunctionInfoPrint() {
PrintF("\n - debug info = ");
debug_info()->ShortPrint();
PrintF("\n - length = %d", length());
PrintF("\n - has_only_this_property_assignments = %d",
has_only_this_property_assignments());
PrintF("\n - has_only_simple_this_property_assignments = %d",
has_only_simple_this_property_assignments());
PrintF("\n - this_property_assignments = ");
this_property_assignments()->ShortPrint();
PrintF("\n");
}

34
deps/v8/src/objects-inl.h

@ -91,7 +91,13 @@ PropertyDetails PropertyDetails::AsDeleted() {
}
#define BOOL_ACCESSORS(holder, field, name, offset) \
#define BOOL_GETTER(holder, field, name, offset) \
bool holder::name() { \
return BooleanBit::get(field(), offset); \
} \
#define BOOL_ACCESSORS(holder, field, name, offset) \
bool holder::name() { \
return BooleanBit::get(field(), offset); \
} \
@ -1937,6 +1943,11 @@ int Map::inobject_properties() {
}
int Map::pre_allocated_property_fields() {
return READ_BYTE_FIELD(this, kPreAllocatedPropertyFieldsOffset);
}
int HeapObject::SizeFromMap(Map* map) {
InstanceType instance_type = map->instance_type();
// Only inline the most frequent cases.
@ -1969,6 +1980,14 @@ void Map::set_inobject_properties(int value) {
}
void Map::set_pre_allocated_property_fields(int value) {
ASSERT(0 <= value && value < 256);
WRITE_BYTE_FIELD(this,
kPreAllocatedPropertyFieldsOffset,
static_cast<byte>(value));
}
InstanceType Map::instance_type() {
return static_cast<InstanceType>(READ_BYTE_FIELD(this, kInstanceTypeOffset));
}
@ -2298,6 +2317,8 @@ ACCESSORS(SharedFunctionInfo, function_data, Object,
ACCESSORS(SharedFunctionInfo, script, Object, kScriptOffset)
ACCESSORS(SharedFunctionInfo, debug_info, Object, kDebugInfoOffset)
ACCESSORS(SharedFunctionInfo, inferred_name, String, kInferredNameOffset)
ACCESSORS(SharedFunctionInfo, this_property_assignments, Object,
kThisPropertyAssignmentsOffset)
BOOL_ACCESSORS(FunctionTemplateInfo, flag, hidden_prototype,
kHiddenPrototypeBit)
@ -2308,6 +2329,13 @@ BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_expression,
kIsExpressionBit)
BOOL_ACCESSORS(SharedFunctionInfo, start_position_and_type, is_toplevel,
kIsTopLevelBit)
BOOL_GETTER(SharedFunctionInfo, compiler_hints,
has_only_this_property_assignments,
kHasOnlyThisPropertyAssignments)
BOOL_GETTER(SharedFunctionInfo, compiler_hints,
has_only_simple_this_property_assignments,
kHasOnlySimpleThisPropertyAssignments)
INT_ACCESSORS(SharedFunctionInfo, length, kLengthOffset)
INT_ACCESSORS(SharedFunctionInfo, formal_parameter_count,
@ -2319,6 +2347,10 @@ INT_ACCESSORS(SharedFunctionInfo, start_position_and_type,
INT_ACCESSORS(SharedFunctionInfo, end_position, kEndPositionOffset)
INT_ACCESSORS(SharedFunctionInfo, function_token_position,
kFunctionTokenPositionOffset)
INT_ACCESSORS(SharedFunctionInfo, compiler_hints,
kCompilerHintsOffset)
INT_ACCESSORS(SharedFunctionInfo, this_property_assignments_count,
kThisPropertyAssignmentsCountOffset)
void SharedFunctionInfo::DontAdaptArguments() {

44
deps/v8/src/objects.cc

@ -4780,6 +4780,48 @@ Object* SharedFunctionInfo::GetSourceCode() {
}
int SharedFunctionInfo::CalculateInstanceSize() {
int instance_size =
JSObject::kHeaderSize +
expected_nof_properties() * kPointerSize;
if (instance_size > JSObject::kMaxInstanceSize) {
instance_size = JSObject::kMaxInstanceSize;
}
return instance_size;
}
int SharedFunctionInfo::CalculateInObjectProperties() {
return (CalculateInstanceSize() - JSObject::kHeaderSize) / kPointerSize;
}
void SharedFunctionInfo::SetThisPropertyAssignmentsInfo(
bool only_this_property_assignments,
bool only_simple_this_property_assignments,
FixedArray* assignments) {
ASSERT(this_property_assignments()->IsUndefined());
set_compiler_hints(BooleanBit::set(compiler_hints(),
kHasOnlyThisPropertyAssignments,
only_this_property_assignments));
set_compiler_hints(BooleanBit::set(compiler_hints(),
kHasOnlySimpleThisPropertyAssignments,
only_simple_this_property_assignments));
set_this_property_assignments(assignments);
set_this_property_assignments_count(assignments->length() / 3);
}
String* SharedFunctionInfo::GetThisPropertyAssignmentName(int index) {
Object* obj = this_property_assignments();
ASSERT(obj->IsFixedArray());
ASSERT(index < this_property_assignments_count());
obj = FixedArray::cast(obj)->get(index * 3);
ASSERT(obj->IsString());
return String::cast(obj);
}
// Support function for printing the source code to a StringStream
// without any allocation in the heap.
void SharedFunctionInfo::SourceCodePrint(StringStream* accumulator,
@ -4826,6 +4868,8 @@ void SharedFunctionInfo::SharedFunctionInfoIterateBody(ObjectVisitor* v) {
IteratePointers(v, kNameOffset, kConstructStubOffset + kPointerSize);
IteratePointers(v, kInstanceClassNameOffset, kScriptOffset + kPointerSize);
IteratePointers(v, kDebugInfoOffset, kInferredNameOffset + kPointerSize);
IteratePointers(v, kThisPropertyAssignmentsOffset,
kThisPropertyAssignmentsOffset + kPointerSize);
}

52
deps/v8/src/objects.h

@ -2704,6 +2704,10 @@ class Map: public HeapObject {
inline int inobject_properties();
inline void set_inobject_properties(int value);
// Count of property fields pre-allocated in the object when first allocated.
inline int pre_allocated_property_fields();
inline void set_pre_allocated_property_fields(int value);
// Instance type.
inline InstanceType instance_type();
inline void set_instance_type(InstanceType value);
@ -2869,6 +2873,8 @@ class Map: public HeapObject {
void MapVerify();
#endif
static const int kMaxPreAllocatedPropertyFields = 255;
// Layout description.
static const int kInstanceSizesOffset = HeapObject::kHeaderSize;
static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize;
@ -2882,7 +2888,8 @@ class Map: public HeapObject {
// Byte offsets within kInstanceSizesOffset.
static const int kInstanceSizeOffset = kInstanceSizesOffset + 0;
static const int kInObjectPropertiesOffset = kInstanceSizesOffset + 1;
// The bytes at positions 2 and 3 are not in use at the moment.
static const int kPreAllocatedPropertyFieldsOffset = kInstanceSizesOffset + 2;
// The byte at position 3 is not in use at the moment.
// Byte offsets within kInstanceAttributesOffset attributes.
static const int kInstanceTypeOffset = kInstanceAttributesOffset + 0;
@ -3090,10 +3097,42 @@ class SharedFunctionInfo: public HeapObject {
inline bool is_toplevel();
inline void set_is_toplevel(bool value);
// Bit field containing various information collected by the compiler to
// drive optimization.
inline int compiler_hints();
inline void set_compiler_hints(int value);
// Add information on assignments of the form this.x = ...;
void SetThisPropertyAssignmentsInfo(
bool has_only_this_property_assignments,
bool has_only_simple_this_property_assignments,
FixedArray* this_property_assignments);
// Indicate that this function only consists of assignments of the form
// this.x = ...;.
inline bool has_only_this_property_assignments();
// Indicate that this function only consists of assignments of the form
// this.x = y; where y is either a constant or refers to an argument.
inline bool has_only_simple_this_property_assignments();
// For functions which only contains this property assignments this provides
// access to the names for the properties assigned.
DECL_ACCESSORS(this_property_assignments, Object)
inline int this_property_assignments_count();
inline void set_this_property_assignments_count(int value);
String* GetThisPropertyAssignmentName(int index);
// [source code]: Source code for the function.
bool HasSourceCode();
Object* GetSourceCode();
// Calculate the instance size.
int CalculateInstanceSize();
// Calculate the number of in-object properties.
int CalculateInObjectProperties();
// Dispatched behavior.
void SharedFunctionInfoIterateBody(ObjectVisitor* v);
// Set max_length to -1 for unlimited length.
@ -3129,7 +3168,12 @@ class SharedFunctionInfo: public HeapObject {
static const int kScriptOffset = kExternalReferenceDataOffset + kPointerSize;
static const int kDebugInfoOffset = kScriptOffset + kPointerSize;
static const int kInferredNameOffset = kDebugInfoOffset + kPointerSize;
static const int kSize = kInferredNameOffset + kPointerSize;
static const int kCompilerHintsOffset = kInferredNameOffset + kPointerSize;
static const int kThisPropertyAssignmentsOffset =
kCompilerHintsOffset + kPointerSize;
static const int kThisPropertyAssignmentsCountOffset =
kThisPropertyAssignmentsOffset + kPointerSize;
static const int kSize = kThisPropertyAssignmentsCountOffset + kPointerSize;
private:
// Bit positions in length_and_flg.
@ -3146,6 +3190,10 @@ class SharedFunctionInfo: public HeapObject {
static const int kStartPositionShift = 2;
static const int kStartPositionMask = ~((1 << kStartPositionShift) - 1);
// Bit positions in compiler_hints.
static const int kHasOnlyThisPropertyAssignments = 0;
static const int kHasOnlySimpleThisPropertyAssignments = 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(SharedFunctionInfo);
};

283
deps/v8/src/parser.cc

@ -97,7 +97,7 @@ class Parser {
// Pre-parse the program from the character stream; returns true on
// success, false if a stack-overflow happened during parsing.
bool PreParseProgram(unibrow::CharacterStream* stream);
bool PreParseProgram(Handle<String> source, unibrow::CharacterStream* stream);
void ReportMessage(const char* message, Vector<const char*> args);
virtual void ReportMessageAt(Scanner::Location loc,
@ -678,6 +678,25 @@ class TemporaryScope BASE_EMBEDDED {
void set_contains_array_literal() { contains_array_literal_ = true; }
bool contains_array_literal() { return contains_array_literal_; }
void SetThisPropertyAssignmentInfo(
bool only_this_property_assignments,
bool only_simple_this_property_assignments,
Handle<FixedArray> this_property_assignments) {
only_this_property_assignments_ = only_this_property_assignments;
only_simple_this_property_assignments_ =
only_simple_this_property_assignments;
this_property_assignments_ = this_property_assignments;
}
bool only_this_property_assignments() {
return only_this_property_assignments_;
}
bool only_simple_this_property_assignments() {
return only_simple_this_property_assignments_;
}
Handle<FixedArray> this_property_assignments() {
return this_property_assignments_;
}
void AddProperty() { expected_property_count_++; }
int expected_property_count() { return expected_property_count_; }
private:
@ -695,6 +714,10 @@ class TemporaryScope BASE_EMBEDDED {
// Properties count estimation.
int expected_property_count_;
bool only_this_property_assignments_;
bool only_simple_this_property_assignments_;
Handle<FixedArray> this_property_assignments_;
// Bookkeeping
Parser* parser_;
TemporaryScope* parent_;
@ -707,6 +730,9 @@ TemporaryScope::TemporaryScope(Parser* parser)
: materialized_literal_count_(0),
contains_array_literal_(false),
expected_property_count_(0),
only_this_property_assignments_(false),
only_simple_this_property_assignments_(false),
this_property_assignments_(Factory::empty_fixed_array()),
parser_(parser),
parent_(parser->temp_scope_) {
parser->temp_scope_ = this;
@ -1167,13 +1193,14 @@ Parser::Parser(Handle<Script> script,
}
bool Parser::PreParseProgram(unibrow::CharacterStream* stream) {
bool Parser::PreParseProgram(Handle<String> source,
unibrow::CharacterStream* stream) {
HistogramTimerScope timer(&Counters::pre_parse);
StackGuard guard;
AssertNoZoneAllocation assert_no_zone_allocation;
AssertNoAllocation assert_no_allocation;
NoHandleAllocation no_handle_allocation;
scanner_.Init(Handle<String>(), stream, 0);
scanner_.Init(source, stream, 0);
ASSERT(target_stack_ == NULL);
mode_ = PARSE_EAGERLY;
DummyScope top_scope;
@ -1217,12 +1244,20 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
bool ok = true;
ParseSourceElements(&body, Token::EOS, &ok);
if (ok) {
result = NEW(FunctionLiteral(no_name, top_scope_,
body.elements(),
temp_scope.materialized_literal_count(),
temp_scope.contains_array_literal(),
temp_scope.expected_property_count(),
0, 0, source->length(), false));
result = NEW(FunctionLiteral(
no_name,
top_scope_,
body.elements(),
temp_scope.materialized_literal_count(),
temp_scope.contains_array_literal(),
temp_scope.expected_property_count(),
temp_scope.only_this_property_assignments(),
temp_scope.only_simple_this_property_assignments(),
temp_scope.this_property_assignments(),
0,
0,
source->length(),
false));
} else if (scanner().stack_overflow()) {
Top::StackOverflow();
}
@ -1313,9 +1348,23 @@ void PreParser::ReportMessageAt(Scanner::Location source_location,
}
// Base class containing common code for the different finder classes used by
// the parser.
class ParserFinder {
protected:
ParserFinder() {}
static Assignment* AsAssignment(Statement* stat) {
if (stat == NULL) return NULL;
ExpressionStatement* exp_stat = stat->AsExpressionStatement();
if (exp_stat == NULL) return NULL;
return exp_stat->expression()->AsAssignment();
}
};
// An InitializationBlockFinder finds and marks sequences of statements of the
// form x.y.z.a = ...; x.y.z.b = ...; etc.
class InitializationBlockFinder {
class InitializationBlockFinder : public ParserFinder {
public:
InitializationBlockFinder()
: first_in_block_(NULL), last_in_block_(NULL), block_size_(0) {}
@ -1340,13 +1389,6 @@ class InitializationBlockFinder {
}
private:
static Assignment* AsAssignment(Statement* stat) {
if (stat == NULL) return NULL;
ExpressionStatement* exp_stat = stat->AsExpressionStatement();
if (exp_stat == NULL) return NULL;
return exp_stat->expression()->AsAssignment();
}
// Returns true if the expressions appear to denote the same object.
// In the context of initialization blocks, we only consider expressions
// of the form 'x.y.z'.
@ -1417,6 +1459,161 @@ class InitializationBlockFinder {
};
// A ThisNamedPropertyAssigmentFinder finds and marks statements of the form
// this.x = ...;, where x is a named property. It also determines whether a
// function contains only assignments of this type.
class ThisNamedPropertyAssigmentFinder : public ParserFinder {
public:
ThisNamedPropertyAssigmentFinder()
: only_this_property_assignments_(true),
only_simple_this_property_assignments_(true),
names_(NULL),
assigned_arguments_(NULL),
assigned_constants_(NULL) {}
void Update(Scope* scope, Statement* stat) {
// Bail out if function already has non this property assignment
// statements.
if (!only_this_property_assignments_) {
return;
}
// Check whether this statement is of the form this.x = ...;
Assignment* assignment = AsAssignment(stat);
if (IsThisPropertyAssignment(assignment)) {
HandleThisPropertyAssignment(scope, assignment);
} else {
only_this_property_assignments_ = false;
only_simple_this_property_assignments_ = false;
}
}
// Returns whether only statements of the form this.x = ...; was encountered.
bool only_this_property_assignments() {
return only_this_property_assignments_;
}
// Returns whether only statements of the form this.x = y; where y is either a
// constant or a function argument was encountered.
bool only_simple_this_property_assignments() {
return only_simple_this_property_assignments_;
}
// Returns a fixed array containing three elements for each assignment of the
// form this.x = y;
Handle<FixedArray> GetThisPropertyAssignments() {
if (names_ == NULL) {
return Factory::empty_fixed_array();
}
ASSERT(names_ != NULL);
ASSERT(assigned_arguments_ != NULL);
ASSERT_EQ(names_->length(), assigned_arguments_->length());
ASSERT_EQ(names_->length(), assigned_constants_->length());
Handle<FixedArray> assignments =
Factory::NewFixedArray(names_->length() * 3);
for (int i = 0; i < names_->length(); i++) {
assignments->set(i * 3, *names_->at(i));
assignments->set(i * 3 + 1, Smi::FromInt(assigned_arguments_->at(i)));
assignments->set(i * 3 + 2, *assigned_constants_->at(i));
}
return assignments;
}
private:
bool IsThisPropertyAssignment(Assignment* assignment) {
if (assignment != NULL) {
Property* property = assignment->target()->AsProperty();
return assignment->op() == Token::ASSIGN
&& property != NULL
&& property->obj()->AsVariableProxy() != NULL
&& property->obj()->AsVariableProxy()->is_this();
}
return false;
}
void HandleThisPropertyAssignment(Scope* scope, Assignment* assignment) {
// Check that the property assigned to is a named property.
Property* property = assignment->target()->AsProperty();
ASSERT(property != NULL);
Literal* literal = property->key()->AsLiteral();
uint32_t dummy;
if (literal != NULL &&
literal->handle()->IsString() &&
!String::cast(*(literal->handle()))->AsArrayIndex(&dummy)) {
Handle<String> key = Handle<String>::cast(literal->handle());
// Check whether the value assigned is either a constant or matches the
// name of one of the arguments to the function.
if (assignment->value()->AsLiteral() != NULL) {
// Constant assigned.
Literal* literal = assignment->value()->AsLiteral();
AssignmentFromConstant(key, literal->handle());
} else if (assignment->value()->AsVariableProxy() != NULL) {
// Variable assigned.
Handle<String> name =
assignment->value()->AsVariableProxy()->name();
// Check whether the variable assigned matches an argument name.
int index = -1;
for (int i = 0; i < scope->num_parameters(); i++) {
if (*scope->parameter(i)->name() == *name) {
// Assigned from function argument.
index = i;
break;
}
}
if (index != -1) {
AssignmentFromParameter(key, index);
} else {
AssignmentFromSomethingElse(key);
}
} else {
AssignmentFromSomethingElse(key);
}
}
}
void AssignmentFromParameter(Handle<String> name, int index) {
EnsureAllocation();
names_->Add(name);
assigned_arguments_->Add(index);
assigned_constants_->Add(Factory::undefined_value());
}
void AssignmentFromConstant(Handle<String> name, Handle<Object> value) {
EnsureAllocation();
names_->Add(name);
assigned_arguments_->Add(-1);
assigned_constants_->Add(value);
}
void AssignmentFromSomethingElse(Handle<String> name) {
EnsureAllocation();
names_->Add(name);
assigned_arguments_->Add(-1);
assigned_constants_->Add(Factory::undefined_value());
// The this assignment is not a simple one.
only_simple_this_property_assignments_ = false;
}
void EnsureAllocation() {
if (names_ == NULL) {
ASSERT(assigned_arguments_ == NULL);
ASSERT(assigned_constants_ == NULL);
names_ = new ZoneStringList(4);
assigned_arguments_ = new ZoneList<int>(4);
assigned_constants_ = new ZoneObjectList(4);
}
}
bool only_this_property_assignments_;
bool only_simple_this_property_assignments_;
ZoneStringList* names_;
ZoneList<int>* assigned_arguments_;
ZoneObjectList* assigned_constants_;
};
void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor,
int end_token,
bool* ok) {
@ -1431,15 +1628,33 @@ void* Parser::ParseSourceElements(ZoneListWrapper<Statement>* processor,
ASSERT(processor != NULL);
InitializationBlockFinder block_finder;
ThisNamedPropertyAssigmentFinder this_property_assignment_finder;
while (peek() != end_token) {
Statement* stat = ParseStatement(NULL, CHECK_OK);
if (stat == NULL || stat->IsEmpty()) continue;
// We find and mark the initialization blocks on top level code only.
// This is because the optimization prevents reuse of the map transitions,
// so it should be used only for code that will only be run once.
if (top_scope_->is_global_scope()) block_finder.Update(stat);
if (top_scope_->is_global_scope()) {
block_finder.Update(stat);
}
// Find and mark all assignments to named properties in this (this.x =)
if (top_scope_->is_function_scope()) {
this_property_assignment_finder.Update(top_scope_, stat);
}
processor->Add(stat);
}
// Propagate the collected information on this property assignments.
if (top_scope_->is_function_scope()) {
if (this_property_assignment_finder.only_this_property_assignments()) {
temp_scope_->SetThisPropertyAssignmentInfo(
this_property_assignment_finder.only_this_property_assignments(),
this_property_assignment_finder.
only_simple_this_property_assignments(),
this_property_assignment_finder.GetThisPropertyAssignments());
}
}
return 0;
}
@ -3506,6 +3721,9 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
int materialized_literal_count;
int expected_property_count;
bool contains_array_literal;
bool only_this_property_assignments;
bool only_simple_this_property_assignments;
Handle<FixedArray> this_property_assignments;
if (is_lazily_compiled && pre_data() != NULL) {
FunctionEntry entry = pre_data()->GetFunctionEnd(start_pos);
int end_pos = entry.end_pos();
@ -3513,12 +3731,20 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
scanner_.SeekForward(end_pos);
materialized_literal_count = entry.literal_count();
expected_property_count = entry.property_count();
only_this_property_assignments = false;
only_simple_this_property_assignments = false;
this_property_assignments = Factory::empty_fixed_array();
contains_array_literal = entry.contains_array_literal();
} else {
ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
materialized_literal_count = temp_scope.materialized_literal_count();
expected_property_count = temp_scope.expected_property_count();
contains_array_literal = temp_scope.contains_array_literal();
only_this_property_assignments =
temp_scope.only_this_property_assignments();
only_simple_this_property_assignments =
temp_scope.only_simple_this_property_assignments();
this_property_assignments = temp_scope.this_property_assignments();
}
Expect(Token::RBRACE, CHECK_OK);
@ -3533,10 +3759,18 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
}
FunctionLiteral* function_literal =
NEW(FunctionLiteral(name, top_scope_,
body.elements(), materialized_literal_count,
contains_array_literal, expected_property_count,
num_parameters, start_pos, end_pos,
NEW(FunctionLiteral(name,
top_scope_,
body.elements(),
materialized_literal_count,
contains_array_literal,
expected_property_count,
only_this_property_assignments,
only_simple_this_property_assignments,
this_property_assignments,
num_parameters,
start_pos,
end_pos,
function_name->length() > 0));
if (!is_pre_parsing_) {
function_literal->set_function_token_position(function_token_position);
@ -4593,7 +4827,8 @@ unsigned* ScriptDataImpl::Data() {
}
ScriptDataImpl* PreParse(unibrow::CharacterStream* stream,
ScriptDataImpl* PreParse(Handle<String> source,
unibrow::CharacterStream* stream,
v8::Extension* extension) {
Handle<Script> no_script;
bool allow_natives_syntax =
@ -4601,7 +4836,7 @@ ScriptDataImpl* PreParse(unibrow::CharacterStream* stream,
FLAG_allow_natives_syntax ||
Bootstrapper::IsActive();
PreParser parser(no_script, allow_natives_syntax, extension);
if (!parser.PreParseProgram(stream)) return NULL;
if (!parser.PreParseProgram(source, stream)) return NULL;
// The list owns the backing store so we need to clone the vector.
// That way, the result will be exactly the right size rather than
// the expected 50% too large.

3
deps/v8/src/parser.h

@ -143,7 +143,8 @@ FunctionLiteral* MakeAST(bool compile_in_global_context,
ScriptDataImpl* pre_data);
ScriptDataImpl* PreParse(unibrow::CharacterStream* stream,
ScriptDataImpl* PreParse(Handle<String> source,
unibrow::CharacterStream* stream,
v8::Extension* extension);

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

@ -54,6 +54,10 @@
#define _WIN32_WINNT 0x500
#endif
#ifdef _WIN64
#error Windows 64-bit blatforms not supported
#endif
#include <windows.h>
#include <time.h> // For LocalOffset() implementation.

31
deps/v8/src/regexp-macro-assembler-irregexp.cc

@ -375,37 +375,6 @@ void RegExpMacroAssemblerIrregexp::CheckNotRegistersEqual(int reg1,
}
void RegExpMacroAssemblerIrregexp::CheckBitmap(uc16 start,
Label* bitmap,
Label* on_zero) {
UNIMPLEMENTED();
}
void RegExpMacroAssemblerIrregexp::DispatchHalfNibbleMap(
uc16 start,
Label* half_nibble_map,
const Vector<Label*>& table) {
UNIMPLEMENTED();
}
void RegExpMacroAssemblerIrregexp::DispatchByteMap(
uc16 start,
Label* byte_map,
const Vector<Label*>& table) {
UNIMPLEMENTED();
}
void RegExpMacroAssemblerIrregexp::DispatchHighByteMap(
byte start,
Label* byte_map,
const Vector<Label*>& table) {
UNIMPLEMENTED();
}
void RegExpMacroAssemblerIrregexp::CheckCharacters(
Vector<const uc16> str,
int cp_offset,

12
deps/v8/src/regexp-macro-assembler-irregexp.h

@ -52,7 +52,6 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
// The byte-code interpreter checks on each push anyway.
virtual int stack_limit_slack() { return 1; }
virtual void Bind(Label* label);
virtual void EmitOrLink(Label* label);
virtual void AdvanceCurrentPosition(int by); // Signed cp change.
virtual void PopCurrentPosition();
virtual void PushCurrentPosition();
@ -100,16 +99,6 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
int cp_offset,
Label* on_failure,
bool check_end_of_string);
virtual void CheckBitmap(uc16 start, Label* bitmap, Label* on_zero);
virtual void DispatchHalfNibbleMap(uc16 start,
Label* half_nibble_map,
const Vector<Label*>& destinations);
virtual void DispatchByteMap(uc16 start,
Label* byte_map,
const Vector<Label*>& destinations);
virtual void DispatchHighByteMap(byte start,
Label* byte_map,
const Vector<Label*>& destinations);
virtual void IfRegisterLT(int register_index, int comparand, Label* if_lt);
virtual void IfRegisterGE(int register_index, int comparand, Label* if_ge);
virtual void IfRegisterEqPos(int register_index, Label* if_eq);
@ -119,6 +108,7 @@ class RegExpMacroAssemblerIrregexp: public RegExpMacroAssembler {
private:
void Expand();
// Code and bitmap emission.
inline void EmitOrLink(Label* label);
inline void Emit32(uint32_t x);
inline void Emit16(uint32_t x);
inline void Emit(uint32_t bc, uint32_t arg);

58
deps/v8/src/regexp-macro-assembler-tracer.cc

@ -53,12 +53,6 @@ void RegExpMacroAssemblerTracer::Bind(Label* label) {
}
void RegExpMacroAssemblerTracer::EmitOrLink(Label* label) {
PrintF(" EmitOrLink(label[%08x]);\n", label);
assembler_->EmitOrLink(label);
}
void RegExpMacroAssemblerTracer::AdvanceCurrentPosition(int by) {
PrintF(" AdvanceCurrentPosition(by=%d);\n", by);
assembler_->AdvanceCurrentPosition(by);
@ -311,13 +305,6 @@ void RegExpMacroAssemblerTracer::CheckCharacters(Vector<const uc16> str,
}
void RegExpMacroAssemblerTracer::CheckBitmap(uc16 start, Label* bitmap,
Label* on_zero) {
PrintF(" CheckBitmap(start=u%04x, <bitmap>, label[%08x]);\n", start, on_zero);
assembler_->CheckBitmap(start, bitmap, on_zero);
}
bool RegExpMacroAssemblerTracer::CheckSpecialCharacterClass(
uc16 type,
int cp_offset,
@ -338,51 +325,6 @@ bool RegExpMacroAssemblerTracer::CheckSpecialCharacterClass(
}
void RegExpMacroAssemblerTracer::DispatchHalfNibbleMap(
uc16 start,
Label* half_nibble_map,
const Vector<Label*>& destinations) {
PrintF(" DispatchHalfNibbleMap(start=u%04x, <half_nibble_map>, [", start);
for (int i = 0; i < destinations.length(); i++) {
if (i > 0)
PrintF(", ");
PrintF("label[%08x]", destinations[i]);
}
PrintF(");\n");
assembler_->DispatchHalfNibbleMap(start, half_nibble_map, destinations);
}
void RegExpMacroAssemblerTracer::DispatchByteMap(
uc16 start,
Label* byte_map,
const Vector<Label*>& destinations) {
PrintF(" DispatchByteMap(start=u%04x, <byte_map>, [", start);
for (int i = 0; i < destinations.length(); i++) {
if (i > 0)
PrintF(", ");
PrintF("label[%08x]", destinations[i]);
}
PrintF(");\n");
assembler_->DispatchByteMap(start, byte_map, destinations);
}
void RegExpMacroAssemblerTracer::DispatchHighByteMap(
byte start,
Label* byte_map,
const Vector<Label*>& destinations) {
PrintF(" DispatchHighByteMap(start=u%04x, <byte_map>, [", start);
for (int i = 0; i < destinations.length(); i++) {
if (i > 0)
PrintF(", ");
PrintF("label[%08x]", destinations[i]);
}
PrintF(");\n");
assembler_->DispatchHighByteMap(start, byte_map, destinations);
}
void RegExpMacroAssemblerTracer::IfRegisterLT(int register_index,
int comparand, Label* if_lt) {
PrintF(" IfRegisterLT(register=%d, number=%d, label[%08x]);\n",

14
deps/v8/src/regexp-macro-assembler-tracer.h

@ -43,7 +43,6 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
virtual void Backtrack();
virtual void Bind(Label* label);
virtual void CheckAtStart(Label* on_at_start);
virtual void CheckBitmap(uc16 start, Label* bitmap, Label* on_zero);
virtual void CheckCharacter(uint32_t c, Label* on_equal);
virtual void CheckCharacterAfterAnd(uint32_t c,
uint32_t and_with,
@ -73,19 +72,6 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
int cp_offset,
bool check_offset,
Label* on_no_match);
virtual void DispatchByteMap(
uc16 start,
Label* byte_map,
const Vector<Label*>& destinations);
virtual void DispatchHalfNibbleMap(
uc16 start,
Label* half_nibble_map,
const Vector<Label*>& destinations);
virtual void DispatchHighByteMap(
byte start,
Label* byte_map,
const Vector<Label*>& destinations);
virtual void EmitOrLink(Label* label);
virtual void Fail();
virtual Handle<Object> GetCode(Handle<String> source);
virtual void GoTo(Label* label);

190
deps/v8/src/regexp-macro-assembler.cc

@ -25,10 +25,10 @@
// (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 <string.h>
#include "v8.h"
#include "ast.h"
#include "assembler.h"
#include "regexp-stack.h"
#include "regexp-macro-assembler.h"
namespace v8 {
@ -42,38 +42,176 @@ RegExpMacroAssembler::~RegExpMacroAssembler() {
}
ByteArrayProvider::ByteArrayProvider(unsigned int initial_size)
: byte_array_size_(initial_size),
current_byte_array_(),
current_byte_array_free_offset_(initial_size) {}
#ifdef V8_NATIVE_REGEXP // Avoid unused code, e.g., on ARM.
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler() {
}
ArraySlice ByteArrayProvider::GetBuffer(unsigned int size,
unsigned int elem_size) {
ASSERT(size > 0);
size_t byte_size = size * elem_size;
int free_offset = current_byte_array_free_offset_;
// align elements
free_offset += elem_size - 1;
free_offset = free_offset - (free_offset % elem_size);
NativeRegExpMacroAssembler::~NativeRegExpMacroAssembler() {
}
if (free_offset + byte_size > byte_array_size_) {
if (byte_size > (byte_array_size_ / 2)) {
Handle<ByteArray> solo_buffer(Factory::NewByteArray(byte_size, TENURED));
return ArraySlice(solo_buffer, 0);
const byte* NativeRegExpMacroAssembler::StringCharacterPosition(
String* subject,
int start_index) {
// Not just flat, but ultra flat.
ASSERT(subject->IsExternalString() || subject->IsSeqString());
ASSERT(start_index >= 0);
ASSERT(start_index <= subject->length());
if (subject->IsAsciiRepresentation()) {
const byte* address;
if (StringShape(subject).IsExternal()) {
const char* data = ExternalAsciiString::cast(subject)->resource()->data();
address = reinterpret_cast<const byte*>(data);
} else {
ASSERT(subject->IsSeqAsciiString());
char* data = SeqAsciiString::cast(subject)->GetChars();
address = reinterpret_cast<const byte*>(data);
}
current_byte_array_ = Factory::NewByteArray(byte_array_size_, TENURED);
free_offset = 0;
return address + start_index;
}
const uc16* data;
if (StringShape(subject).IsExternal()) {
data = ExternalTwoByteString::cast(subject)->resource()->data();
} else {
ASSERT(subject->IsSeqTwoByteString());
data = SeqTwoByteString::cast(subject)->GetChars();
}
current_byte_array_free_offset_ = free_offset + byte_size;
return ArraySlice(current_byte_array_, free_offset);
return reinterpret_cast<const byte*>(data + start_index);
}
template <typename T>
ArraySlice ByteArrayProvider::GetBuffer(Vector<T> values) {
ArraySlice slice = GetBuffer(values.length(), sizeof(T));
memcpy(slice.location(), values.start(), values.length() * sizeof(T));
return slice;
NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Match(
Handle<Code> regexp_code,
Handle<String> subject,
int* offsets_vector,
int offsets_vector_length,
int previous_index) {
ASSERT(subject->IsFlat());
ASSERT(previous_index >= 0);
ASSERT(previous_index <= subject->length());
// No allocations before calling the regexp, but we can't use
// AssertNoAllocation, since regexps might be preempted, and another thread
// might do allocation anyway.
String* subject_ptr = *subject;
// Character offsets into string.
int start_offset = previous_index;
int end_offset = subject_ptr->length();
bool is_ascii = subject->IsAsciiRepresentation();
if (StringShape(subject_ptr).IsCons()) {
subject_ptr = ConsString::cast(subject_ptr)->first();
} else if (StringShape(subject_ptr).IsSliced()) {
SlicedString* slice = SlicedString::cast(subject_ptr);
start_offset += slice->start();
end_offset += slice->start();
subject_ptr = slice->buffer();
}
// Ensure that an underlying string has the same ascii-ness.
ASSERT(subject_ptr->IsAsciiRepresentation() == is_ascii);
ASSERT(subject_ptr->IsExternalString() || subject_ptr->IsSeqString());
// String is now either Sequential or External
int char_size_shift = is_ascii ? 0 : 1;
int char_length = end_offset - start_offset;
const byte* input_start =
StringCharacterPosition(subject_ptr, start_offset);
int byte_length = char_length << char_size_shift;
const byte* input_end = input_start + byte_length;
Result res = Execute(*regexp_code,
subject_ptr,
start_offset,
input_start,
input_end,
offsets_vector,
previous_index == 0);
if (res == SUCCESS) {
// Capture values are relative to start_offset only.
// Convert them to be relative to start of string.
for (int i = 0; i < offsets_vector_length; i++) {
if (offsets_vector[i] >= 0) {
offsets_vector[i] += previous_index;
}
}
}
return res;
}
NativeRegExpMacroAssembler::Result NativeRegExpMacroAssembler::Execute(
Code* code,
String* input,
int start_offset,
const byte* input_start,
const byte* input_end,
int* output,
bool at_start) {
typedef int (*matcher)(String*, int, const byte*,
const byte*, int*, int, Address);
matcher matcher_func = FUNCTION_CAST<matcher>(code->entry());
int at_start_val = at_start ? 1 : 0;
// Ensure that the minimum stack has been allocated.
RegExpStack stack;
Address stack_base = RegExpStack::stack_base();
int result = matcher_func(input,
start_offset,
input_start,
input_end,
output,
at_start_val,
stack_base);
ASSERT(result <= SUCCESS);
ASSERT(result >= RETRY);
if (result == EXCEPTION && !Top::has_pending_exception()) {
// We detected a stack overflow (on the backtrack stack) in RegExp code,
// but haven't created the exception yet.
Top::StackOverflow();
}
return static_cast<Result>(result);
}
static unibrow::Mapping<unibrow::Ecma262Canonicalize> canonicalize;
int NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16(
Address byte_offset1,
Address byte_offset2,
size_t byte_length) {
// This function is not allowed to cause a garbage collection.
// A GC might move the calling generated code and invalidate the
// return address on the stack.
ASSERT(byte_length % 2 == 0);
uc16* substring1 = reinterpret_cast<uc16*>(byte_offset1);
uc16* substring2 = reinterpret_cast<uc16*>(byte_offset2);
size_t length = byte_length >> 1;
for (size_t i = 0; i < length; i++) {
unibrow::uchar c1 = substring1[i];
unibrow::uchar c2 = substring2[i];
if (c1 != c2) {
unibrow::uchar s1[1] = { c1 };
canonicalize.get(c1, '\0', s1);
if (s1[0] != c2) {
unibrow::uchar s2[1] = { c2 };
canonicalize.get(c2, '\0', s2);
if (s1[0] != s2[0]) {
return 0;
}
}
}
}
return 1;
}
#endif // V8_NATIVE_REGEXP
} } // namespace v8::internal

102
deps/v8/src/regexp-macro-assembler.h

@ -46,6 +46,7 @@ class RegExpMacroAssembler {
enum IrregexpImplementation {
kIA32Implementation,
kARMImplementation,
kX64Implementation,
kBytecodeImplementation
};
@ -67,12 +68,6 @@ class RegExpMacroAssembler {
virtual void Backtrack() = 0;
virtual void Bind(Label* label) = 0;
virtual void CheckAtStart(Label* on_at_start) = 0;
// Check the current character against a bitmap. The range of the current
// character must be from start to start + length_of_bitmap_in_bits.
virtual void CheckBitmap(
uc16 start, // The bitmap is indexed from this character.
Label* bitmap, // Where the bitmap is emitted.
Label* on_zero) = 0; // Where to go if the bit is 0. Fall through on 1.
// Dispatch after looking the current character up in a 2-bits-per-entry
// map. The destinations vector has up to 4 labels.
virtual void CheckCharacter(uint32_t c, Label* on_equal) = 0;
@ -132,23 +127,6 @@ class RegExpMacroAssembler {
Label* on_no_match) {
return false;
}
// Dispatch after looking the current character up in a byte map. The
// destinations vector has up to 256 labels.
virtual void DispatchByteMap(
uc16 start,
Label* byte_map,
const Vector<Label*>& destinations) = 0;
virtual void DispatchHalfNibbleMap(
uc16 start,
Label* half_nibble_map,
const Vector<Label*>& destinations) = 0;
// Dispatch after looking the high byte of the current character up in a byte
// map. The destinations vector has up to 256 labels.
virtual void DispatchHighByteMap(
byte start,
Label* byte_map,
const Vector<Label*>& destinations) = 0;
virtual void EmitOrLink(Label* label) = 0;
virtual void Fail() = 0;
virtual Handle<Object> GetCode(Handle<String> source) = 0;
virtual void GoTo(Label* label) = 0;
@ -181,51 +159,53 @@ class RegExpMacroAssembler {
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset) = 0;
virtual void ClearRegisters(int reg_from, int reg_to) = 0;
virtual void WriteStackPointerToRegister(int reg) = 0;
private:
};
struct ArraySlice {
#ifdef V8_NATIVE_REGEXP // Avoid compiling unused code.
class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
public:
ArraySlice(Handle<ByteArray> array, size_t offset)
: array_(array), offset_(offset) {}
Handle<ByteArray> array() { return array_; }
// Offset in the byte array data.
size_t offset() { return offset_; }
// Offset from the ByteArray pointer.
size_t base_offset() {
return ByteArray::kHeaderSize - kHeapObjectTag + offset_;
}
void* location() {
return reinterpret_cast<void*>(array_->GetDataStartAddress() + offset_);
}
template <typename T>
T& at(int idx) {
return reinterpret_cast<T*>(array_->GetDataStartAddress() + offset_)[idx];
}
private:
Handle<ByteArray> array_;
size_t offset_;
};
// Type of input string to generate code for.
enum Mode { ASCII = 1, UC16 = 2 };
// Result of calling generated native RegExp code.
// RETRY: Something significant changed during execution, and the matching
// should be retried from scratch.
// EXCEPTION: Something failed during execution. If no exception has been
// thrown, it's an internal out-of-memory, and the caller should
// throw the exception.
// FAILURE: Matching failed.
// SUCCESS: Matching succeeded, and the output array has been filled with
// capture positions.
enum Result { RETRY = -2, EXCEPTION = -1, FAILURE = 0, SUCCESS = 1 };
class ByteArrayProvider {
public:
explicit ByteArrayProvider(unsigned int initial_size);
// Provides a place to put "size" elements of size "element_size".
// The information can be stored in the provided ByteArray at the "offset".
// The offset is aligned to the element size.
ArraySlice GetBuffer(unsigned int size,
unsigned int element_size);
template <typename T>
ArraySlice GetBuffer(Vector<T> values);
private:
size_t byte_array_size_;
Handle<ByteArray> current_byte_array_;
int current_byte_array_free_offset_;
};
NativeRegExpMacroAssembler();
virtual ~NativeRegExpMacroAssembler();
static Result Match(Handle<Code> regexp,
Handle<String> subject,
int* offsets_vector,
int offsets_vector_length,
int previous_index);
// Compares two-byte strings case insensitively.
// Called from generated RegExp code.
static int CaseInsensitiveCompareUC16(Address byte_offset1,
Address byte_offset2,
size_t byte_length);
static const byte* StringCharacterPosition(String* subject, int start_index);
static Result Execute(Code* code,
String* input,
int start_offset,
const byte* input_start,
const byte* input_end,
int* output,
bool at_start);
};
#endif // V8_NATIVE_REGEXP
} } // namespace v8::internal
#endif // V8_REGEXP_MACRO_ASSEMBLER_H_

4
deps/v8/src/regexp-stack.h

@ -48,7 +48,7 @@ class RegExpStack {
~RegExpStack(); // Releases the stack if it has grown.
// Gives the top of the memory used as stack.
static Address stack_top() {
static Address stack_base() {
ASSERT(thread_local_.memory_size_ != 0);
return thread_local_.memory_ + thread_local_.memory_size_;
}
@ -74,7 +74,7 @@ class RegExpStack {
private:
// Artificial limit used when no memory has been allocated.
static const uint32_t kMemoryTop = 0xffffffff;
static const uintptr_t kMemoryTop = static_cast<uintptr_t>(-1);
// Minimal size of allocated stack area.
static const size_t kMinimumStackSize = 1 * KB;

28
deps/v8/src/runtime.cc

@ -1022,6 +1022,30 @@ static Object* Runtime_InitializeConstContextSlot(Arguments args) {
}
static Object* Runtime_OptimizeObjectForAddingMultipleProperties(
Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(JSObject, object, 0);
CONVERT_SMI_CHECKED(properties, args[1]);
if (object->HasFastProperties()) {
NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
}
return *object;
}
static Object* Runtime_TransformToFastProperties(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(JSObject, object, 0);
if (!object->HasFastProperties() && !object->IsGlobalObject()) {
TransformToFastProperties(object, 0);
}
return *object;
}
static Object* Runtime_RegExpExec(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 4);
@ -3075,7 +3099,7 @@ static Object* Runtime_Typeof(Arguments args) {
}
ASSERT(heap_obj->IsUndefined());
return Heap::undefined_symbol();
case JS_FUNCTION_TYPE:
case JS_FUNCTION_TYPE: case JS_REGEXP_TYPE:
return Heap::function_symbol();
default:
// For any kind of object not handled above, the spec rule for
@ -4356,6 +4380,8 @@ static Object* Runtime_NewObject(Arguments args) {
Handle<Code> stub = ComputeConstructStub(map);
function->shared()->set_construct_stub(*stub);
}
Counters::constructed_objects.Increment();
Counters::constructed_objects_runtime.Increment();
return *result;
}

2
deps/v8/src/runtime.h

@ -247,6 +247,8 @@ namespace internal {
F(InitializeVarGlobal, -1 /* 1 or 2 */) \
F(InitializeConstGlobal, 2) \
F(InitializeConstContextSlot, 3) \
F(OptimizeObjectForAddingMultipleProperties, 2) \
F(TransformToFastProperties, 1) \
\
/* Debugging */ \
F(DebugPrint, 1) \

97
deps/v8/src/scanner.cc

@ -92,33 +92,35 @@ void UTF8Buffer::AddCharSlow(uc32 c) {
UTF16Buffer::UTF16Buffer()
: pos_(0),
pushback_buffer_(0),
last_(0),
stream_(NULL) { }
: pos_(0), size_(0) { }
void UTF16Buffer::Initialize(Handle<String> data,
unibrow::CharacterStream* input) {
data_ = data;
pos_ = 0;
stream_ = input;
Handle<String> UTF16Buffer::SubString(int start, int end) {
return internal::SubString(data_, start, end);
}
Handle<String> UTF16Buffer::SubString(int start, int end) {
return internal::SubString(data_, start, end);
// CharacterStreamUTF16Buffer
CharacterStreamUTF16Buffer::CharacterStreamUTF16Buffer()
: pushback_buffer_(0), last_(0), stream_(NULL) { }
void CharacterStreamUTF16Buffer::Initialize(Handle<String> data,
unibrow::CharacterStream* input) {
data_ = data;
pos_ = 0;
stream_ = input;
}
void UTF16Buffer::PushBack(uc32 ch) {
void CharacterStreamUTF16Buffer::PushBack(uc32 ch) {
pushback_buffer()->Add(last_);
last_ = ch;
pos_--;
}
uc32 UTF16Buffer::Advance() {
uc32 CharacterStreamUTF16Buffer::Advance() {
// NOTE: It is of importance to Persian / Farsi resources that we do
// *not* strip format control characters in the scanner; see
//
@ -135,7 +137,7 @@ uc32 UTF16Buffer::Advance() {
uc32 next = stream_->GetNext();
return last_ = next;
} else {
// note: currently the following increment is necessary to avoid a
// Note: currently the following increment is necessary to avoid a
// test-parser problem!
pos_++;
return last_ = static_cast<uc32>(-1);
@ -143,13 +145,53 @@ uc32 UTF16Buffer::Advance() {
}
void UTF16Buffer::SeekForward(int pos) {
void CharacterStreamUTF16Buffer::SeekForward(int pos) {
pos_ = pos;
ASSERT(pushback_buffer()->is_empty());
stream_->Seek(pos);
}
// TwoByteStringUTF16Buffer
TwoByteStringUTF16Buffer::TwoByteStringUTF16Buffer()
: raw_data_(NULL) { }
void TwoByteStringUTF16Buffer::Initialize(
Handle<ExternalTwoByteString> data) {
ASSERT(!data.is_null());
data_ = data;
pos_ = 0;
raw_data_ = data->resource()->data();
size_ = data->length();
}
uc32 TwoByteStringUTF16Buffer::Advance() {
if (pos_ < size_) {
return raw_data_[pos_++];
} else {
// note: currently the following increment is necessary to avoid a
// test-parser problem!
pos_++;
return static_cast<uc32>(-1);
}
}
void TwoByteStringUTF16Buffer::PushBack(uc32 ch) {
pos_--;
ASSERT(pos_ >= 0 && raw_data_[pos_] == ch);
}
void TwoByteStringUTF16Buffer::SeekForward(int pos) {
pos_ = pos;
}
// ----------------------------------------------------------------------------
// Scanner
@ -161,7 +203,15 @@ Scanner::Scanner(bool pre) : stack_overflow_(false), is_pre_parsing_(pre) {
void Scanner::Init(Handle<String> source, unibrow::CharacterStream* stream,
int position) {
// Initialize the source buffer.
source_.Initialize(source, stream);
if (!source.is_null() && StringShape(*source).IsExternalTwoByte()) {
two_byte_string_buffer_.Initialize(
Handle<ExternalTwoByteString>::cast(source));
source_ = &two_byte_string_buffer_;
} else {
char_stream_buffer_.Initialize(source, stream);
source_ = &char_stream_buffer_;
}
position_ = position;
// Reset literals buffer
@ -180,7 +230,7 @@ void Scanner::Init(Handle<String> source, unibrow::CharacterStream* stream,
Handle<String> Scanner::SubString(int start, int end) {
return source_.SubString(start - position_, end - position_);
return source_->SubString(start - position_, end - position_);
}
@ -223,17 +273,6 @@ void Scanner::AddCharAdvance() {
}
void Scanner::Advance() {
c0_ = source_.Advance();
}
void Scanner::PushBack(uc32 ch) {
source_.PushBack(ch);
c0_ = ch;
}
static inline bool IsByteOrderMark(uc32 c) {
// The Unicode value U+FFFE is guaranteed never to be assigned as a
// Unicode character; this implies that in a Unicode context the
@ -583,7 +622,7 @@ void Scanner::Scan() {
void Scanner::SeekForward(int pos) {
source_.SeekForward(pos - 1);
source_->SeekForward(pos - 1);
Advance();
Scan();
}

57
deps/v8/src/scanner.h

@ -73,24 +73,53 @@ class UTF8Buffer {
class UTF16Buffer {
public:
UTF16Buffer();
virtual ~UTF16Buffer() {}
virtual void PushBack(uc32 ch) = 0;
// returns a value < 0 when the buffer end is reached
virtual uc32 Advance() = 0;
virtual void SeekForward(int pos) = 0;
void Initialize(Handle<String> data, unibrow::CharacterStream* stream);
void PushBack(uc32 ch);
uc32 Advance(); // returns a value < 0 when the buffer end is reached
uint16_t CharAt(int index);
int pos() const { return pos_; }
int size() const { return size_; }
Handle<String> SubString(int start, int end);
List<uc32>* pushback_buffer() { return &pushback_buffer_; }
void SeekForward(int pos);
private:
protected:
Handle<String> data_;
int pos_;
int size_;
};
class CharacterStreamUTF16Buffer: public UTF16Buffer {
public:
CharacterStreamUTF16Buffer();
virtual ~CharacterStreamUTF16Buffer() {}
void Initialize(Handle<String> data, unibrow::CharacterStream* stream);
virtual void PushBack(uc32 ch);
virtual uc32 Advance();
virtual void SeekForward(int pos);
private:
List<uc32> pushback_buffer_;
uc32 last_;
unibrow::CharacterStream* stream_;
List<uc32>* pushback_buffer() { return &pushback_buffer_; }
};
class TwoByteStringUTF16Buffer: public UTF16Buffer {
public:
TwoByteStringUTF16Buffer();
virtual ~TwoByteStringUTF16Buffer() {}
void Initialize(Handle<ExternalTwoByteString> data);
virtual void PushBack(uc32 ch);
virtual uc32 Advance();
virtual void SeekForward(int pos);
private:
const uint16_t* raw_data_;
};
@ -184,8 +213,11 @@ class Scanner {
static unibrow::Predicate<unibrow::WhiteSpace, 128> kIsWhiteSpace;
private:
CharacterStreamUTF16Buffer char_stream_buffer_;
TwoByteStringUTF16Buffer two_byte_string_buffer_;
// Source.
UTF16Buffer source_;
UTF16Buffer* source_;
int position_;
// Buffer to hold literal values (identifiers, strings, numbers)
@ -219,8 +251,11 @@ class Scanner {
void TerminateLiteral();
// Low-level scanning support.
void Advance();
void PushBack(uc32 ch);
void Advance() { c0_ = source_->Advance(); }
void PushBack(uc32 ch) {
source_->PushBack(ch);
c0_ = ch;
}
bool SkipWhiteSpace();
Token::Value SkipSingleLineComment();
@ -243,7 +278,7 @@ class Scanner {
// Return the current source position.
int source_pos() {
return source_.pos() - kCharacterLookaheadBufferSize + position_;
return source_->pos() - kCharacterLookaheadBufferSize + position_;
}
// Decodes a unicode escape-sequence which is part of an identifier.

23
deps/v8/src/scopes.cc

@ -108,14 +108,31 @@ Variable* VariableMap::Lookup(Handle<String> name) {
// Dummy constructor
Scope::Scope()
: inner_scopes_(0),
Scope::Scope(Type type)
: outer_scope_(NULL),
inner_scopes_(0),
type_(type),
scope_name_(Factory::empty_symbol()),
variables_(false),
temps_(0),
params_(0),
dynamics_(NULL),
unresolved_(0),
decls_(0) {
decls_(0),
receiver_(NULL),
function_(NULL),
arguments_(NULL),
arguments_shadow_(NULL),
illegal_redecl_(NULL),
scope_inside_with_(false),
scope_contains_with_(false),
scope_calls_eval_(false),
outer_scope_calls_eval_(false),
inner_scope_calls_eval_(false),
outer_scope_is_eval_scope_(false),
force_eager_compilation_(false),
num_stack_slots_(0),
num_heap_slots_(0) {
}

7
deps/v8/src/scopes.h

@ -93,7 +93,6 @@ class Scope: public ZoneObject {
GLOBAL_SCOPE // the top-level scope for a program or a top-level eval
};
Scope();
Scope(Scope* outer_scope, Type type);
virtual ~Scope() { }
@ -130,7 +129,7 @@ class Scope: public ZoneObject {
Variable* DeclareGlobal(Handle<String> name);
// Add a parameter to the parameter list. The parameter must have been
// declared via Declare. The same parameter may occur more then once in
// declared via Declare. The same parameter may occur more than once in
// the parameter list; they must be added in source order, from left to
// right.
void AddParameter(Variable* var);
@ -286,6 +285,8 @@ class Scope: public ZoneObject {
protected:
friend class ParserFactory;
explicit Scope(Type type);
// Scope tree.
Scope* outer_scope_; // the immediately enclosing outer scope, or NULL
ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes
@ -375,7 +376,7 @@ class Scope: public ZoneObject {
class DummyScope : public Scope {
public:
DummyScope() {
DummyScope() : Scope(GLOBAL_SCOPE) {
outer_scope_ = this;
}

73
deps/v8/src/spaces.cc

@ -726,47 +726,25 @@ void PagedSpace::Shrink() {
Page* top_page = AllocationTopPage();
ASSERT(top_page->is_valid());
// Loop over the pages from the top page to the end of the space to count
// the number of pages to keep and find the last page to keep.
int free_pages = 0;
int pages_to_keep = 0; // Of the free pages.
Page* last_page_to_keep = top_page;
Page* current_page = top_page->next_page();
// Loop over the pages to the end of the space.
while (current_page->is_valid()) {
#if defined(ANDROID)
// Free all chunks if possible
#else
// Advance last_page_to_keep every other step to end up at the midpoint.
if ((free_pages & 0x1) == 1) {
pages_to_keep++;
last_page_to_keep = last_page_to_keep->next_page();
}
#endif
free_pages++;
current_page = current_page->next_page();
// Count the number of pages we would like to free.
int pages_to_free = 0;
for (Page* p = top_page->next_page(); p->is_valid(); p = p->next_page()) {
pages_to_free++;
}
// Free pages after last_page_to_keep, and adjust the next_page link.
Page* p = MemoryAllocator::FreePages(last_page_to_keep->next_page());
MemoryAllocator::SetNextPage(last_page_to_keep, p);
// Free pages after top_page.
Page* p = MemoryAllocator::FreePages(top_page->next_page());
MemoryAllocator::SetNextPage(top_page, p);
// Since pages are only freed in whole chunks, we may have kept more
// than pages_to_keep. Count the extra pages and cache the new last
// page in the space.
last_page_ = last_page_to_keep;
while (p->is_valid()) {
pages_to_keep++;
// Find out how many pages we failed to free and update last_page_.
// Please note pages can only be freed in whole chunks.
last_page_ = top_page;
for (Page* p = top_page->next_page(); p->is_valid(); p = p->next_page()) {
pages_to_free--;
last_page_ = p;
p = p->next_page();
}
// The difference between free_pages and pages_to_keep is the number of
// pages actually freed.
ASSERT(pages_to_keep <= free_pages);
int bytes_freed = (free_pages - pages_to_keep) * Page::kObjectAreaSize;
accounting_stats_.ShrinkSpace(bytes_freed);
accounting_stats_.ShrinkSpace(pages_to_free * Page::kObjectAreaSize);
ASSERT(Capacity() == CountTotalPages() * Page::kObjectAreaSize);
}
@ -884,8 +862,6 @@ bool NewSpace::Setup(Address start, int size) {
ASSERT(initial_semispace_capacity <= maximum_semispace_capacity);
ASSERT(IsPowerOf2(maximum_semispace_capacity));
maximum_capacity_ = maximum_semispace_capacity;
capacity_ = initial_semispace_capacity;
// Allocate and setup the histogram arrays if necessary.
#if defined(DEBUG) || defined(ENABLE_LOGGING_AND_PROFILING)
@ -898,15 +874,17 @@ bool NewSpace::Setup(Address start, int size) {
#undef SET_NAME
#endif
ASSERT(size == 2 * maximum_capacity_);
ASSERT(size == 2 * maximum_semispace_capacity);
ASSERT(IsAddressAligned(start, size, 0));
if (!to_space_.Setup(start, capacity_, maximum_capacity_)) {
if (!to_space_.Setup(start,
initial_semispace_capacity,
maximum_semispace_capacity)) {
return false;
}
if (!from_space_.Setup(start + maximum_capacity_,
capacity_,
maximum_capacity_)) {
if (!from_space_.Setup(start + maximum_semispace_capacity,
initial_semispace_capacity,
maximum_semispace_capacity)) {
return false;
}
@ -938,7 +916,6 @@ void NewSpace::TearDown() {
#endif
start_ = NULL;
capacity_ = 0;
allocation_info_.top = NULL;
allocation_info_.limit = NULL;
mc_forwarding_info_.top = NULL;
@ -975,12 +952,11 @@ void NewSpace::Flip() {
bool NewSpace::Grow() {
ASSERT(capacity_ < maximum_capacity_);
ASSERT(Capacity() < MaximumCapacity());
// TODO(1240712): Failure to double the from space can result in
// semispaces of different sizes. In the event of that failure, the
// to space doubling should be rolled back before returning false.
if (!to_space_.Grow() || !from_space_.Grow()) return false;
capacity_ = to_space_.Capacity() + from_space_.Capacity();
allocation_info_.limit = to_space_.high();
ASSERT_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_);
return true;
@ -1104,10 +1080,9 @@ void SemiSpace::TearDown() {
bool SemiSpace::Grow() {
// Commit 50% extra space but only up to maximum capacity.
int extra = RoundUp(capacity_ / 2, OS::AllocateAlignment());
if (capacity_ + extra > maximum_capacity_) {
extra = maximum_capacity_ - capacity_;
}
int maximum_extra = maximum_capacity_ - capacity_;
int extra = Min(RoundUp(capacity_ / 2, OS::AllocateAlignment()),
maximum_extra);
if (!MemoryAllocator::CommitBlock(high(), extra, executable())) {
return false;
}

20
deps/v8/src/spaces.h

@ -1054,6 +1054,10 @@ class SemiSpace : public Space {
// Returns the current capacity of the semi space.
int Capacity() { return capacity_; }
// Returns the maximum capacity of the semi space.
int MaximumCapacity() { return maximum_capacity_; }
private:
// The current and maximum capacity of the space.
int capacity_;
@ -1164,12 +1168,18 @@ class NewSpace : public Space {
// Return the allocated bytes in the active semispace.
virtual int Size() { return top() - bottom(); }
// Return the current capacity of a semispace.
int Capacity() { return capacity_; }
int Capacity() {
ASSERT(to_space_.Capacity() == from_space_.Capacity());
return to_space_.Capacity();
}
// Return the available bytes without growing in the active semispace.
int Available() { return Capacity() - Size(); }
// Return the maximum capacity of a semispace.
int MaximumCapacity() { return maximum_capacity_; }
int MaximumCapacity() {
ASSERT(to_space_.MaximumCapacity() == from_space_.MaximumCapacity());
return to_space_.MaximumCapacity();
}
// Return the address of the allocation pointer in the active semispace.
Address top() { return allocation_info_.top; }
@ -1275,10 +1285,6 @@ class NewSpace : public Space {
}
private:
// The current and maximum capacities of a semispace.
int capacity_;
int maximum_capacity_;
// The semispaces.
SemiSpace to_space_;
SemiSpace from_space_;
@ -1574,7 +1580,7 @@ class FixedSpace : public PagedSpace {
// Give a fixed sized block of memory to the space's free list.
void Free(Address start) {
free_list_.Free(start);
accounting_stats_.DeallocateBytes(Map::kSize);
accounting_stats_.DeallocateBytes(object_size_in_bytes_);
}
// Prepares for a mark-compact GC.

2
deps/v8/src/v8-counters.h

@ -139,6 +139,8 @@ namespace internal {
SC(named_store_global_inline_miss, V8.NamedStoreGlobalInlineMiss) \
SC(call_global_inline, V8.CallGlobalInline) \
SC(call_global_inline_miss, V8.CallGlobalInlineMiss) \
SC(constructed_objects, V8.ConstructedObjects) \
SC(constructed_objects_runtime, V8.ConstructedObjectsRuntime) \
SC(for_in, V8.ForIn) \
SC(enum_cache_hits, V8.EnumCacheHits) \
SC(enum_cache_misses, V8.EnumCacheMisses) \

7
deps/v8/src/v8natives.js

@ -46,12 +46,16 @@ const $isFinite = GlobalIsFinite;
// Helper function used to install functions on objects.
function InstallFunctions(object, attributes, functions) {
if (functions.length >= 8) {
%OptimizeObjectForAddingMultipleProperties(object, functions.length >> 1);
}
for (var i = 0; i < functions.length; i += 2) {
var key = functions[i];
var f = functions[i + 1];
%FunctionSetName(f, key);
%SetProperty(object, key, f, attributes);
}
%TransformToFastProperties(object);
}
// Emulates JSC by installing functions on a hidden prototype that
@ -453,9 +457,11 @@ function NumberToJSON(key) {
// ----------------------------------------------------------------------------
function SetupNumber() {
%OptimizeObjectForAddingMultipleProperties($Number.prototype, 8);
// Setup the constructor property on the Number prototype object.
%SetProperty($Number.prototype, "constructor", $Number, DONT_ENUM);
%OptimizeObjectForAddingMultipleProperties($Number, 5);
// ECMA-262 section 15.7.3.1.
%SetProperty($Number,
"MAX_VALUE",
@ -479,6 +485,7 @@ function SetupNumber() {
"POSITIVE_INFINITY",
1/0,
DONT_ENUM | DONT_DELETE | READ_ONLY);
%TransformToFastProperties($Number);
// Setup non-enumerable functions on the Number prototype object.
InstallFunctions($Number.prototype, DONT_ENUM, $Array(

2
deps/v8/src/version.cc

@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 1
#define MINOR_VERSION 3
#define BUILD_NUMBER 4
#define BUILD_NUMBER 5
#define PATCH_LEVEL 0
#define CANDIDATE_VERSION false

24
deps/v8/src/x64/assembler-x64-inl.h

@ -228,43 +228,47 @@ void RelocInfo::set_target_object(Object* target) {
bool RelocInfo::IsCallInstruction() {
UNIMPLEMENTED(); // IA32 code below.
return *pc_ == 0xE8;
// The recognized call sequence is:
// movq(kScratchRegister, immediate64); call(kScratchRegister);
// It only needs to be distinguished from a return sequence
// movq(rsp, rbp); pop(rbp); ret(n); int3 *6
// The 11th byte is int3 (0xCC) in the return sequence and
// REX.WB (0x48+register bit) for the call sequence.
return pc_[10] != 0xCC;
}
Address RelocInfo::call_address() {
UNIMPLEMENTED(); // IA32 code below.
ASSERT(IsCallInstruction());
return Assembler::target_address_at(pc_ + 1);
return Assembler::target_address_at(
pc_ + Assembler::kPatchReturnSequenceAddressOffset);
}
void RelocInfo::set_call_address(Address target) {
UNIMPLEMENTED(); // IA32 code below.
ASSERT(IsCallInstruction());
Assembler::set_target_address_at(pc_ + 1, target);
Assembler::set_target_address_at(
pc_ + Assembler::kPatchReturnSequenceAddressOffset,
target);
}
Object* RelocInfo::call_object() {
UNIMPLEMENTED(); // IA32 code below.
ASSERT(IsCallInstruction());
return *call_object_address();
}
void RelocInfo::set_call_object(Object* target) {
UNIMPLEMENTED(); // IA32 code below.
ASSERT(IsCallInstruction());
*call_object_address() = target;
}
Object** RelocInfo::call_object_address() {
UNIMPLEMENTED(); // IA32 code below.
ASSERT(IsCallInstruction());
return reinterpret_cast<Object**>(pc_ + 1);
return reinterpret_cast<Object**>(
pc_ + Assembler::kPatchReturnSequenceAddressOffset);
}
// -----------------------------------------------------------------------------

136
deps/v8/src/x64/assembler-x64.cc

@ -178,6 +178,13 @@ void RelocInfo::PatchCodeWithCall(Address target, int guard_bytes) {
}
void RelocInfo::PatchCode(byte* instructions, int instruction_count) {
// Patch the code at the current address with the supplied instructions.
for (int i = 0; i < instruction_count; i++) {
*(pc_ + i) = *(instructions + i);
}
}
// -----------------------------------------------------------------------------
// Implementation of Operand
@ -437,21 +444,43 @@ void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) {
}
void Assembler::arithmetic_op(byte opcode, Register dst, Register src) {
void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(dst, src);
emit_rex_64(reg, rm_reg);
emit(opcode);
emit_modrm(dst, src);
emit_modrm(reg, rm_reg);
}
void Assembler::arithmetic_op_32(byte opcode, Register dst, Register src) {
void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_optional_rex_32(dst, src);
emit(0x66);
emit_optional_rex_32(reg, rm_reg);
emit(opcode);
emit_modrm(dst, src);
emit_modrm(reg, rm_reg);
}
void Assembler::arithmetic_op_16(byte opcode,
Register reg,
const Operand& rm_reg) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0x66);
emit_optional_rex_32(reg, rm_reg);
emit(opcode);
emit_operand(reg, rm_reg);
}
void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_optional_rex_32(reg, rm_reg);
emit(opcode);
emit_modrm(reg, rm_reg);
}
@ -504,6 +533,47 @@ void Assembler::immediate_arithmetic_op(byte subcode,
}
void Assembler::immediate_arithmetic_op_16(byte subcode,
Register dst,
Immediate src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0x66); // Operand size override prefix.
emit_optional_rex_32(dst);
if (is_int8(src.value_)) {
emit(0x83);
emit_modrm(subcode, dst);
emit(src.value_);
} else if (dst.is(rax)) {
emit(0x05 | (subcode << 3));
emitl(src.value_);
} else {
emit(0x81);
emit_modrm(subcode, dst);
emitl(src.value_);
}
}
void Assembler::immediate_arithmetic_op_16(byte subcode,
const Operand& dst,
Immediate src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0x66); // Operand size override prefix.
emit_optional_rex_32(dst);
if (is_int8(src.value_)) {
emit(0x83);
emit_operand(subcode, dst);
emit(src.value_);
} else {
emit(0x81);
emit_operand(subcode, dst);
emitl(src.value_);
}
}
void Assembler::immediate_arithmetic_op_32(byte subcode,
Register dst,
Immediate src) {
@ -744,6 +814,14 @@ void Assembler::cmovl(Condition cc, Register dst, const Operand& src) {
}
void Assembler::cmpb_al(Immediate imm8) {
ASSERT(is_int8(imm8.value_) || is_uint8(imm8.value_));
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0x3c);
emit(imm8.value_);
}
void Assembler::cpuid() {
ASSERT(CpuFeatures::IsEnabled(CpuFeatures::CPUID));
@ -1000,6 +1078,16 @@ void Assembler::jmp(Register target) {
}
void Assembler::jmp(const Operand& src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
// Opcode FF/4 m64
emit_optional_rex_32(src);
emit(0xFF);
emit_operand(0x4, src);
}
void Assembler::lea(Register dst, const Operand& src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
@ -1193,6 +1281,32 @@ void Assembler::movq(const Operand& dst, Immediate value) {
}
/*
* Loads the ip-relative location of the src label into the target
* location (as a 32-bit offset sign extended to 64-bit).
*/
void Assembler::movl(const Operand& dst, Label* src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_optional_rex_32(dst);
emit(0xC7);
emit_operand(0, dst);
if (src->is_bound()) {
int offset = src->pos() - pc_offset() - sizeof(int32_t);
ASSERT(offset <= 0);
emitl(offset);
} else if (src->is_linked()) {
emitl(src->pos());
src->link_to(pc_offset() - sizeof(int32_t));
} else {
ASSERT(src->is_unused());
int32_t current = pc_offset();
emitl(current);
src->link_to(current);
}
}
void Assembler::movq(Register dst, Handle<Object> value, RelocInfo::Mode mode) {
// If there is no relocation info, emit the value of the handle efficiently
// (possibly using less that 8 bytes for the value).
@ -1608,6 +1722,11 @@ void Assembler::testl(Register dst, Register src) {
void Assembler::testl(Register reg, Immediate mask) {
// testl with a mask that fits in the low byte is exactly testb.
if (is_uint8(mask.value_)) {
testb(reg, mask);
return;
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
if (reg.is(rax)) {
@ -1623,6 +1742,11 @@ void Assembler::testl(Register reg, Immediate mask) {
void Assembler::testl(const Operand& op, Immediate mask) {
// testl with a mask that fits in the low byte is exactly testb.
if (is_uint8(mask.value_)) {
testb(op, mask);
return;
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_optional_rex_32(rax, op);

96
deps/v8/src/x64/assembler-x64.h

@ -442,8 +442,10 @@ class Assembler : public Malloced {
// Distance between the address of the code target in the call instruction
// and the return address. Checked in the debug build.
static const int kTargetAddrToReturnAddrDist = 3 + kPointerSize;
static const int kPatchReturnSequenceLength = 3 + kPointerSize;
// Distance between start of patched return sequence and the emitted address
// to jump to (movq = REX.W 0xB8+r.).
static const int kPatchReturnSequenceAddressOffset = 2;
// ---------------------------------------------------------------------------
// Code generation
@ -496,13 +498,17 @@ class Assembler : public Malloced {
// Load a 32-bit immediate value, zero-extended to 64 bits.
void movl(Register dst, Immediate imm32);
// Move 64 bit register value to 64-bit memory location.
void movq(const Operand& dst, Register src);
// Move 64 bit memory location to 64-bit register value.
void movq(Register dst, const Operand& src);
void movq(Register dst, Register src);
// Sign extends immediate 32-bit value to 64 bits.
void movq(Register dst, Immediate x);
void movq(Register dst, Register src);
// Move the offset of the label location relative to the current
// position (after the move) to the destination.
void movl(const Operand& dst, Label* src);
// Move 64 bit register value to 64-bit memory location.
void movq(const Operand& dst, Register src);
// Move sign extended immediate to memory location.
void movq(const Operand& dst, Immediate value);
// New x64 instructions to load a 64-bit immediate into a register.
@ -535,7 +541,11 @@ class Assembler : public Malloced {
// Arithmetics
void addl(Register dst, Register src) {
arithmetic_op_32(0x03, dst, src);
if (dst.low_bits() == 4) { // Forces SIB byte.
arithmetic_op_32(0x01, src, dst);
} else {
arithmetic_op_32(0x03, dst, src);
}
}
void addl(Register dst, Immediate src) {
@ -574,10 +584,44 @@ class Assembler : public Malloced {
immediate_arithmetic_op_8(0x7, dst, src);
}
void cmpb_al(Immediate src);
void cmpb(Register dst, Register src) {
arithmetic_op(0x3A, dst, src);
}
void cmpb(Register dst, const Operand& src) {
arithmetic_op(0x3A, dst, src);
}
void cmpb(const Operand& dst, Register src) {
arithmetic_op(0x38, src, dst);
}
void cmpb(const Operand& dst, Immediate src) {
immediate_arithmetic_op_8(0x7, dst, src);
}
void cmpw(const Operand& dst, Immediate src) {
immediate_arithmetic_op_16(0x7, dst, src);
}
void cmpw(Register dst, Immediate src) {
immediate_arithmetic_op_16(0x7, dst, src);
}
void cmpw(Register dst, const Operand& src) {
arithmetic_op_16(0x3B, dst, src);
}
void cmpw(Register dst, Register src) {
arithmetic_op_16(0x3B, dst, src);
}
void cmpw(const Operand& dst, Register src) {
arithmetic_op_16(0x39, src, dst);
}
void cmpl(Register dst, Register src) {
arithmetic_op_32(0x3B, dst, src);
}
@ -794,6 +838,10 @@ class Assembler : public Malloced {
immediate_arithmetic_op_32(0x5, dst, src);
}
void subb(Register dst, Immediate src) {
immediate_arithmetic_op_8(0x5, dst, src);
}
void testb(Register reg, Immediate mask);
void testb(const Operand& op, Immediate mask);
void testl(Register dst, Register src);
@ -871,6 +919,9 @@ class Assembler : public Malloced {
// Jump near absolute indirect (r64)
void jmp(Register adr);
// Jump near absolute indirect (m64)
void jmp(const Operand& src);
// Conditional jumps
void j(Condition cc, Label* L);
@ -1141,26 +1192,36 @@ class Assembler : public Malloced {
// AND, OR, XOR, or CMP. The encodings of these operations are all
// similar, differing just in the opcode or in the reg field of the
// ModR/M byte.
void arithmetic_op(byte opcode, Register dst, Register src);
void arithmetic_op_32(byte opcode, Register dst, Register src);
void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
void arithmetic_op(byte opcode, Register reg, Register rm_reg);
void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
// Operate on a 32-bit word in memory or register.
void immediate_arithmetic_op_32(byte subcode,
const Operand& dst,
Immediate src);
void immediate_arithmetic_op_32(byte subcode,
Register dst,
Immediate src);
// Operate on a byte in memory or register.
void immediate_arithmetic_op_8(byte subcode,
const Operand& dst,
Register dst,
Immediate src);
void immediate_arithmetic_op_8(byte subcode,
Register dst,
const Operand& dst,
Immediate src);
// Operate on a word in memory or register.
void immediate_arithmetic_op_16(byte subcode,
Register dst,
Immediate src);
void immediate_arithmetic_op_16(byte subcode,
const Operand& dst,
Immediate src);
// Operate on a 32-bit word in memory or register.
void immediate_arithmetic_op_32(byte subcode,
Register dst,
Immediate src);
void immediate_arithmetic_op_32(byte subcode,
const Operand& dst,
Immediate src);
// Emit machine code for a shift operation.
void shift(Register dst, Immediate shift_amount, int subcode);
void shift_32(Register dst, Immediate shift_amount, int subcode);
@ -1180,6 +1241,7 @@ class Assembler : public Malloced {
friend class CodePatcher;
friend class EnsureSpace;
friend class RegExpMacroAssemblerX64;
// Code buffer:
// The buffer into which code and relocation info are generated.

22
deps/v8/src/x64/builtins-x64.cc

@ -35,7 +35,7 @@ namespace internal {
#define __ ACCESS_MASM(masm)
void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
// TODO(1238487): Don't pass the function in a static variable.
// TODO(428): Don't pass the function in a static variable.
ExternalReference passed = ExternalReference::builtin_passed_function();
__ movq(kScratchRegister, passed.address(), RelocInfo::EXTERNAL_REFERENCE);
__ movq(Operand(kScratchRegister, 0), rdi);
@ -505,7 +505,14 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
Label rt_call, allocated;
if (FLAG_inline_new) {
Label undo_allocation;
// TODO(X64): Enable debugger support, using debug_step_in_fp.
#ifdef ENABLE_DEBUGGER_SUPPORT
ExternalReference debug_step_in_fp =
ExternalReference::debug_step_in_fp_address();
__ movq(kScratchRegister, debug_step_in_fp);
__ cmpq(Operand(kScratchRegister, 0), Immediate(0));
__ j(not_equal, &rt_call);
#endif
// Verified that the constructor is a JSFunction.
// Load the initial map and verify that it is in fact a map.
@ -585,12 +592,16 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// rax: initial map
// rbx: JSObject
// rdi: start of next object
// Calculate total properties described map.
__ movzxbq(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
__ movzxbq(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset));
__ movzxbq(rcx, FieldOperand(rax, Map::kPreAllocatedPropertyFieldsOffset));
__ addq(rdx, rcx);
// Calculate unused properties past the end of the in-object properties.
__ movzxbq(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset));
__ subq(rdx, rcx);
// Done if no extra properties are to be allocated.
__ j(zero, &allocated);
__ Assert(positive, "Property allocation count failed.");
// Scale the number of elements by pointer size and add the header for
// FixedArrays to the start of the next object calculation from above.
@ -726,6 +737,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ pop(rcx);
__ lea(rsp, Operand(rsp, rbx, times_4, 1 * kPointerSize)); // 1 ~ receiver
__ push(rcx);
__ IncrementCounter(&Counters::constructed_objects, 1);
__ ret(0);
}
@ -823,10 +835,8 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
// Invoke the code.
if (is_construct) {
// Expects rdi to hold function pointer.
__ movq(kScratchRegister,
Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
__ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
RelocInfo::CODE_TARGET);
__ call(kScratchRegister);
} else {
ParameterCount actual(rax);
// Function must be in rdi.

4
deps/v8/src/x64/cfg-x64.cc

@ -114,8 +114,8 @@ void ExitNode::Compile(MacroAssembler* masm) {
int count = CfgGlobals::current()->fun()->scope()->num_parameters();
__ ret((count + 1) * kPointerSize);
// Add padding that will be overwritten by a debugger breakpoint.
// "movq rsp, rbp; pop rbp" has length 5. "ret k" has length 2.
const int kPadding = Debug::kX64JSReturnSequenceLength - 5 - 2;
// "movq rsp, rbp; pop rbp" has length 4. "ret k" has length 3.
const int kPadding = Debug::kX64JSReturnSequenceLength - 4 - 3;
for (int i = 0; i < kPadding; ++i) {
__ int3();
}

44
deps/v8/src/x64/codegen-x64.cc

@ -500,17 +500,19 @@ void CodeGenerator::GenerateReturnSequence(Result* return_value) {
return_value->ToRegister(rax);
// Add a label for checking the size of the code used for returning.
#ifdef DEBUG
Label check_exit_codesize;
masm_->bind(&check_exit_codesize);
#endif
// Leave the frame and return popping the arguments and the
// receiver.
frame_->Exit();
masm_->ret((scope_->num_parameters() + 1) * kPointerSize);
// Add padding that will be overwritten by a debugger breakpoint.
// frame_->Exit() generates "movq rsp, rbp; pop rbp" length 5.
// "ret k" has length 2.
const int kPadding = Debug::kX64JSReturnSequenceLength - 5 - 2;
// frame_->Exit() generates "movq rsp, rbp; pop rbp; ret k"
// with length 7 (3 + 1 + 3).
const int kPadding = Debug::kX64JSReturnSequenceLength - 7;
for (int i = 0; i < kPadding; ++i) {
masm_->int3();
}
@ -3084,26 +3086,19 @@ void CodeGenerator::VisitCountOperation(CountOperation* node) {
is_increment);
}
Result tmp = allocator_->AllocateWithoutSpilling();
ASSERT(kSmiTagMask == 1 && kSmiTag == 0);
__ movl(tmp.reg(), Immediate(kSmiTagMask));
// Smi test.
__ movq(kScratchRegister, new_value.reg());
if (is_increment) {
__ addl(kScratchRegister, Immediate(Smi::FromInt(1)));
} else {
__ subl(kScratchRegister, Immediate(Smi::FromInt(1)));
}
// deferred->Branch(overflow);
__ cmovl(overflow, kScratchRegister, tmp.reg());
__ testl(kScratchRegister, tmp.reg());
tmp.Unuse();
// Smi test.
deferred->Branch(overflow);
__ testl(kScratchRegister, Immediate(kSmiTagMask));
deferred->Branch(not_zero);
__ movq(new_value.reg(), kScratchRegister);
deferred->BindExit();
// Postfix: store the old value in the allocated slot under the
// reference.
if (is_postfix) frame_->SetElementAt(target.size(), &old_value);
@ -5738,6 +5733,13 @@ void Reference::GetValue(TypeofState typeof_state) {
ASSERT(cgen_->HasValidEntryRegisters());
ASSERT(!is_illegal());
MacroAssembler* masm = cgen_->masm();
// Record the source position for the property load.
Property* property = expression_->AsProperty();
if (property != NULL) {
cgen_->CodeForSourcePosition(property->position());
}
switch (type_) {
case SLOT: {
Comment cmnt(masm, "[ Load from Slot");
@ -6957,17 +6959,12 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
Label throw_out_of_memory_exception;
Label throw_normal_exception;
// Call into the runtime system. Collect garbage before the call if
// running with --gc-greedy set.
if (FLAG_gc_greedy) {
Failure* failure = Failure::RetryAfterGC(0);
__ movq(rax, failure, RelocInfo::NONE);
}
// Call into the runtime system.
GenerateCore(masm,
&throw_normal_exception,
&throw_out_of_memory_exception,
frame_type,
FLAG_gc_greedy,
false,
false);
// Do space-specific GC and retry runtime call.
@ -7536,11 +7533,10 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// Reserve space for converted numbers.
__ subq(rsp, Immediate(2 * kPointerSize));
bool use_sse3 = CpuFeatures::IsSupported(CpuFeatures::SSE3);
if (use_sse3) {
if (use_sse3_) {
// Truncate the operands to 32-bit integers and check for
// exceptions in doing so.
CpuFeatures::Scope scope(CpuFeatures::SSE3);
CpuFeatures::Scope scope(CpuFeatures::SSE3);
__ fisttp_s(Operand(rsp, 0 * kPointerSize));
__ fisttp_s(Operand(rsp, 1 * kPointerSize));
__ fnstsw_ax();
@ -7625,7 +7621,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
// the runtime system.
__ bind(&operand_conversion_failure);
__ addq(rsp, Immediate(2 * kPointerSize));
if (use_sse3) {
if (use_sse3_) {
// If we've used the SSE3 instructions for truncating the
// floating point values to integers and it failed, we have a
// pending #IA exception. Clear it.

21
deps/v8/src/x64/codegen-x64.h

@ -299,14 +299,9 @@ class CodeGenerator: public AstVisitor {
#endif
static void SetFunctionInfo(Handle<JSFunction> fun,
int length,
int function_token_position,
int start_position,
int end_position,
bool is_expression,
FunctionLiteral* lit,
bool is_toplevel,
Handle<Script> script,
Handle<String> inferred_name);
Handle<Script> script);
// Accessors
MacroAssembler* masm() { return masm_; }
@ -624,6 +619,7 @@ class GenericBinaryOpStub: public CodeStub {
OverwriteMode mode,
GenericBinaryFlags flags)
: op_(op), mode_(mode), flags_(flags) {
use_sse3_ = CpuFeatures::IsSupported(CpuFeatures::SSE3);
ASSERT(OpBits::is_valid(Token::NUM_TOKENS));
}
@ -633,6 +629,7 @@ class GenericBinaryOpStub: public CodeStub {
Token::Value op_;
OverwriteMode mode_;
GenericBinaryFlags flags_;
bool use_sse3_;
const char* GetName();
@ -645,17 +642,19 @@ class GenericBinaryOpStub: public CodeStub {
}
#endif
// Minor key encoding in 16 bits FOOOOOOOOOOOOOMM.
// Minor key encoding in 16 bits FSOOOOOOOOOOOOMM.
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
class OpBits: public BitField<Token::Value, 2, 13> {};
class OpBits: public BitField<Token::Value, 2, 12> {};
class SSE3Bits: public BitField<bool, 14, 1> {};
class FlagBits: public BitField<GenericBinaryFlags, 15, 1> {};
Major MajorKey() { return GenericBinaryOp; }
int MinorKey() {
// Encode the parameters in a unique 16 bit value.
return OpBits::encode(op_)
| ModeBits::encode(mode_)
| FlagBits::encode(flags_);
| ModeBits::encode(mode_)
| FlagBits::encode(flags_)
| SSE3Bits::encode(use_sse3_);
}
void Generate(MacroAssembler* masm);
};

150
deps/v8/src/x64/debug-x64.cc

@ -39,60 +39,176 @@ namespace internal {
bool Debug::IsDebugBreakAtReturn(v8::internal::RelocInfo* rinfo) {
ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()));
// 11th byte of patch is 0x49, 11th byte of JS return is 0xCC (int3).
// 11th byte of patch is 0x49 (REX.WB byte of computed jump/call to r10),
// 11th byte of JS return is 0xCC (int3).
ASSERT(*(rinfo->pc() + 10) == 0x49 || *(rinfo->pc() + 10) == 0xCC);
return (*(rinfo->pc() + 10) == 0x49);
return (*(rinfo->pc() + 10) != 0xCC);
}
#define __ ACCESS_MASM(masm)
static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
RegList pointer_regs,
bool convert_call_to_jmp) {
// Save the content of all general purpose registers in memory. This copy in
// memory is later pushed onto the JS expression stack for the fake JS frame
// generated and also to the C frame generated on top of that. In the JS
// frame ONLY the registers containing pointers will be pushed on the
// expression stack. This causes the GC to update these pointers so that
// they will have the correct value when returning from the debugger.
__ SaveRegistersToMemory(kJSCallerSaved);
// Enter an internal frame.
__ EnterInternalFrame();
// Store the registers containing object pointers on the expression stack to
// make sure that these are correctly updated during GC.
__ PushRegistersFromMemory(pointer_regs);
#ifdef DEBUG
__ RecordComment("// Calling from debug break to runtime - come in - over");
#endif
__ xor_(rax, rax); // No arguments (argc == 0).
__ movq(rbx, ExternalReference::debug_break());
CEntryDebugBreakStub ceb;
__ CallStub(&ceb);
// Restore the register values containing object pointers from the expression
// stack in the reverse order as they where pushed.
__ PopRegistersToMemory(pointer_regs);
// Get rid of the internal frame.
__ LeaveInternalFrame();
// If this call did not replace a call but patched other code then there will
// be an unwanted return address left on the stack. Here we get rid of that.
if (convert_call_to_jmp) {
__ pop(rax);
}
// Finally restore all registers.
__ RestoreRegistersFromMemory(kJSCallerSaved);
// Now that the break point has been handled, resume normal execution by
// jumping to the target address intended by the caller and that was
// overwritten by the address of DebugBreakXXX.
ExternalReference after_break_target =
ExternalReference(Debug_Address::AfterBreakTarget());
__ movq(kScratchRegister, after_break_target);
__ jmp(Operand(kScratchRegister, 0));
}
void Debug::GenerateCallICDebugBreak(MacroAssembler* masm) {
masm->int3(); // UNIMPLEMENTED
// Register state for keyed IC call call (from ic-x64.cc)
// ----------- S t a t e -------------
// -- rax: number of arguments
// -----------------------------------
// The number of arguments in rax is not smi encoded.
Generate_DebugBreakCallHelper(masm, 0, false);
}
void Debug::GenerateConstructCallDebugBreak(MacroAssembler* masm) {
masm->int3(); // UNIMPLEMENTED
// Register state just before return from JS function (from codegen-x64.cc).
// rax is the actual number of arguments not encoded as a smi, see comment
// above IC call.
// ----------- S t a t e -------------
// -- rax: number of arguments
// -----------------------------------
// The number of arguments in rax is not smi encoded.
Generate_DebugBreakCallHelper(masm, 0, false);
}
void Debug::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
masm->int3(); // UNIMPLEMENTED
// Register state for keyed IC load call (from ic-x64.cc).
// ----------- S t a t e -------------
// No registers used on entry.
// -----------------------------------
Generate_DebugBreakCallHelper(masm, 0, false);
}
void Debug::GenerateKeyedStoreICDebugBreak(MacroAssembler* masm) {
masm->int3(); // UNIMPLEMENTED
// Register state for keyed IC load call (from ic-x64.cc).
// ----------- S t a t e -------------
// -- rax : value
// -----------------------------------
// Register rax contains an object that needs to be pushed on the
// expression stack of the fake JS frame.
Generate_DebugBreakCallHelper(masm, rax.bit(), false);
}
void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
masm->int3(); // UNIMPLEMENTED
// Register state for IC load call (from ic-x64.cc).
// ----------- S t a t e -------------
// -- rcx : name
// -----------------------------------
Generate_DebugBreakCallHelper(masm, rcx.bit(), false);
}
void Debug::GenerateReturnDebugBreak(MacroAssembler* masm) {
masm->int3(); // UNIMPLEMENTED
// Register state just before return from JS function (from codegen-x64.cc).
// ----------- S t a t e -------------
// -- rax: return value
// -----------------------------------
Generate_DebugBreakCallHelper(masm, rax.bit(), true);
}
void Debug::GenerateReturnDebugBreakEntry(MacroAssembler* masm) {
masm->int3(); // UNIMPLEMENTED
// OK to clobber rbx as we are returning from a JS function through the code
// generated by CodeGenerator::GenerateReturnSequence()
ExternalReference debug_break_return =
ExternalReference(Debug_Address::DebugBreakReturn());
__ movq(rbx, debug_break_return);
__ movq(rbx, Operand(rbx, 0));
__ addq(rbx, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(rbx);
}
void Debug::GenerateStoreICDebugBreak(MacroAssembler* masm) {
masm->int3(); // UNIMPLEMENTED
// REgister state for IC store call (from ic-x64.cc).
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : name
// -----------------------------------
Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), false);
}
void Debug::GenerateStubNoRegistersDebugBreak(MacroAssembler* masm) {
masm->int3(); // UNIMPLEMENTED
// Register state for stub CallFunction (from CallFunctionStub in ic-x64.cc).
// ----------- S t a t e -------------
// No registers used on entry.
// -----------------------------------
Generate_DebugBreakCallHelper(masm, 0, false);
}
#undef __
void BreakLocationIterator::ClearDebugBreakAtReturn() {
// TODO(X64): Implement this when we start setting Debug breaks.
UNIMPLEMENTED();
rinfo()->PatchCode(original_rinfo()->pc(),
Debug::kX64JSReturnSequenceLength);
}
bool BreakLocationIterator::IsDebugBreakAtReturn() {
// TODO(X64): Implement this when we start setting Debug breaks.
UNIMPLEMENTED();
return false;
return Debug::IsDebugBreakAtReturn(rinfo());
}
void BreakLocationIterator::SetDebugBreakAtReturn() {
UNIMPLEMENTED();
ASSERT(Debug::kX64JSReturnSequenceLength >= Debug::kX64CallInstructionLength);
rinfo()->PatchCodeWithCall(Debug::debug_break_return_entry()->entry(),
Debug::kX64JSReturnSequenceLength - Debug::kX64CallInstructionLength);
}
#endif // ENABLE_DEBUGGER_SUPPORT

4
deps/v8/src/x64/ic-x64.cc

@ -167,7 +167,7 @@ static bool PatchInlinedMapCheck(Address address, Object* map) {
// Arguments are address of start of call sequence that called
// the IC,
Address test_instruction_address =
address + Assembler::kTargetAddrToReturnAddrDist;
address + Assembler::kPatchReturnSequenceLength;
// The keyed load has a fast inlined case if the IC call instruction
// is immediately followed by a test instruction.
if (*test_instruction_address != kTestEaxByte) return false;
@ -845,7 +845,7 @@ void LoadIC::GenerateStringLength(MacroAssembler* masm) {
bool LoadIC::PatchInlinedLoad(Address address, Object* map, int offset) {
// The address of the instruction following the call.
Address test_instruction_address =
address + Assembler::kTargetAddrToReturnAddrDist;
address + Assembler::kPatchReturnSequenceLength;
// If the instruction following the call is not a test eax, nothing
// was inlined.
if (*test_instruction_address != kTestEaxByte) return false;

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

@ -262,8 +262,7 @@ void MacroAssembler::Abort(const char* msg) {
void MacroAssembler::CallStub(CodeStub* stub) {
ASSERT(allow_stub_calls()); // calls are not allowed in some stubs
movq(kScratchRegister, stub->GetCode(), RelocInfo::CODE_TARGET);
call(kScratchRegister);
Call(stub->GetCode(), RelocInfo::CODE_TARGET);
}
@ -495,7 +494,6 @@ void MacroAssembler::Jump(Address destination, RelocInfo::Mode rmode) {
void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
WriteRecordedPositions();
ASSERT(RelocInfo::IsCodeTarget(rmode));
movq(kScratchRegister, code_object, rmode);
#ifdef DEBUG
@ -504,7 +502,7 @@ void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode) {
#endif
jmp(kScratchRegister);
#ifdef DEBUG
ASSERT_EQ(kTargetAddrToReturnAddrDist,
ASSERT_EQ(kPatchReturnSequenceLength,
SizeOfCodeGeneratedSince(&target) + kPointerSize);
#endif
}
@ -523,8 +521,8 @@ void MacroAssembler::Call(Address destination, RelocInfo::Mode rmode) {
void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
WriteRecordedPositions();
ASSERT(RelocInfo::IsCodeTarget(rmode));
WriteRecordedPositions();
movq(kScratchRegister, code_object, rmode);
#ifdef DEBUG
// Patch target is kPointer size bytes *before* target label.
@ -533,7 +531,7 @@ void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode) {
#endif
call(kScratchRegister);
#ifdef DEBUG
ASSERT_EQ(kTargetAddrToReturnAddrDist,
ASSERT_EQ(kPatchReturnSequenceLength,
SizeOfCodeGeneratedSince(&target) + kPointerSize);
#endif
}
@ -799,7 +797,7 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
Bootstrapper::FixupFlagsIsPCRelative::encode(false) |
Bootstrapper::FixupFlagsUseCodeObject::encode(false);
Unresolved entry =
{ pc_offset() - kTargetAddrToReturnAddrDist, flags, name };
{ pc_offset() - kPatchReturnSequenceLength, flags, name };
unresolved_.Add(entry);
}
}
@ -859,12 +857,11 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
movq(rdx, code_register);
}
movq(kScratchRegister, adaptor, RelocInfo::CODE_TARGET);
if (flag == CALL_FUNCTION) {
call(kScratchRegister);
Call(adaptor, RelocInfo::CODE_TARGET);
jmp(done);
} else {
jmp(kScratchRegister);
Jump(adaptor, RelocInfo::CODE_TARGET);
}
bind(&invoke);
}

1274
deps/v8/src/x64/regexp-macro-assembler-x64.cc

File diff suppressed because it is too large

268
deps/v8/src/x64/regexp-macro-assembler-x64.h

@ -25,3 +25,271 @@
// (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_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
#define V8_X64_REGEXP_MACRO_ASSEMBLER_X64_H_
namespace v8 {
namespace internal {
class RegExpMacroAssemblerX64: public NativeRegExpMacroAssembler {
public:
RegExpMacroAssemblerX64(Mode mode, int registers_to_save);
virtual ~RegExpMacroAssemblerX64();
virtual int stack_limit_slack();
virtual void AdvanceCurrentPosition(int by);
virtual void AdvanceRegister(int reg, int by);
virtual void Backtrack();
virtual void Bind(Label* label);
virtual void CheckAtStart(Label* on_at_start);
virtual void CheckCharacter(uint32_t c, Label* on_equal);
virtual void CheckCharacterAfterAnd(uint32_t c,
uint32_t mask,
Label* on_equal);
virtual void CheckCharacterGT(uc16 limit, Label* on_greater);
virtual void CheckCharacterLT(uc16 limit, Label* on_less);
virtual void CheckCharacters(Vector<const uc16> str,
int cp_offset,
Label* on_failure,
bool check_end_of_string);
// A "greedy loop" is a loop that is both greedy and with a simple
// body. It has a particularly simple implementation.
virtual void CheckGreedyLoop(Label* on_tos_equals_current_position);
virtual void CheckNotAtStart(Label* on_not_at_start);
virtual void CheckNotBackReference(int start_reg, Label* on_no_match);
virtual void CheckNotBackReferenceIgnoreCase(int start_reg,
Label* on_no_match);
virtual void CheckNotRegistersEqual(int reg1, int reg2, Label* on_not_equal);
virtual void CheckNotCharacter(uint32_t c, Label* on_not_equal);
virtual void CheckNotCharacterAfterAnd(uint32_t c,
uint32_t mask,
Label* on_not_equal);
virtual void CheckNotCharacterAfterMinusAnd(uc16 c,
uc16 minus,
uc16 mask,
Label* on_not_equal);
// Checks whether the given offset from the current position is before
// the end of the string.
virtual void CheckPosition(int cp_offset, Label* on_outside_input);
virtual bool CheckSpecialCharacterClass(uc16 type,
int cp_offset,
bool check_offset,
Label* on_no_match);
virtual void Fail();
virtual Handle<Object> GetCode(Handle<String> source);
virtual void GoTo(Label* label);
virtual void IfRegisterGE(int reg, int comparand, Label* if_ge);
virtual void IfRegisterLT(int reg, int comparand, Label* if_lt);
virtual void IfRegisterEqPos(int reg, Label* if_eq);
virtual IrregexpImplementation Implementation();
virtual void LoadCurrentCharacter(int cp_offset,
Label* on_end_of_input,
bool check_bounds = true,
int characters = 1);
virtual void PopCurrentPosition();
virtual void PopRegister(int register_index);
virtual void PushBacktrack(Label* label);
virtual void PushCurrentPosition();
virtual void PushRegister(int register_index,
StackCheckFlag check_stack_limit);
virtual void ReadCurrentPositionFromRegister(int reg);
virtual void ReadStackPointerFromRegister(int reg);
virtual void SetRegister(int register_index, int to);
virtual void Succeed();
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset);
virtual void ClearRegisters(int reg_from, int reg_to);
virtual void WriteStackPointerToRegister(int reg);
static Result Match(Handle<Code> regexp,
Handle<String> subject,
int* offsets_vector,
int offsets_vector_length,
int previous_index);
static Result Execute(Code* code,
String* input,
int start_offset,
const byte* input_start,
const byte* input_end,
int* output,
bool at_start);
private:
// Offsets from rbp of function parameters and stored registers.
static const int kFramePointer = 0;
// Above the frame pointer - function parameters and return address.
static const int kReturn_eip = kFramePointer + kPointerSize;
static const int kFrameAlign = kReturn_eip + kPointerSize;
#ifdef __MSVC__
// Parameters (first four passed as registers, but with room on stack).
// In Microsoft 64-bit Calling Convention, there is room on the callers
// stack (before the return address) to spill parameter registers. We
// use this space to store the register passed parameters.
static const int kInputString = kFrameAlign;
static const int kStartIndex = kInputString + kPointerSize;
static const int kInputStart = kStartIndex + kPointerSize;
static const int kInputEnd = kInputStart + kPointerSize;
static const int kRegisterOutput = kInputEnd + kPointerSize;
static const int kAtStart = kRegisterOutput + kPointerSize;
static const int kStackHighEnd = kAtStart + kPointerSize;
#else
// In AMD64 ABI Calling Convention, the first six integer parameters
// are passed as registers, and caller must allocate space on the stack
// if it wants them stored. We push the parameters after the frame pointer.
static const int kInputString = kFramePointer - kPointerSize;
static const int kStartIndex = kInputString - kPointerSize;
static const int kInputStart = kStartIndex - kPointerSize;
static const int kInputEnd = kInputStart - kPointerSize;
static const int kRegisterOutput = kInputEnd - kPointerSize;
static const int kAtStart = kRegisterOutput - kPointerSize;
static const int kStackHighEnd = kFrameAlign;
#endif
#ifdef __MSVC__
// Microsoft calling convention has three callee-saved registers
// (that we are using). We push these after the frame pointer.
static const int kBackup_rsi = kFramePointer - kPointerSize;
static const int kBackup_rdi = kBackup_rsi - kPointerSize;
static const int kBackup_rbx = kBackup_rdi - kPointerSize;
static const int kLastCalleeSaveRegister = kBackup_rbx;
#else
// AMD64 Calling Convention has only one callee-save register that
// we use. We push this after the frame pointer (and after the
// parameters).
static const int kBackup_rbx = kAtStart - kPointerSize;
static const int kLastCalleeSaveRegister = kBackup_rbx;
#endif
// When adding local variables remember to push space for them in
// the frame in GetCode.
static const int kInputStartMinusOne =
kLastCalleeSaveRegister - kPointerSize;
// First register address. Following registers are below it on the stack.
static const int kRegisterZero = kInputStartMinusOne - kPointerSize;
// Initial size of code buffer.
static const size_t kRegExpCodeSize = 1024;
// Load a number of characters at the given offset from the
// current position, into the current-character register.
void LoadCurrentCharacterUnchecked(int cp_offset, int character_count);
// Check whether preemption has been requested.
void CheckPreemption();
// Check whether we are exceeding the stack limit on the backtrack stack.
void CheckStackLimit();
// Called from RegExp if the stack-guard is triggered.
// If the code object is relocated, the return address is fixed before
// returning.
static int CheckStackGuardState(Address* return_address,
Code* re_code,
Address re_frame);
// Generate a call to CheckStackGuardState.
void CallCheckStackGuardState();
// Called from RegExp if the backtrack stack limit is hit.
// Tries to expand the stack. Returns the new stack-pointer if
// successful, and updates the stack_top address, or returns 0 if unable
// to grow the stack.
// This function must not trigger a garbage collection.
static Address GrowStack(Address stack_pointer, Address* stack_top);
// The rbp-relative location of a regexp register.
Operand register_location(int register_index);
// The register containing the current character after LoadCurrentCharacter.
inline Register current_character() { return rdx; }
// The register containing the backtrack stack top. Provides a meaningful
// name to the register.
inline Register backtrack_stackpointer() { return rcx; }
// The registers containing a self pointer to this code's Code object.
inline Register code_object_pointer() { return r8; }
// Byte size of chars in the string to match (decided by the Mode argument)
inline int char_size() { return static_cast<int>(mode_); }
// Equivalent to a conditional branch to the label, unless the label
// is NULL, in which case it is a conditional Backtrack.
void BranchOrBacktrack(Condition condition, Label* to);
void MarkPositionForCodeRelativeFixup() {
code_relative_fixup_positions_.Add(masm_->pc_offset());
}
void FixupCodeRelativePositions();
// Call and return internally in the generated code in a way that
// is GC-safe (i.e., doesn't leave absolute code addresses on the stack)
inline void SafeCall(Label* to);
inline void SafeCallTarget(Label* label);
inline void SafeReturn();
// Pushes the value of a register on the backtrack stack. Decrements the
// stack pointer (rcx) by a word size and stores the register's value there.
inline void Push(Register source);
// Pushes a value on the backtrack stack. Decrements the stack pointer (rcx)
// by a word size and stores the value there.
inline void Push(Immediate value);
// Pushes the Code object relative offset of a label on the backtrack stack
// (i.e., a backtrack target). Decrements the stack pointer (rcx)
// by a word size and stores the value there.
inline void Push(Label* label);
// Pops a value from the backtrack stack. Reads the word at the stack pointer
// (rcx) and increments it by a word size.
inline void Pop(Register target);
// Drops the top value from the backtrack stack without reading it.
// Increments the stack pointer (rcx) by a word size.
inline void Drop();
// Before calling a C-function from generated code, align arguments on stack.
// After aligning the frame, arguments must be stored in esp[0], esp[4],
// etc., not pushed. The argument count assumes all arguments are word sized.
// Some compilers/platforms require the stack to be aligned when calling
// C++ code.
// Needs a scratch register to do some arithmetic. This register will be
// trashed.
inline void FrameAlign(int num_arguments);
// Calls a C function and cleans up the space for arguments allocated
// by FrameAlign. The called function is not allowed to trigger a garbage
// collection, since that might move the code and invalidate the return
// address (unless this is somehow accounted for by the called function).
inline void CallCFunction(Address function_address, int num_arguments);
MacroAssembler* masm_;
ZoneList<int> code_relative_fixup_positions_;
// Which mode to generate code for (ASCII or UC16).
Mode mode_;
// One greater than maximal register index actually used.
int num_registers_;
// Number of registers to output at the end (the saved registers
// are always 0..num_saved_registers_-1)
int num_saved_registers_;
// Labels used internally.
Label entry_label_;
Label start_label_;
Label success_label_;
Label backtrack_label_;
Label exit_label_;
Label check_preempt_label_;
Label stack_overflow_label_;
};
}} // namespace v8::internal
#endif // V8_X64_REGEXP_MACRO_ASSEMBLER_X64_H_

58
deps/v8/test/cctest/cctest.status

@ -60,61 +60,3 @@ test-log/ProfLazyMode: SKIP
# the JavaScript stacks are separate.
test-api/ExceptionOrder: FAIL
test-api/TryCatchInTryFinally: FAIL
[ $arch == x64 ]
test-decls/Present: CRASH || FAIL
test-decls/Unknown: CRASH || FAIL
test-decls/Appearing: CRASH || FAIL
test-decls/Absent: CRASH || FAIL
test-debug/DebugStub: CRASH || FAIL
test-decls/AbsentInPrototype: CRASH || FAIL
test-decls/Reappearing: CRASH || FAIL
test-debug/DebugInfo: CRASH || FAIL
test-decls/ExistsInPrototype: CRASH || FAIL
test-debug/BreakPointICStore: CRASH || FAIL
test-debug/BreakPointICLoad: CRASH || FAIL
test-debug/BreakPointICCall: CRASH || FAIL
test-debug/BreakPointReturn: CRASH || FAIL
test-debug/GCDuringBreakPointProcessing: CRASH || FAIL
test-debug/BreakPointSurviveGC: CRASH || FAIL
test-debug/BreakPointThroughJavaScript: CRASH || FAIL
test-debug/ScriptBreakPointByNameThroughJavaScript: CRASH || FAIL
test-debug/ScriptBreakPointByIdThroughJavaScript: CRASH || FAIL
test-debug/EnableDisableScriptBreakPoint: CRASH || FAIL
test-debug/ConditionalScriptBreakPoint: CRASH || FAIL
test-debug/ScriptBreakPointIgnoreCount: CRASH || FAIL
test-debug/ScriptBreakPointReload: CRASH || FAIL
test-debug/ScriptBreakPointMultiple: CRASH || FAIL
test-debug/RemoveBreakPointInBreak: CRASH || FAIL
test-debug/DebugEvaluate: CRASH || FAIL
test-debug/ScriptBreakPointLine: CRASH || FAIL
test-debug/ScriptBreakPointLineOffset: CRASH || FAIL
test-debug/DebugStepLinear: CRASH || FAIL
test-debug/DebugStepKeyedLoadLoop: CRASH || FAIL
test-debug/DebugStepKeyedStoreLoop: CRASH || FAIL
test-debug/DebugStepLinearMixedICs: CRASH || FAIL
test-debug/DebugStepFor: CRASH || FAIL
test-debug/DebugStepIf: CRASH || FAIL
test-debug/DebugStepSwitch: CRASH || FAIL
test-debug/StepInOutSimple: CRASH || FAIL
test-debug/StepInOutBranch: CRASH || FAIL
test-debug/StepInOutTree: CRASH || FAIL
test-debug/DebugStepNatives: CRASH || FAIL
test-debug/DebugStepFunctionApply: CRASH || FAIL
test-debug/DebugStepFunctionCall: CRASH || FAIL
test-debug/StepWithException: CRASH || FAIL
test-debug/DebugBreak: CRASH || FAIL
test-debug/DisableBreak: CRASH || FAIL
test-debug/MessageQueues: CRASH || FAIL
test-debug/CallFunctionInDebugger: SKIP
test-debug/RecursiveBreakpoints: CRASH || FAIL
test-debug/DebuggerUnload: CRASH || FAIL
test-debug/DebuggerHostDispatch: CRASH || FAIL
test-debug/DebugBreakInMessageHandler: CRASH || FAIL
test-debug/NoDebugBreakInAfterCompileMessageHandler: CRASH || FAIL
test-api/Threading: CRASH || FAIL
test-api/Threading2: PASS || TIMEOUT
test-api/TryCatchSourceInfo: CRASH || FAIL
test-api/RegExpInterruption: PASS || TIMEOUT
test-api/RegExpStringModification: PASS || TIMEOUT

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

@ -7738,3 +7738,31 @@ THREADED_TEST(PixelArray) {
free(pixel_data);
}
THREADED_TEST(ScriptContextDependence) {
v8::HandleScope scope;
LocalContext c1;
const char *source = "foo";
v8::Handle<v8::Script> dep = v8::Script::Compile(v8::String::New(source));
v8::Handle<v8::Script> indep = v8::Script::New(v8::String::New(source));
c1->Global()->Set(v8::String::New("foo"), v8::Integer::New(100));
CHECK_EQ(dep->Run()->Int32Value(), 100);
CHECK_EQ(indep->Run()->Int32Value(), 100);
LocalContext c2;
c2->Global()->Set(v8::String::New("foo"), v8::Integer::New(101));
CHECK_EQ(dep->Run()->Int32Value(), 100);
CHECK_EQ(indep->Run()->Int32Value(), 101);
}
THREADED_TEST(StackTrace) {
v8::HandleScope scope;
LocalContext context;
v8::TryCatch try_catch;
const char *source = "function foo() { FAIL.FAIL; }; foo();";
v8::Handle<v8::String> src = v8::String::New(source);
v8::Handle<v8::String> origin = v8::String::New("stack-trace-test");
v8::Script::New(src, origin)->Run();
CHECK(try_catch.HasCaught());
v8::String::Utf8Value stack(try_catch.StackTrace());
CHECK(strstr(*stack, "at foo (stack-trace-test") != NULL);
}

25
deps/v8/test/cctest/test-debug.cc

@ -487,9 +487,7 @@ void CheckDebugBreakFunction(DebugLocalContext* env,
CHECK_EQ(debug_break,
Code::GetCodeFromTargetAddress(it1.it()->rinfo()->target_address()));
} else {
// TODO(1240753): Make the test architecture independent or split
// parts of the debugger into architecture dependent files.
CHECK_EQ(0xE8, *(it1.rinfo()->pc()));
CHECK(Debug::IsDebugBreakAtReturn(it1.it()->rinfo()));
}
// Clear the break point and check that the debug break function is no longer
@ -501,9 +499,7 @@ void CheckDebugBreakFunction(DebugLocalContext* env,
it2.FindBreakLocationFromPosition(position);
CHECK_EQ(mode, it2.it()->rinfo()->rmode());
if (mode == v8::internal::RelocInfo::JS_RETURN) {
// TODO(1240753): Make the test architecture independent or split
// parts of the debugger into architecture dependent files.
CHECK_NE(0xE8, *(it2.rinfo()->pc()));
CHECK(!Debug::IsDebugBreakAtReturn(it2.it()->rinfo()));
}
}
@ -5357,3 +5353,20 @@ TEST(NoDebugBreakInAfterCompileMessageHandler) {
v8::Debug::SetMessageHandler2(NULL);
CheckDebuggerUnloaded();
}
TEST(GetMirror) {
v8::HandleScope scope;
DebugLocalContext env;
v8::Handle<v8::Value> obj = v8::Debug::GetMirror(v8::String::New("hodja"));
v8::Handle<v8::Function> run_test = v8::Handle<v8::Function>::Cast(
v8::Script::New(
v8::String::New(
"function runTest(mirror) {"
" return mirror.isString() && (mirror.length() == 5);"
"}"
""
"runTest;"))->Run());
v8::Handle<v8::Value> result = run_test->Call(env->Global(), 1, &obj);
CHECK(result->IsTrue());
}

5
deps/v8/test/cctest/test-decls.cc

@ -111,7 +111,7 @@ void DeclarationContext::InitializeIfNeeded() {
if (is_initialized_) return;
HandleScope scope;
Local<FunctionTemplate> function = FunctionTemplate::New();
Local<Value> data = Integer::New(reinterpret_cast<intptr_t>(this));
Local<Value> data = External::New(this);
GetHolder(function)->SetNamedPropertyHandler(&HandleGet,
&HandleSet,
&HandleHas,
@ -179,8 +179,7 @@ v8::Handle<Boolean> DeclarationContext::HandleHas(Local<String> key,
DeclarationContext* DeclarationContext::GetInstance(const AccessorInfo& info) {
Local<Value> data = info.Data();
return reinterpret_cast<DeclarationContext*>(Int32::Cast(*data)->Value());
return static_cast<DeclarationContext*>(External::Unwrap(info.Data()));
}

12
deps/v8/test/cctest/test-heap.cc

@ -44,35 +44,26 @@ TEST(HeapMaps) {
static void CheckOddball(Object* obj, const char* string) {
CHECK(obj->IsOddball());
#ifndef V8_HOST_ARCH_64_BIT
// TODO(X64): Reenable when native builtins work.
bool exc;
Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
#endif // V8_HOST_ARCH_64_BIT
}
static void CheckSmi(int value, const char* string) {
#ifndef V8_HOST_ARCH_64_BIT
// TODO(X64): Reenable when native builtins work.
bool exc;
Object* print_string =
*Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
#endif // V8_HOST_ARCH_64_BIT
}
static void CheckNumber(double value, const char* string) {
Object* obj = Heap::NumberFromDouble(value);
CHECK(obj->IsNumber());
#ifndef V8_HOST_ARCH_64_BIT
// TODO(X64): Reenable when native builtins work.
bool exc;
Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
#endif // V8_HOST_ARCH_64_BIT
}
@ -492,8 +483,11 @@ static const char* not_so_random_string_table[] = {
static void CheckSymbols(const char** strings) {
for (const char* string = *strings; *strings != 0; string = *strings++) {
Object* a = Heap::LookupAsciiSymbol(string);
// LookupAsciiSymbol may return a failure if a GC is needed.
if (a->IsFailure()) continue;
CHECK(a->IsSymbol());
Object* b = Heap::LookupAsciiSymbol(string);
if (b->IsFailure()) continue;
CHECK_EQ(b, a);
CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
}

443
deps/v8/test/cctest/test-regexp.cc

@ -38,18 +38,21 @@
#include "jsregexp.h"
#include "regexp-macro-assembler.h"
#include "regexp-macro-assembler-irregexp.h"
#ifdef V8_NATIVE_REGEXP
#ifdef V8_TARGET_ARCH_ARM
#include "arm/regexp-macro-assembler-arm.h"
#endif
#ifdef V8_TARGET_ARCH_X64
// No X64-implementation yet.
#include "x64/macro-assembler-x64.h"
#include "x64/regexp-macro-assembler-x64.h"
#endif
#ifdef V8_TARGET_ARCH_IA32
#include "ia32/macro-assembler-ia32.h"
#include "ia32/regexp-macro-assembler-ia32.h"
#endif
#else
#include "interpreter-irregexp.h"
#endif
using namespace v8::internal;
@ -599,75 +602,20 @@ TEST(DispatchTableConstruction) {
// Tests of interpreter.
TEST(MacroAssembler) {
V8::Initialize(NULL);
byte codes[1024];
RegExpMacroAssemblerIrregexp m(Vector<byte>(codes, 1024));
// ^f(o)o.
Label fail, fail2, start;
uc16 foo_chars[3];
foo_chars[0] = 'f';
foo_chars[1] = 'o';
foo_chars[2] = 'o';
Vector<const uc16> foo(foo_chars, 3);
m.SetRegister(4, 42);
m.PushRegister(4, RegExpMacroAssembler::kNoStackLimitCheck);
m.AdvanceRegister(4, 42);
m.GoTo(&start);
m.Fail();
m.Bind(&start);
m.PushBacktrack(&fail2);
m.CheckCharacters(foo, 0, &fail, true);
m.WriteCurrentPositionToRegister(0, 0);
m.PushCurrentPosition();
m.AdvanceCurrentPosition(3);
m.WriteCurrentPositionToRegister(1, 0);
m.PopCurrentPosition();
m.AdvanceCurrentPosition(1);
m.WriteCurrentPositionToRegister(2, 0);
m.AdvanceCurrentPosition(1);
m.WriteCurrentPositionToRegister(3, 0);
m.Succeed();
m.Bind(&fail);
m.Backtrack();
m.Succeed();
m.Bind(&fail2);
m.PopRegister(0);
m.Fail();
v8::HandleScope scope;
Handle<String> source = Factory::NewStringFromAscii(CStrVector("^f(o)o"));
Handle<ByteArray> array = Handle<ByteArray>::cast(m.GetCode(source));
int captures[5];
const uc16 str1[] = {'f', 'o', 'o', 'b', 'a', 'r'};
Handle<String> f1_16 =
Factory::NewStringFromTwoByte(Vector<const uc16>(str1, 6));
CHECK(IrregexpInterpreter::Match(array, f1_16, captures, 0));
CHECK_EQ(0, captures[0]);
CHECK_EQ(3, captures[1]);
CHECK_EQ(1, captures[2]);
CHECK_EQ(2, captures[3]);
CHECK_EQ(84, captures[4]);
const uc16 str2[] = {'b', 'a', 'r', 'f', 'o', 'o'};
Handle<String> f2_16 =
Factory::NewStringFromTwoByte(Vector<const uc16>(str2, 6));
CHECK(!IrregexpInterpreter::Match(array, f2_16, captures, 0));
CHECK_EQ(42, captures[0]);
}
#ifdef V8_TARGET_ARCH_IA32 // IA32 Native Regexp only tests.
#ifdef V8_NATIVE_REGEXP
#ifdef V8_TARGET_ARCH_IA32
typedef RegExpMacroAssemblerIA32 ArchRegExpMacroAssembler;
#endif
#ifdef V8_TARGET_ARCH_X64
typedef RegExpMacroAssemblerX64 ArchRegExpMacroAssembler;
#endif
class ContextInitializer {
public:
ContextInitializer() : env_(), scope_(), stack_guard_() {
ContextInitializer()
: env_(), scope_(), zone_(DELETE_ON_EXIT), stack_guard_() {
env_ = v8::Context::New();
env_->Enter();
}
@ -678,18 +626,19 @@ class ContextInitializer {
private:
v8::Persistent<v8::Context> env_;
v8::HandleScope scope_;
v8::internal::ZoneScope zone_;
v8::internal::StackGuard stack_guard_;
};
static RegExpMacroAssemblerIA32::Result ExecuteIA32(Code* code,
String* input,
int start_offset,
const byte* input_start,
const byte* input_end,
int* captures,
bool at_start) {
return RegExpMacroAssemblerIA32::Execute(
static ArchRegExpMacroAssembler::Result Execute(Code* code,
String* input,
int start_offset,
const byte* input_start,
const byte* input_end,
int* captures,
bool at_start) {
return NativeRegExpMacroAssembler::Execute(
code,
input,
start_offset,
@ -700,11 +649,11 @@ static RegExpMacroAssemblerIA32::Result ExecuteIA32(Code* code,
}
TEST(MacroAssemblerIA32Success) {
TEST(MacroAssemblerNativeSuccess) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4);
m.Succeed();
@ -718,16 +667,16 @@ TEST(MacroAssemblerIA32Success) {
const byte* start_adr =
reinterpret_cast<const byte*>(seq_input->GetCharsAddress());
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + seq_input->length(),
captures,
true);
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
start_adr + seq_input->length(),
captures,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
CHECK_EQ(-1, captures[0]);
CHECK_EQ(-1, captures[1]);
CHECK_EQ(-1, captures[2]);
@ -735,11 +684,11 @@ TEST(MacroAssemblerIA32Success) {
}
TEST(MacroAssemblerIA32Simple) {
TEST(MacroAssemblerNativeSimple) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4);
uc16 foo_chars[3] = {'f', 'o', 'o'};
Vector<const uc16> foo(foo_chars, 3);
@ -762,16 +711,16 @@ TEST(MacroAssemblerIA32Simple) {
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length(),
captures,
true);
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
start_adr + input->length(),
captures,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
CHECK_EQ(0, captures[0]);
CHECK_EQ(3, captures[1]);
CHECK_EQ(-1, captures[2]);
@ -781,23 +730,23 @@ TEST(MacroAssemblerIA32Simple) {
seq_input = Handle<SeqAsciiString>::cast(input);
start_adr = seq_input->GetCharsAddress();
result = ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length(),
captures,
true);
result = Execute(*code,
*input,
0,
start_adr,
start_adr + input->length(),
captures,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::FAILURE, result);
CHECK_EQ(NativeRegExpMacroAssembler::FAILURE, result);
}
TEST(MacroAssemblerIA32SimpleUC16) {
TEST(MacroAssemblerNativeSimpleUC16) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::UC16, 4);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::UC16, 4);
uc16 foo_chars[3] = {'f', 'o', 'o'};
Vector<const uc16> foo(foo_chars, 3);
@ -822,16 +771,16 @@ TEST(MacroAssemblerIA32SimpleUC16) {
Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length(),
captures,
true);
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
start_adr + input->length(),
captures,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
CHECK_EQ(0, captures[0]);
CHECK_EQ(3, captures[1]);
CHECK_EQ(-1, captures[2]);
@ -842,23 +791,23 @@ TEST(MacroAssemblerIA32SimpleUC16) {
seq_input = Handle<SeqTwoByteString>::cast(input);
start_adr = seq_input->GetCharsAddress();
result = ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length() * 2,
captures,
true);
result = Execute(*code,
*input,
0,
start_adr,
start_adr + input->length() * 2,
captures,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::FAILURE, result);
CHECK_EQ(NativeRegExpMacroAssembler::FAILURE, result);
}
TEST(MacroAssemblerIA32Backtrack) {
TEST(MacroAssemblerNativeBacktrack) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 0);
Label fail;
Label backtrack;
@ -879,24 +828,24 @@ TEST(MacroAssemblerIA32Backtrack) {
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length(),
NULL,
true);
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
start_adr + input->length(),
NULL,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::FAILURE, result);
CHECK_EQ(NativeRegExpMacroAssembler::FAILURE, result);
}
TEST(MacroAssemblerIA32BackReferenceASCII) {
TEST(MacroAssemblerNativeBackReferenceASCII) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 3);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 3);
m.WriteCurrentPositionToRegister(0, 0);
m.AdvanceCurrentPosition(2);
@ -922,27 +871,27 @@ TEST(MacroAssemblerIA32BackReferenceASCII) {
Address start_adr = seq_input->GetCharsAddress();
int output[3];
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length(),
output,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
start_adr + input->length(),
output,
true);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
CHECK_EQ(0, output[0]);
CHECK_EQ(2, output[1]);
CHECK_EQ(6, output[2]);
}
TEST(MacroAssemblerIA32BackReferenceUC16) {
TEST(MacroAssemblerNativeBackReferenceUC16) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::UC16, 3);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::UC16, 3);
m.WriteCurrentPositionToRegister(0, 0);
m.AdvanceCurrentPosition(2);
@ -970,8 +919,8 @@ TEST(MacroAssemblerIA32BackReferenceUC16) {
Address start_adr = seq_input->GetCharsAddress();
int output[3];
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
@ -979,7 +928,7 @@ TEST(MacroAssemblerIA32BackReferenceUC16) {
output,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
CHECK_EQ(0, output[0]);
CHECK_EQ(2, output[1]);
CHECK_EQ(6, output[2]);
@ -987,11 +936,11 @@ TEST(MacroAssemblerIA32BackReferenceUC16) {
TEST(MacroAssemblerIA32AtStart) {
TEST(MacroAssemblernativeAtStart) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 0);
Label not_at_start, newline, fail;
m.CheckNotAtStart(&not_at_start);
@ -1022,34 +971,34 @@ TEST(MacroAssemblerIA32AtStart) {
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length(),
NULL,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
result = ExecuteIA32(*code,
*input,
3,
start_adr + 3,
start_adr + input->length(),
NULL,
false);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
start_adr + input->length(),
NULL,
true);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
result = Execute(*code,
*input,
3,
start_adr + 3,
start_adr + input->length(),
NULL,
false);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
}
TEST(MacroAssemblerIA32BackRefNoCase) {
TEST(MacroAssemblerNativeBackRefNoCase) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 4);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4);
Label fail, succ;
@ -1084,16 +1033,16 @@ TEST(MacroAssemblerIA32BackRefNoCase) {
Address start_adr = seq_input->GetCharsAddress();
int output[4];
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length(),
output,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
start_adr + input->length(),
output,
true);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
CHECK_EQ(0, output[0]);
CHECK_EQ(12, output[1]);
CHECK_EQ(0, output[2]);
@ -1102,11 +1051,11 @@ TEST(MacroAssemblerIA32BackRefNoCase) {
TEST(MacroAssemblerIA32Registers) {
TEST(MacroAssemblerNativeRegisters) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 5);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 5);
uc16 foo_chars[3] = {'f', 'o', 'o'};
Vector<const uc16> foo(foo_chars, 3);
@ -1184,8 +1133,8 @@ TEST(MacroAssemblerIA32Registers) {
Address start_adr = seq_input->GetCharsAddress();
int output[5];
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
@ -1193,7 +1142,7 @@ TEST(MacroAssemblerIA32Registers) {
output,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
CHECK_EQ(0, output[0]);
CHECK_EQ(3, output[1]);
CHECK_EQ(6, output[2]);
@ -1202,11 +1151,11 @@ TEST(MacroAssemblerIA32Registers) {
}
TEST(MacroAssemblerIA32StackOverflow) {
TEST(MacroAssemblerStackOverflow) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 0);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 0);
Label loop;
m.Bind(&loop);
@ -1224,26 +1173,26 @@ TEST(MacroAssemblerIA32StackOverflow) {
Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
Address start_adr = seq_input->GetCharsAddress();
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length(),
NULL,
true);
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
start_adr + input->length(),
NULL,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::EXCEPTION, result);
CHECK_EQ(NativeRegExpMacroAssembler::EXCEPTION, result);
CHECK(Top::has_pending_exception());
Top::clear_pending_exception();
}
TEST(MacroAssemblerIA32LotsOfRegisters) {
TEST(MacroAssemblerNativeLotsOfRegisters) {
v8::V8::Initialize();
ContextInitializer initializer;
RegExpMacroAssemblerIA32 m(RegExpMacroAssemblerIA32::ASCII, 2);
ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 2);
// At least 2048, to ensure the allocated space for registers
// span one full page.
@ -1270,24 +1219,88 @@ TEST(MacroAssemblerIA32LotsOfRegisters) {
Address start_adr = seq_input->GetCharsAddress();
int captures[2];
RegExpMacroAssemblerIA32::Result result =
ExecuteIA32(*code,
*input,
0,
start_adr,
start_adr + input->length(),
captures,
true);
CHECK_EQ(RegExpMacroAssemblerIA32::SUCCESS, result);
NativeRegExpMacroAssembler::Result result =
Execute(*code,
*input,
0,
start_adr,
start_adr + input->length(),
captures,
true);
CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
CHECK_EQ(0, captures[0]);
CHECK_EQ(42, captures[1]);
Top::clear_pending_exception();
}
#endif // V8_REGEXP_NATIVE
#endif // V8_TARGET_ARCH_IA32
#else // ! V8_REGEX_NATIVE
TEST(MacroAssembler) {
V8::Initialize(NULL);
byte codes[1024];
RegExpMacroAssemblerIrregexp m(Vector<byte>(codes, 1024));
// ^f(o)o.
Label fail, fail2, start;
uc16 foo_chars[3];
foo_chars[0] = 'f';
foo_chars[1] = 'o';
foo_chars[2] = 'o';
Vector<const uc16> foo(foo_chars, 3);
m.SetRegister(4, 42);
m.PushRegister(4, RegExpMacroAssembler::kNoStackLimitCheck);
m.AdvanceRegister(4, 42);
m.GoTo(&start);
m.Fail();
m.Bind(&start);
m.PushBacktrack(&fail2);
m.CheckCharacters(foo, 0, &fail, true);
m.WriteCurrentPositionToRegister(0, 0);
m.PushCurrentPosition();
m.AdvanceCurrentPosition(3);
m.WriteCurrentPositionToRegister(1, 0);
m.PopCurrentPosition();
m.AdvanceCurrentPosition(1);
m.WriteCurrentPositionToRegister(2, 0);
m.AdvanceCurrentPosition(1);
m.WriteCurrentPositionToRegister(3, 0);
m.Succeed();
m.Bind(&fail);
m.Backtrack();
m.Succeed();
m.Bind(&fail2);
m.PopRegister(0);
m.Fail();
v8::HandleScope scope;
Handle<String> source = Factory::NewStringFromAscii(CStrVector("^f(o)o"));
Handle<ByteArray> array = Handle<ByteArray>::cast(m.GetCode(source));
int captures[5];
const uc16 str1[] = {'f', 'o', 'o', 'b', 'a', 'r'};
Handle<String> f1_16 =
Factory::NewStringFromTwoByte(Vector<const uc16>(str1, 6));
CHECK(IrregexpInterpreter::Match(array, f1_16, captures, 0));
CHECK_EQ(0, captures[0]);
CHECK_EQ(3, captures[1]);
CHECK_EQ(1, captures[2]);
CHECK_EQ(2, captures[3]);
CHECK_EQ(84, captures[4]);
const uc16 str2[] = {'b', 'a', 'r', 'f', 'o', 'o'};
Handle<String> f2_16 =
Factory::NewStringFromTwoByte(Vector<const uc16>(str2, 6));
CHECK(!IrregexpInterpreter::Match(array, f2_16, captures, 0));
CHECK_EQ(42, captures[0]);
}
#endif // ! V8_REGEXP_NATIVE
TEST(AddInverseToTable) {

13
deps/v8/test/message/message.status

@ -29,16 +29,3 @@ prefix message
# All tests in the bug directory are expected to fail.
bugs: FAIL
[ $arch == x64 ]
simple-throw: FAIL
try-catch-finally-throw-in-catch-and-finally: FAIL
try-catch-finally-throw-in-catch: FAIL
try-catch-finally-throw-in-finally: FAIL
try-finally-throw-in-finally: FAIL
try-finally-throw-in-try-and-finally: FAIL
try-finally-throw-in-try: FAIL
overwritten-builtins: FAIL
regress/regress-73: FAIL
regress/regress-75: FAIL

9
deps/v8/test/mjsunit/div-mod.js

@ -48,7 +48,7 @@ function run_tests_for(divisor) {
divmod(div_func, mod_func, 0, divisor);
divmod(div_func, mod_func, 1 / 0, divisor);
// Floating point number test.
for (exp = -1024; exp <= 1024; exp += 4) {
for (exp = -1024; exp <= 1024; exp += 8) {
divmod(div_func, mod_func, Math.pow(2, exp), divisor);
divmod(div_func, mod_func, 0.9999999 * Math.pow(2, exp), divisor);
divmod(div_func, mod_func, 1.0000001 * Math.pow(2, exp), divisor);
@ -76,13 +76,7 @@ var divisors = [
8,
9,
10,
// These ones in the middle don't add much apart from slowness to the test.
0x1000000,
0x2000000,
0x4000000,
0x8000000,
0x10000000,
0x20000000,
0x40000000,
12,
60,
@ -92,4 +86,3 @@ var divisors = [
for (var i = 0; i < divisors.length; i++) {
run_tests_for(divisors[i]);
}

8
deps/v8/test/mjsunit/mjsunit.js

@ -179,9 +179,13 @@ function assertInstanceof(obj, type) {
function assertDoesNotThrow(code) {
try {
eval(code);
if (typeof code == 'function') {
code();
} else {
eval(code);
}
} catch (e) {
assertTrue(false, "threw an exception");
assertTrue(false, "threw an exception: " + (e.message || e));
}
}

30
deps/v8/test/mjsunit/mjsunit.status

@ -73,33 +73,3 @@ string-compare-alignment: PASS || FAIL
# Times out often in release mode on ARM.
array-splice: PASS || TIMEOUT
[ $arch == x64 ]
debug-backtrace: CRASH || FAIL
debug-backtrace-text: CRASH || FAIL
debug-multiple-breakpoints: CRASH || FAIL
debug-breakpoints: CRASH || FAIL
debug-changebreakpoint: CRASH || FAIL
debug-clearbreakpoint: CRASH || FAIL
debug-conditional-breakpoints: CRASH || FAIL
debug-constructor: CRASH || FAIL
debug-continue: CRASH || FAIL
debug-enable-disable-breakpoints: CRASH || FAIL
debug-evaluate-recursive: CRASH || FAIL
debug-event-listener: CRASH || FAIL
debug-evaluate: CRASH || FAIL
debug-ignore-breakpoints: CRASH || FAIL
debug-setbreakpoint: CRASH || FAIL
debug-step-stub-callfunction: CRASH || FAIL
debug-step: CRASH || FAIL
debug-stepin-builtin: CRASH || FAIL
debug-stepin-constructor: CRASH || FAIL
debug-stepin-function-call: CRASH || FAIL
debug-stepin-accessor: CRASH || FAIL
fuzz-natives: PASS || TIMEOUT
debug-handle: CRASH || FAIL
debug-clearbreakpointgroup: CRASH || FAIL
regress/regress-269: CRASH || FAIL
regress/regress-998565: CRASH || FAIL
tools/tickprocessor: PASS || CRASH || FAIL

78
deps/v8/test/mjsunit/simple-constructor.js

@ -0,0 +1,78 @@
// Copyright 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.
function props(x) {
var array = [];
for (var p in x) array.push(p);
return array.sort();
}
function f1() {
this.x = 1;
}
function f2(x) {
this.x = x;
}
function f3(x) {
this.x = x;
this.y = 1;
this.z = f1;
}
function f4(x) {
this.x = x;
this.y = 1;
if (x == 1) return;
this.z = f1;
}
o1_1 = new f1();
o1_2 = new f1();
assertArrayEquals(["x"], props(o1_1));
assertArrayEquals(["x"], props(o1_2));
o2_1 = new f2(0);
o2_2 = new f2(0);
assertArrayEquals(["x"], props(o2_1));
assertArrayEquals(["x"], props(o2_2));
o3_1 = new f3(0);
o3_2 = new f3(0);
assertArrayEquals(["x", "y", "z"], props(o3_1));
assertArrayEquals(["x", "y", "z"], props(o3_2));
o4_0_1 = new f4(0);
o4_0_2 = new f4(0);
assertArrayEquals(["x", "y", "z"], props(o4_0_1));
assertArrayEquals(["x", "y", "z"], props(o4_0_2));
o4_1_1 = new f4(1);
o4_1_2 = new f4(1);
assertArrayEquals(["x", "y"], props(o4_1_1));
assertArrayEquals(["x", "y"], props(o4_1_2));

63
deps/v8/test/mjsunit/stack-traces.js

@ -103,22 +103,24 @@ function testStrippedCustomError() {
// Utility function for testing that the expected strings occur
// in the stack trace produced when running the given function.
function testTrace(fun, expected, unexpected) {
function testTrace(name, fun, expected, unexpected) {
var threw = false;
try {
fun();
} catch (e) {
for (var i = 0; i < expected.length; i++) {
assertTrue(e.stack.indexOf(expected[i]) != -1);
assertTrue(e.stack.indexOf(expected[i]) != -1,
name + " doesn't contain expected[" + i + "]");
}
if (unexpected) {
for (var i = 0; i < unexpected.length; i++) {
assertEquals(e.stack.indexOf(unexpected[i]), -1);
assertEquals(e.stack.indexOf(unexpected[i]), -1,
name + " contains unexpected[" + i + "]");
}
}
threw = true;
}
assertTrue(threw);
assertTrue(threw, name + " didn't throw");
}
// Test that the error constructor is not shown in the trace
@ -127,10 +129,11 @@ function testCallerCensorship() {
try {
FAIL;
} catch (e) {
assertEquals(-1, e.stack.indexOf('at new ReferenceError'));
assertEquals(-1, e.stack.indexOf('at new ReferenceError'),
"CallerCensorship contained new ReferenceError");
threw = true;
}
assertTrue(threw);
assertTrue(threw, "CallerCensorship didn't throw");
}
// Test that the explicit constructor call is shown in the trace
@ -143,10 +146,11 @@ function testUnintendedCallerCensorship() {
}
});
} catch (e) {
assertTrue(e.stack.indexOf('at new ReferenceError') != -1);
assertTrue(e.stack.indexOf('at new ReferenceError') != -1,
"UnintendedCallerCensorship didn't contain new ReferenceError");
threw = true;
}
assertTrue(threw);
assertTrue(threw, "UnintendedCallerCensorship didn't throw");
}
// If an error occurs while the stack trace is being formatted it should
@ -161,9 +165,10 @@ function testErrorsDuringFormatting() {
n.foo();
} catch (e) {
threw = true;
assertTrue(e.stack.indexOf('<error: ReferenceError') != -1);
assertTrue(e.stack.indexOf('<error: ReferenceError') != -1,
"ErrorsDuringFormatting didn't contain error: ReferenceError");
}
assertTrue(threw);
assertTrue(threw, "ErrorsDuringFormatting didn't throw");
threw = false;
// Now we can't even format the message saying that we couldn't format
// the stack frame. Put that in your pipe and smoke it!
@ -172,26 +177,28 @@ function testErrorsDuringFormatting() {
n.foo();
} catch (e) {
threw = true;
assertTrue(e.stack.indexOf('<error>') != -1);
assertTrue(e.stack.indexOf('<error>') != -1,
"ErrorsDuringFormatting didn't contain <error>");
}
assertTrue(threw);
}
testTrace(testArrayNative, ["Array.map (native)"]);
testTrace(testNested, ["at one", "at two", "at three"]);
testTrace(testMethodNameInference, ["at Foo.bar"]);
testTrace(testImplicitConversion, ["at Nirk.valueOf"]);
testTrace(testEval, ["at Doo (eval at testEval"]);
testTrace(testNestedEval, ["eval at Inner (eval at Outer"]);
testTrace(testValue, ["at Number.causeError"]);
testTrace(testConstructor, ["new Plonk"]);
testTrace(testRenamedMethod, ["Wookie.a$b$c$d [as d]"]);
testTrace(testAnonymousMethod, ["Array.<anonymous>"]);
testTrace(testDefaultCustomError, ["hep-hey", "new CustomError"],
assertTrue(threw, "ErrorsDuringFormatting didnt' throw (2)");
}
testTrace("testArrayNative", testArrayNative, ["Array.map (native)"]);
testTrace("testNested", testNested, ["at one", "at two", "at three"]);
testTrace("testMethodNameInference", testMethodNameInference, ["at Foo.bar"]);
testTrace("testImplicitConversion", testImplicitConversion, ["at Nirk.valueOf"]);
testTrace("testEval", testEval, ["at Doo (eval at testEval"]);
testTrace("testNestedEval", testNestedEval, ["eval at Inner (eval at Outer"]);
testTrace("testValue", testValue, ["at Number.causeError"]);
testTrace("testConstructor", testConstructor, ["new Plonk"]);
testTrace("testRenamedMethod", testRenamedMethod, ["Wookie.a$b$c$d [as d]"]);
testTrace("testAnonymousMethod", testAnonymousMethod, ["Array.<anonymous>"]);
testTrace("testDefaultCustomError", testDefaultCustomError,
["hep-hey", "new CustomError"],
["collectStackTrace"]);
testTrace(testStrippedCustomError, ["hep-hey"], ["new CustomError",
"collectStackTrace"]);
testTrace("testStrippedCustomError", testStrippedCustomError, ["hep-hey"],
["new CustomError", "collectStackTrace"]);
testCallerCensorship();
testUnintendedCallerCensorship();
testErrorsDuringFormatting();

16
deps/v8/test/mjsunit/tools/logreader.js

@ -80,3 +80,19 @@
assertEquals('bbbbaaaa', reader.expandBackRef_('bbbb#2:4'));
assertEquals('"#1:1"', reader.expandBackRef_('"#1:1"'));
})();
// See http://code.google.com/p/v8/issues/detail?id=420
(function testReadingTruncatedLog() {
// Having an incorrect event in the middle of a log should throw an exception.
var reader1 = new devtools.profiler.LogReader({});
assertThrows(function() {
reader1.processLogChunk('alias,a,b\nxxxx\nalias,c,d\n');
});
// But having it as the last record should not.
var reader2 = new devtools.profiler.LogReader({});
assertDoesNotThrow(function() {
reader2.processLogChunk('alias,a,b\nalias,c,d\nxxxx');
});
})();

72
deps/v8/test/mjsunit/tools/tickprocessor.js

@ -227,6 +227,78 @@
})();
// http://code.google.com/p/v8/issues/detail?id=427
(function testWindowsProcessExeAndDllMapFile() {
function exeSymbols(exeName) {
return [
' 0000:00000000 ___ImageBase 00400000 <linker-defined>',
' 0001:00000780 ?RunMain@@YAHHQAPAD@Z 00401780 f shell.obj',
' 0001:00000ac0 _main 00401ac0 f shell.obj',
''
].join('\r\n');
}
function dllSymbols(dllName) {
return [
' 0000:00000000 ___ImageBase 01c30000 <linker-defined>',
' 0001:00000780 _DllMain@12 01c31780 f libcmt:dllmain.obj',
' 0001:00000ac0 ___DllMainCRTStartup 01c31ac0 f libcmt:dllcrt0.obj',
''
].join('\r\n');
}
var oldRead = read;
read = exeSymbols;
var exe_exe_syms = [];
(new WindowsCppEntriesProvider()).parseVmSymbols(
'chrome.exe', 0x00400000, 0x00472000,
function (name, start, end) {
exe_exe_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
assertEquals(
[['RunMain', 0x00401780, 0x00401ac0],
['_main', 0x00401ac0, 0x00472000]],
exe_exe_syms, '.exe with .exe symbols');
read = dllSymbols;
var exe_dll_syms = [];
(new WindowsCppEntriesProvider()).parseVmSymbols(
'chrome.exe', 0x00400000, 0x00472000,
function (name, start, end) {
exe_dll_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
assertEquals(
[],
exe_dll_syms, '.exe with .dll symbols');
read = dllSymbols;
var dll_dll_syms = [];
(new WindowsCppEntriesProvider()).parseVmSymbols(
'chrome.dll', 0x01c30000, 0x02b80000,
function (name, start, end) {
dll_dll_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
assertEquals(
[['_DllMain@12', 0x01c31780, 0x01c31ac0],
['___DllMainCRTStartup', 0x01c31ac0, 0x02b80000]],
dll_dll_syms, '.dll with .dll symbols');
read = exeSymbols;
var dll_exe_syms = [];
(new WindowsCppEntriesProvider()).parseVmSymbols(
'chrome.dll', 0x01c30000, 0x02b80000,
function (name, start, end) {
dll_exe_syms.push(Array.prototype.slice.apply(arguments, [0]));
});
assertEquals(
[],
dll_exe_syms, '.dll with .exe symbols');
read = oldRead;
})();
function CppEntriesProviderMock() {
};

12
deps/v8/test/mozilla/mozilla.status

@ -278,6 +278,11 @@ js1_2/regexp/beginLine: FAIL_OK
js1_2/regexp/endLine: FAIL_OK
# To be compatible with safari typeof a regexp yields 'function';
# in firefox it yields 'object'.
js1_2/function/regexparg-1: FAIL_OK
# Date trouble?
js1_5/Date/regress-301738-02: FAIL_OK
@ -803,10 +808,3 @@ ecma/Expressions/11.7.3: SKIP
ecma/Expressions/11.10-3: SKIP
ecma/Expressions/11.7.1: SKIP
ecma_3/RegExp/regress-209067: SKIP
[ $ARCH == x64 ]
# Tests that fail on the 64-bit port. This section should be empty
# when the 64-bit port is fully debugged.
js1_2/regexp/regress-9141: FAIL

18
deps/v8/tools/gyp/v8.gyp

@ -32,6 +32,7 @@
'gcc_version%': 'unknown',
'target_arch%': 'ia32',
'v8_use_snapshot%': 'true',
'v8_regexp%': 'native',
},
'includes': [
'../../../build/common.gypi',
@ -55,6 +56,7 @@
['target_arch=="x64"', {
'defines': [
'V8_TARGET_ARCH_X64',
'V8_NATIVE_REGEXP',
],
}],
],
@ -428,14 +430,18 @@
'../../src/ia32/jump-target-ia32.cc',
'../../src/ia32/macro-assembler-ia32.cc',
'../../src/ia32/macro-assembler-ia32.h',
'../../src/ia32/regexp-macro-assembler-ia32.cc',
'../../src/ia32/regexp-macro-assembler-ia32.h',
'../../src/ia32/register-allocator-ia32.cc',
'../../src/ia32/stub-cache-ia32.cc',
'../../src/ia32/virtual-frame-ia32.cc',
'../../src/ia32/virtual-frame-ia32.h',
],
}],
['target_arch=="ia32" and v8_regexp=="native"', {
'sources': [
'../../src/ia32/regexp-macro-assembler-ia32.cc',
'../../src/ia32/regexp-macro-assembler-ia32.h',
],
}],
['target_arch=="x64"', {
'include_dirs+': [
'../../src/x64',
@ -457,14 +463,18 @@
'../../src/x64/jump-target-x64.cc',
'../../src/x64/macro-assembler-x64.cc',
'../../src/x64/macro-assembler-x64.h',
#'../../src/x64/regexp-macro-assembler-x64.cc',
#'../../src/x64/regexp-macro-assembler-x64.h',
'../../src/x64/register-allocator-x64.cc',
'../../src/x64/stub-cache-x64.cc',
'../../src/x64/virtual-frame-x64.cc',
'../../src/x64/virtual-frame-x64.h',
],
}],
['target_arch=="x64" and v8_regexp=="native"', {
'sources': [
'../../src/x64/regexp-macro-assembler-x64.cc',
'../../src/x64/regexp-macro-assembler-x64.h',
],
}],
['OS=="linux"', {
'link_settings': {
'libraries': [

7
deps/v8/tools/logreader.js

@ -294,8 +294,11 @@ devtools.profiler.LogReader.prototype.processLog_ = function(lines) {
this.dispatchLogRow_(fields);
}
} catch (e) {
this.printError('line ' + (i + 1) + ': ' + (e.message || e));
throw e;
// An error on the last line is acceptable since log file can be truncated.
if (i < n - 1) {
this.printError('line ' + (i + 1) + ': ' + (e.message || e));
throw e;
}
}
};

4
deps/v8/tools/mac-nm

@ -12,7 +12,7 @@
# needs to be parsed, which requires a lot of knowledge to be coded in.
if [ "`which c++filt`" == "" ]; then
nm $@
nm "$@"
else
nm $@ | c++filt -p -i
nm "$@" | c++filt -p -i
fi

33
deps/v8/tools/tickprocessor.js

@ -499,19 +499,32 @@ function WindowsCppEntriesProvider() {
inherits(WindowsCppEntriesProvider, CppEntriesProvider);
WindowsCppEntriesProvider.FILENAME_RE = /^(.*)\.exe$/;
WindowsCppEntriesProvider.FILENAME_RE = /^(.*)\.([^.]+)$/;
WindowsCppEntriesProvider.FUNC_RE =
/^ 0001:[0-9a-fA-F]{8}\s+([_\?@$0-9a-zA-Z]+)\s+([0-9a-fA-F]{8}).*$/;
/^\s+0001:[0-9a-fA-F]{8}\s+([_\?@$0-9a-zA-Z]+)\s+([0-9a-fA-F]{8}).*$/;
WindowsCppEntriesProvider.IMAGE_BASE_RE =
/^\s+0000:00000000\s+___ImageBase\s+([0-9a-fA-F]{8}).*$/;
// This is almost a constant on Windows.
WindowsCppEntriesProvider.EXE_IMAGE_BASE = 0x00400000;
WindowsCppEntriesProvider.prototype.loadSymbols = function(libName) {
var fileNameFields = libName.match(WindowsCppEntriesProvider.FILENAME_RE);
// Only try to load symbols for the .exe file.
if (!fileNameFields) return;
var mapFileName = fileNameFields[1] + '.map';
this.symbols = readFile(mapFileName);
this.moduleType_ = fileNameFields[2].toLowerCase();
try {
this.symbols = read(mapFileName);
} catch (e) {
// If .map file cannot be found let's not panic.
this.symbols = '';
}
};
@ -523,6 +536,18 @@ WindowsCppEntriesProvider.prototype.parseNextLine = function() {
var line = this.symbols.substring(this.parsePos, lineEndPos);
this.parsePos = lineEndPos + 2;
// Image base entry is above all other symbols, so we can just
// terminate parsing.
var imageBaseFields = line.match(WindowsCppEntriesProvider.IMAGE_BASE_RE);
if (imageBaseFields) {
var imageBase = parseInt(imageBaseFields[1], 16);
if ((this.moduleType_ == 'exe') !=
(imageBase == WindowsCppEntriesProvider.EXE_IMAGE_BASE)) {
return false;
}
}
var fields = line.match(WindowsCppEntriesProvider.FUNC_RE);
return fields ?
{ name: this.unmangleName(fields[1]), start: parseInt(fields[2], 16) } :

2
deps/v8/tools/visual_studio/common.vsprops

@ -10,7 +10,7 @@
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="$(ProjectDir)\..\..\src;$(IntDir)\DerivedSources"
PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_USE_32BIT_TIME_T;_HAS_EXCEPTIONS=0;ENABLE_LOGGING_AND_PROFILING"
PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_HAS_EXCEPTIONS=0;ENABLE_LOGGING_AND_PROFILING"
MinimalRebuild="false"
ExceptionHandling="0"
RuntimeTypeInfo="false"

199
deps/v8/tools/visual_studio/d8_x64.vcproj

@ -0,0 +1,199 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="d8"
ProjectGUID="{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}"
RootNamespace="d8"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|x64"
ConfigurationType="1"
InheritedPropertySheets=".\common.vsprops;.\x64.vsprops;.\debug.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
ConfigurationType="1"
InheritedPropertySheets=".\common.vsprops;.\x64.vsprops;.\release.vsprops"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="winmm.lib Ws2_32.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<File
RelativePath="..\..\src\d8.cc"
>
</File>
<File
RelativePath="..\..\src\d8.h"
>
</File>
<File
RelativePath="..\..\src\d8-debug.cc"
>
</File>
<File
RelativePath="..\..\src\d8-debug.h"
>
</File>
<File
RelativePath="..\..\src\d8-windows.cc"
>
</File>
<File
RelativePath="..\..\src\d8.js"
>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Processing js files..."
CommandLine=".\d8js2c.cmd ..\..\src &quot;$(IntDir)\DerivedSources&quot;"
Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCustomBuildTool"
Description="Processing js files..."
CommandLine=".\d8js2c.cmd ..\..\src &quot;$(IntDir)\DerivedSources&quot;"
Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc"
/>
</FileConfiguration>
</File>
<Filter
Name="generated files"
>
<File
RelativePath="$(IntDir)\DerivedSources\natives.cc"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

2
deps/v8/tools/visual_studio/ia32.vsprops

@ -6,6 +6,6 @@
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="V8_TARGET_ARCH_IA32;V8_NATIVE_REGEXP"
PreprocessorDefinitions="_USE_32BIT_TIME_T;V8_TARGET_ARCH_IA32;V8_NATIVE_REGEXP"
/>
</VisualStudioPropertySheet>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save