diff options
author | Ryan <ry@tinyclouds.org> | 2009-08-19 16:37:15 +0200 |
---|---|---|
committer | Ryan <ry@tinyclouds.org> | 2009-08-19 16:37:15 +0200 |
commit | 0cec74d03dc6a1735e731fe06056a1731e14c0df (patch) | |
tree | 9606bcb9afeba305a7b2a1ac4c518ded63a25d89 /deps | |
parent | b590a45849307f5544b7a95854f45064527105ad (diff) | |
download | node-new-0cec74d03dc6a1735e731fe06056a1731e14c0df.tar.gz |
Upgrade v8 to 1.3.5
Diffstat (limited to 'deps')
110 files changed, 6193 insertions, 1307 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index 4bfd8d5ca9..c59661d366 100644 --- a/deps/v8/ChangeLog +++ b/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. diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct index c981ef9139..efd34dbade 100644 --- a/deps/v8/SConstruct +++ b/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): diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h index 345d331a12..3c5c923b3d 100644 --- a/deps/v8/include/v8-debug.h +++ b/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. diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index d8de00ceca..a0cc4ea8b0 100644 --- a/deps/v8/include/v8.h +++ b/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(); @@ -2256,6 +2290,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. * diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript index a9669a1229..6a38c1a79e 100755 --- a/deps/v8/src/SConscript +++ b/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'], diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 0dc4fd7c7e..88cf2bcde0 100644 --- a/deps/v8/src/api.cc +++ b/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); } diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index eeab4a72cc..b3ebb8be8b 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/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; // --------------------------------------------------------------------------- diff --git a/deps/v8/src/arm/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc index b5332ece4c..28524c80ad 100644 --- a/deps/v8/src/arm/builtins-arm.cc +++ b/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)); diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc index d3507ec0e3..40b0ac8160 100644 --- a/deps/v8/src/arm/codegen-arm.cc +++ b/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. diff --git a/deps/v8/src/arm/codegen-arm.h b/deps/v8/src/arm/codegen-arm.h index 80d1d56ee2..70a7b27765 100644 --- a/deps/v8/src/arm/codegen-arm.h +++ b/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_; } diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index 875c91e964..4b02e2d688 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/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)); } diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index 879ee5410a..1ddc8a31e8 100644 --- a/deps/v8/src/assembler.h +++ b/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 diff --git a/deps/v8/src/ast.h b/deps/v8/src/ast.h index 3a309ac96a..ea83712137 100644 --- a/deps/v8/src/ast.h +++ b/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_; diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc index 1ea0245a72..dbd18f82a5 100644 --- a/deps/v8/src/builtins.cc +++ b/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)); diff --git a/deps/v8/src/codegen.cc b/deps/v8/src/codegen.cc index 7a4bb12ed0..8e516c0b04 100644 --- a/deps/v8/src/codegen.cc +++ b/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. diff --git a/deps/v8/src/compilation-cache.cc b/deps/v8/src/compilation-cache.cc index ec5b39c2fb..8dd9ec16b2 100644 --- a/deps/v8/src/compilation-cache.cc +++ b/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)); } diff --git a/deps/v8/src/compiler.cc b/deps/v8/src/compiler.cc index 5607f29622..feff492404 100644 --- a/deps/v8/src/compiler.cc +++ b/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. diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc index 18536f5c7a..f2a28148b1 100644 --- a/deps/v8/src/debug.cc +++ b/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 diff --git a/deps/v8/src/debug.h b/deps/v8/src/debug.h index 970dbbe5ce..5b0273aa22 100644 --- a/deps/v8/src/debug.h +++ b/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. diff --git a/deps/v8/src/execution.cc b/deps/v8/src/execution.cc index 4ab6b61731..9080f5eaaa 100644 --- a/deps/v8/src/execution.cc +++ b/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)); } diff --git a/deps/v8/src/execution.h b/deps/v8/src/execution.h index 126b172d21..fba696e72c 100644 --- a/deps/v8/src/execution.h +++ b/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: diff --git a/deps/v8/src/factory.cc b/deps/v8/src/factory.cc index 36554df732..bb6987bb8c 100644 --- a/deps/v8/src/factory.cc +++ b/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); } diff --git a/deps/v8/src/factory.h b/deps/v8/src/factory.h index 4db5d4e71b..ddf71dec7a 100644 --- a/deps/v8/src/factory.h +++ b/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 diff --git a/deps/v8/src/handles-inl.h b/deps/v8/src/handles-inl.h index 6013c5b51e..8478bb5cd9 100644 --- a/deps/v8/src/handles-inl.h +++ b/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); } diff --git a/deps/v8/src/handles.h b/deps/v8/src/handles.h index ba2694f509..8c9cbebfd9 100644 --- a/deps/v8/src/handles.h +++ b/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: diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index f8d22a2e36..7d6e442b87 100644 --- a/deps/v8/src/heap.cc +++ b/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()) { diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h index 179f9af10c..ec1e21af5b 100644 --- a/deps/v8/src/heap.h +++ b/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_; diff --git a/deps/v8/src/ia32/assembler-ia32.h b/deps/v8/src/ia32/assembler-ia32.h index b648055f1b..6a90e070d8 100644 --- a/deps/v8/src/ia32/assembler-ia32.h +++ b/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. // --------------------------------------------------------------------------- diff --git a/deps/v8/src/ia32/builtins-ia32.cc b/deps/v8/src/ia32/builtins-ia32.cc index a70a9d2acf..6de9de6ee5 100644 --- a/deps/v8/src/ia32/builtins-ia32.cc +++ b/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); } diff --git a/deps/v8/src/ia32/codegen-ia32.cc b/deps/v8/src/ia32/codegen-ia32.cc index 9542b1646f..b8b3db64bd 100644 --- a/deps/v8/src/ia32/codegen-ia32.cc +++ b/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. diff --git a/deps/v8/src/ia32/codegen-ia32.h b/deps/v8/src/ia32/codegen-ia32.h index 1d0cc8bdd2..afdbffe58e 100644 --- a/deps/v8/src/ia32/codegen-ia32.h +++ b/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); }; diff --git a/deps/v8/src/ia32/debug-ia32.cc b/deps/v8/src/ia32/debug-ia32.cc index 9913a39ba9..4ef0862af1 100644 --- a/deps/v8/src/ia32/debug-ia32.cc +++ b/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)); diff --git a/deps/v8/src/ia32/ic-ia32.cc b/deps/v8/src/ia32/ic-ia32.cc index 08ffe2f141..fa9b8a20f6 100644 --- a/deps/v8/src/ia32/ic-ia32.cc +++ b/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; diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc index 7782aa95c6..e362cd3c5b 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.cc +++ b/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 diff --git a/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc b/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc index a49c1f510e..bc8107633e 100644 --- a/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc +++ b/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 diff --git a/deps/v8/src/ia32/regexp-macro-assembler-ia32.h b/deps/v8/src/ia32/regexp-macro-assembler-ia32.h index c3d9155700..d11439299c 100644 --- a/deps/v8/src/ia32/regexp-macro-assembler-ia32.h +++ b/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 diff --git a/deps/v8/src/ic-inl.h b/deps/v8/src/ic-inl.h index 08304d83e7..38d61dcbb4 100644 --- a/deps/v8/src/ic-inl.h +++ b/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 diff --git a/deps/v8/src/ic.cc b/deps/v8/src/ic.cc index f4d74c9354..393ccbf6a7 100644 --- a/deps/v8/src/ic.cc +++ b/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. diff --git a/deps/v8/src/ic.h b/deps/v8/src/ic.h index 860b7e60d6..007b0352e9 100644 --- a/deps/v8/src/ic.h +++ b/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); diff --git a/deps/v8/src/jsregexp.cc b/deps/v8/src/jsregexp.cc index bd511024bb..06208aa50a 100644 --- a/deps/v8/src/jsregexp.cc +++ b/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(¯o_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(¯o_assembler, node, data->capture_count, pattern); -#endif // V8_NATIVE_REGEXP } }} // namespace v8::internal diff --git a/deps/v8/src/math.js b/deps/v8/src/math.js index db75cb28ae..e3d266e4be 100644 --- a/deps/v8/src/math.js +++ b/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. diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc index 40001f9619..e97b207bac 100644 --- a/deps/v8/src/objects-debug.cc +++ b/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"); } diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index a3bd3ce1ca..7b750b61ea 100644 --- a/deps/v8/src/objects-inl.h +++ b/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() { diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index c3051b811c..e4a3a67a57 100644 --- a/deps/v8/src/objects.cc +++ b/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); } diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index 03f0f3dd6b..a4029614e8 100644 --- a/deps/v8/src/objects.h +++ b/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); }; diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index 348c12a4ac..5cc6341f9a 100644 --- a/deps/v8/src/parser.cc +++ b/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. diff --git a/deps/v8/src/parser.h b/deps/v8/src/parser.h index c029c4b25d..86e1f74fbe 100644 --- a/deps/v8/src/parser.h +++ b/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); diff --git a/deps/v8/src/platform-win32.cc b/deps/v8/src/platform-win32.cc index 633b2c25a8..0a2d99041b 100644 --- a/deps/v8/src/platform-win32.cc +++ b/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. diff --git a/deps/v8/src/regexp-macro-assembler-irregexp.cc b/deps/v8/src/regexp-macro-assembler-irregexp.cc index eea3c23eae..21b622ef05 100644 --- a/deps/v8/src/regexp-macro-assembler-irregexp.cc +++ b/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, diff --git a/deps/v8/src/regexp-macro-assembler-irregexp.h b/deps/v8/src/regexp-macro-assembler-irregexp.h index 597046c4c3..dd64e7ae83 100644 --- a/deps/v8/src/regexp-macro-assembler-irregexp.h +++ b/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); diff --git a/deps/v8/src/regexp-macro-assembler-tracer.cc b/deps/v8/src/regexp-macro-assembler-tracer.cc index 30eb485e37..0aad337378 100644 --- a/deps/v8/src/regexp-macro-assembler-tracer.cc +++ b/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", diff --git a/deps/v8/src/regexp-macro-assembler-tracer.h b/deps/v8/src/regexp-macro-assembler-tracer.h index 0fd73f3d6f..28434d7cab 100644 --- a/deps/v8/src/regexp-macro-assembler-tracer.h +++ b/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); diff --git a/deps/v8/src/regexp-macro-assembler.cc b/deps/v8/src/regexp-macro-assembler.cc index 8dede304eb..7f830fe485 100644 --- a/deps/v8/src/regexp-macro-assembler.cc +++ b/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 diff --git a/deps/v8/src/regexp-macro-assembler.h b/deps/v8/src/regexp-macro-assembler.h index 484986428b..e59082768a 100644 --- a/deps/v8/src/regexp-macro-assembler.h +++ b/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_ diff --git a/deps/v8/src/regexp-stack.h b/deps/v8/src/regexp-stack.h index 6c090daa65..99cf33cd32 100644 --- a/deps/v8/src/regexp-stack.h +++ b/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; diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index 0da4be8216..b3e8aa477d 100644 --- a/deps/v8/src/runtime.cc +++ b/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; } diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h index cdf21dcabf..d47ca18e79 100644 --- a/deps/v8/src/runtime.h +++ b/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) \ diff --git a/deps/v8/src/scanner.cc b/deps/v8/src/scanner.cc index 24a6d4be9c..720dc3536c 100644 --- a/deps/v8/src/scanner.cc +++ b/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(); } diff --git a/deps/v8/src/scanner.h b/deps/v8/src/scanner.h index eea23a70c2..340da86ed7 100644 --- a/deps/v8/src/scanner.h +++ b/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. diff --git a/deps/v8/src/scopes.cc b/deps/v8/src/scopes.cc index 78ed035180..25873fac1d 100644 --- a/deps/v8/src/scopes.cc +++ b/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) { } diff --git a/deps/v8/src/scopes.h b/deps/v8/src/scopes.h index 5767d9f017..fc627df619 100644 --- a/deps/v8/src/scopes.h +++ b/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; } diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc index 9f266cb0ea..9227a87f3c 100644 --- a/deps/v8/src/spaces.cc +++ b/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; } diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h index 4760a42402..f12e0e4f47 100644 --- a/deps/v8/src/spaces.h +++ b/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. diff --git a/deps/v8/src/v8-counters.h b/deps/v8/src/v8-counters.h index a62cd74465..43cd5e3d60 100644 --- a/deps/v8/src/v8-counters.h +++ b/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) \ diff --git a/deps/v8/src/v8natives.js b/deps/v8/src/v8natives.js index 841c920852..be92347768 100644 --- a/deps/v8/src/v8natives.js +++ b/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( diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index 7bc52a8490..26b009c78d 100644 --- a/deps/v8/src/version.cc +++ b/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 diff --git a/deps/v8/src/x64/assembler-x64-inl.h b/deps/v8/src/x64/assembler-x64-inl.h index 196f2eedbd..f51a3ea887 100644 --- a/deps/v8/src/x64/assembler-x64-inl.h +++ b/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); } // ----------------------------------------------------------------------------- diff --git a/deps/v8/src/x64/assembler-x64.cc b/deps/v8/src/x64/assembler-x64.cc index b4fd678e17..a02557e96a 100644 --- a/deps/v8/src/x64/assembler-x64.cc +++ b/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); diff --git a/deps/v8/src/x64/assembler-x64.h b/deps/v8/src/x64/assembler-x64.h index 015fa68237..9d602b9ef1 100644 --- a/deps/v8/src/x64/assembler-x64.h +++ b/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. diff --git a/deps/v8/src/x64/builtins-x64.cc b/deps/v8/src/x64/builtins-x64.cc index 087aaff2cb..6988d72082 100644 --- a/deps/v8/src/x64/builtins-x64.cc +++ b/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. diff --git a/deps/v8/src/x64/cfg-x64.cc b/deps/v8/src/x64/cfg-x64.cc index 8d01ed28e1..34ddbbf025 100644 --- a/deps/v8/src/x64/cfg-x64.cc +++ b/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(); } diff --git a/deps/v8/src/x64/codegen-x64.cc b/deps/v8/src/x64/codegen-x64.cc index b3df929d78..7fe6ebdb8b 100644 --- a/deps/v8/src/x64/codegen-x64.cc +++ b/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. diff --git a/deps/v8/src/x64/codegen-x64.h b/deps/v8/src/x64/codegen-x64.h index b1c61d8688..bfdff56744 100644 --- a/deps/v8/src/x64/codegen-x64.h +++ b/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); }; diff --git a/deps/v8/src/x64/debug-x64.cc b/deps/v8/src/x64/debug-x64.cc index 177eb90a49..f2bb62bc69 100644 --- a/deps/v8/src/x64/debug-x64.cc +++ b/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 diff --git a/deps/v8/src/x64/ic-x64.cc b/deps/v8/src/x64/ic-x64.cc index 86008eb325..1c74a44d02 100644 --- a/deps/v8/src/x64/ic-x64.cc +++ b/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; diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc index 2219a5a0ee..8f8398dc9d 100644 --- a/deps/v8/src/x64/macro-assembler-x64.cc +++ b/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); } diff --git a/deps/v8/src/x64/regexp-macro-assembler-x64.cc b/deps/v8/src/x64/regexp-macro-assembler-x64.cc index 209aa2d307..1e38d6da97 100644 --- a/deps/v8/src/x64/regexp-macro-assembler-x64.cc +++ b/deps/v8/src/x64/regexp-macro-assembler-x64.cc @@ -25,3 +25,1277 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#include "v8.h" +#include "serialize.h" +#include "unicode.h" +#include "log.h" +#include "ast.h" +#include "regexp-stack.h" +#include "macro-assembler.h" +#include "regexp-macro-assembler.h" +#include "x64/macro-assembler-x64.h" +#include "x64/regexp-macro-assembler-x64.h" + +namespace v8 { +namespace internal { + +/* + * This assembler uses the following register assignment convention + * - rdx : currently loaded character(s) as ASCII or UC16. Must be loaded using + * LoadCurrentCharacter before using any of the dispatch methods. + * - rdi : current position in input, as negative offset from end of string. + * Please notice that this is the byte offset, not the character + * offset! Is always a 32-bit signed (negative) offset, but must be + * maintained sign-extended to 64 bits, since it is used as index. + * - rsi : end of input (points to byte after last character in input), + * so that rsi+rdi points to the current character. + * - rbp : frame pointer. Used to access arguments, local variables and + * RegExp registers. + * - rsp : points to tip of C stack. + * - rcx : points to tip of backtrack stack. The backtrack stack contains + * only 32-bit values. Most are offsets from some base (e.g., character + * positions from end of string or code location from Code* pointer). + * - r8 : code object pointer. Used to convert between absolute and + * code-object-relative addresses. + * + * The registers rax, rbx, rcx, r9 and r11 are free to use for computations. + * If changed to use r12+, they should be saved as callee-save registers. + * + * Each call to a C++ method should retain these registers. + * + * The stack will have the following content, in some order, indexable from the + * frame pointer (see, e.g., kStackHighEnd): + * - 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). + * - end of input (Address of end of string) + * - start of input (Address of first character in string) + * - String** input_string (location of a handle containing the string) + * - return address + * - backup of callee save registers (rbx, possibly rsi and rdi). + * - Offset of location before start of input (effectively character + * position -1). Used to initialize capture registers to a non-position. + * - register 0 rbp[-n] (Only positions must be stored in the first + * - register 1 rbp[-n-8] num_saved_registers_ registers) + * - ... + * + * The first num_saved_registers_ registers are initialized to point to + * "character -1" in the string (i.e., char_size() bytes before the first + * character of the string). The remaining registers starts out uninitialized. + * + * The first seven values must be provided by the calling code by + * calling the code's entry address cast to a function pointer with the + * following signature: + * int (*match)(String* input_string, + * Address start, + * Address end, + * int* capture_output_array, + * bool at_start, + * byte* stack_area_base) + */ + +#define __ ACCESS_MASM(masm_) + +RegExpMacroAssemblerX64::RegExpMacroAssemblerX64( + Mode mode, + int registers_to_save) + : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), + code_relative_fixup_positions_(4), + mode_(mode), + num_registers_(registers_to_save), + num_saved_registers_(registers_to_save), + entry_label_(), + start_label_(), + success_label_(), + backtrack_label_(), + exit_label_() { + __ jmp(&entry_label_); // We'll write the entry code when we know more. + __ bind(&start_label_); // And then continue from here. +} + + +RegExpMacroAssemblerX64::~RegExpMacroAssemblerX64() { + delete masm_; + // Unuse labels in case we throw away the assembler without calling GetCode. + entry_label_.Unuse(); + start_label_.Unuse(); + success_label_.Unuse(); + backtrack_label_.Unuse(); + exit_label_.Unuse(); + check_preempt_label_.Unuse(); + stack_overflow_label_.Unuse(); +} + + +int RegExpMacroAssemblerX64::stack_limit_slack() { + return RegExpStack::kStackLimitSlack; +} + + +void RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) { + if (by != 0) { + Label inside_string; + __ addq(rdi, Immediate(by * char_size())); + } +} + + +void RegExpMacroAssemblerX64::AdvanceRegister(int reg, int by) { + ASSERT(reg >= 0); + ASSERT(reg < num_registers_); + if (by != 0) { + __ addq(register_location(reg), Immediate(by)); + } +} + + +void RegExpMacroAssemblerX64::Backtrack() { + CheckPreemption(); + // Pop Code* offset from backtrack stack, add Code* and jump to location. + Pop(rbx); + __ addq(rbx, code_object_pointer()); + __ jmp(rbx); +} + + +void RegExpMacroAssemblerX64::Bind(Label* label) { + __ bind(label); +} + + +void RegExpMacroAssemblerX64::CheckCharacter(uint32_t c, Label* on_equal) { + __ cmpl(current_character(), Immediate(c)); + BranchOrBacktrack(equal, on_equal); +} + + +void RegExpMacroAssemblerX64::CheckCharacterGT(uc16 limit, Label* on_greater) { + __ cmpl(current_character(), Immediate(limit)); + BranchOrBacktrack(greater, on_greater); +} + + +void RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) { + Label not_at_start; + // Did we start the match at the start of the string at all? + __ cmpb(Operand(rbp, kAtStart), Immediate(0)); + BranchOrBacktrack(equal, ¬_at_start); + // If we did, are we still at the start of the input? + __ lea(rax, Operand(rsi, rdi, times_1, 0)); + __ cmpq(rax, Operand(rbp, kInputStart)); + BranchOrBacktrack(equal, on_at_start); + __ bind(¬_at_start); +} + + +void RegExpMacroAssemblerX64::CheckNotAtStart(Label* on_not_at_start) { + // Did we start the match at the start of the string at all? + __ cmpb(Operand(rbp, kAtStart), Immediate(0)); + BranchOrBacktrack(equal, on_not_at_start); + // If we did, are we still at the start of the input? + __ lea(rax, Operand(rsi, rdi, times_1, 0)); + __ cmpq(rax, Operand(rbp, kInputStart)); + BranchOrBacktrack(not_equal, on_not_at_start); +} + + +void RegExpMacroAssemblerX64::CheckCharacterLT(uc16 limit, Label* on_less) { + __ cmpl(current_character(), Immediate(limit)); + BranchOrBacktrack(less, on_less); +} + + +void RegExpMacroAssemblerX64::CheckCharacters(Vector<const uc16> str, + int cp_offset, + Label* on_failure, + bool check_end_of_string) { + int byte_length = str.length() * char_size(); + int byte_offset = cp_offset * char_size(); + if (check_end_of_string) { + // Check that there are at least str.length() characters left in the input. + __ cmpl(rdi, Immediate(-(byte_offset + byte_length))); + BranchOrBacktrack(greater, on_failure); + } + + if (on_failure == NULL) { + // Instead of inlining a backtrack, (re)use the global backtrack target. + on_failure = &backtrack_label_; + } + + // TODO(lrn): Test multiple characters at a time by loading 4 or 8 bytes + // at a time. + for (int i = 0; i < str.length(); i++) { + if (mode_ == ASCII) { + __ cmpb(Operand(rsi, rdi, times_1, byte_offset + i), + Immediate(static_cast<int8_t>(str[i]))); + } else { + ASSERT(mode_ == UC16); + __ cmpw(Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16)), + Immediate(str[i])); + } + BranchOrBacktrack(not_equal, on_failure); + } +} + + +void RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) { + Label fallthrough; + __ cmpl(rdi, Operand(backtrack_stackpointer(), 0)); + __ j(not_equal, &fallthrough); + Drop(); + BranchOrBacktrack(no_condition, on_equal); + __ bind(&fallthrough); +} + + +void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( + int start_reg, + Label* on_no_match) { + Label fallthrough; + __ movq(rdx, register_location(start_reg)); // Offset of start of capture + __ movq(rbx, register_location(start_reg + 1)); // Offset of end of capture + __ subq(rbx, rdx); // Length of capture. + + // ----------------------- + // rdx = Start offset of capture. + // rbx = Length of capture + + // If length is negative, this code will fail (it's a symptom of a partial or + // illegal capture where start of capture after end of capture). + // This must not happen (no back-reference can reference a capture that wasn't + // closed before in the reg-exp, and we must not generate code that can cause + // this condition). + + // If length is zero, either the capture is empty or it is nonparticipating. + // In either case succeed immediately. + __ j(equal, &fallthrough); + + if (mode_ == ASCII) { + Label loop_increment; + if (on_no_match == NULL) { + on_no_match = &backtrack_label_; + } + + __ lea(r9, Operand(rsi, rdx, times_1, 0)); + __ lea(r11, Operand(rsi, rdi, times_1, 0)); + __ addq(rbx, r9); // End of capture + // --------------------- + // r11 - current input character address + // r9 - current capture character address + // rbx - end of capture + + Label loop; + __ bind(&loop); + __ movzxbl(rdx, Operand(r9, 0)); + __ movzxbl(rax, Operand(r11, 0)); + // al - input character + // dl - capture character + __ cmpb(rax, rdx); + __ j(equal, &loop_increment); + + // Mismatch, try case-insensitive match (converting letters to lower-case). + // I.e., if or-ing with 0x20 makes values equal and in range 'a'-'z', it's + // a match. + __ or_(rax, Immediate(0x20)); // Convert match character to lower-case. + __ or_(rdx, Immediate(0x20)); // Convert capture character to lower-case. + __ cmpb(rax, rdx); + __ j(not_equal, on_no_match); // Definitely not equal. + __ subb(rax, Immediate('a')); + __ cmpb(rax, Immediate('z' - 'a')); + __ j(above, on_no_match); // Weren't letters anyway. + + __ bind(&loop_increment); + // Increment pointers into match and capture strings. + __ addq(r11, Immediate(1)); + __ addq(r9, Immediate(1)); + // Compare to end of capture, and loop if not done. + __ cmpq(r9, rbx); + __ j(below, &loop); + + // Compute new value of character position after the matched part. + __ movq(rdi, r11); + __ subq(rdi, rsi); + } else { + ASSERT(mode_ == UC16); + // Save important/volatile registers before calling C function. +#ifndef __MSVC__ + // Callee save on Win64 + __ push(rsi); + __ push(rdi); +#endif + __ push(backtrack_stackpointer()); + + int num_arguments = 3; + FrameAlign(num_arguments); + + // Put arguments into parameter registers. Parameters are + // Address byte_offset1 - Address captured substring's start. + // Address byte_offset2 - Address of current character position. + // size_t byte_length - length of capture in bytes(!) +#ifdef __MSVC__ + // Compute and set byte_offset1 (start of capture). + __ lea(rcx, Operand(rsi, rdx, times_1, 0)); + // Set byte_offset2. + __ lea(rdx, Operand(rsi, rdi, times_1, 0)); + // Set byte_length. + __ movq(r8, rbx); +#else // AMD64 calling convention + // Compute byte_offset2 (current position = rsi+rdi). + __ lea(rax, Operand(rsi, rdi, times_1, 0)); + // Compute and set byte_offset1 (start of capture). + __ lea(rdi, Operand(rsi, rdx, times_1, 0)); + // Set byte_offset2. + __ movq(rsi, rax); + // Set byte_length. + __ movq(rdx, rbx); +#endif + Address function_address = FUNCTION_ADDR(&CaseInsensitiveCompareUC16); + CallCFunction(function_address, num_arguments); + + // Restore original values before reacting on result value. + __ Move(code_object_pointer(), masm_->CodeObject()); + __ pop(backtrack_stackpointer()); +#ifndef __MSVC__ + __ pop(rdi); + __ pop(rsi); +#endif + + // Check if function returned non-zero for success or zero for failure. + __ testq(rax, rax); + BranchOrBacktrack(zero, on_no_match); + // On success, increment position by length of capture. + // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). + __ addq(rdi, rbx); + } + __ bind(&fallthrough); +} + + +void RegExpMacroAssemblerX64::CheckNotBackReference( + int start_reg, + Label* on_no_match) { + Label fallthrough; + + // Find length of back-referenced capture. + __ movq(rdx, register_location(start_reg)); + __ movq(rax, register_location(start_reg + 1)); + __ subq(rax, rdx); // Length to check. + + // Fail on partial or illegal capture (start of capture after end of capture). + // This must not happen (no back-reference can reference a capture that wasn't + // closed before in the reg-exp). + __ Check(greater_equal, "Invalid capture referenced"); + + // Succeed on empty capture (including non-participating capture) + __ j(equal, &fallthrough); + + // ----------------------- + // rdx - Start of capture + // rax - length of capture + + // Check that there are sufficient characters left in the input. + __ movl(rbx, rdi); + __ addl(rbx, rax); + BranchOrBacktrack(greater, on_no_match); + + // Compute pointers to match string and capture string + __ lea(rbx, Operand(rsi, rdi, times_1, 0)); // Start of match. + __ addq(rdx, rsi); // Start of capture. + __ lea(r9, Operand(rdx, rax, times_1, 0)); // End of capture + + // ----------------------- + // rbx - current capture character address. + // rbx - current input character address . + // r9 - end of input to match (capture length after rbx). + + Label loop; + __ bind(&loop); + if (mode_ == ASCII) { + __ movzxbl(rax, Operand(rdx, 0)); + __ cmpb(rax, Operand(rbx, 0)); + } else { + ASSERT(mode_ == UC16); + __ movzxwl(rax, Operand(rdx, 0)); + __ cmpw(rax, Operand(rbx, 0)); + } + BranchOrBacktrack(not_equal, on_no_match); + // Increment pointers into capture and match string. + __ addq(rbx, Immediate(char_size())); + __ addq(rdx, Immediate(char_size())); + // Check if we have reached end of match area. + __ cmpq(rdx, r9); + __ j(below, &loop); + + // Success. + // Set current character position to position after match. + __ movq(rdi, rbx); + __ subq(rdi, rsi); + + __ bind(&fallthrough); +} + + +void RegExpMacroAssemblerX64::CheckNotRegistersEqual(int reg1, + int reg2, + Label* on_not_equal) { + __ movq(rax, register_location(reg1)); + __ cmpq(rax, register_location(reg2)); + BranchOrBacktrack(not_equal, on_not_equal); +} + + +void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, + Label* on_not_equal) { + __ cmpl(current_character(), Immediate(c)); + BranchOrBacktrack(not_equal, on_not_equal); +} + + +void RegExpMacroAssemblerX64::CheckCharacterAfterAnd(uint32_t c, + uint32_t mask, + Label* on_equal) { + __ movl(rax, current_character()); + __ and_(rax, Immediate(mask)); + __ cmpl(rax, Immediate(c)); + BranchOrBacktrack(equal, on_equal); +} + + +void RegExpMacroAssemblerX64::CheckNotCharacterAfterAnd(uint32_t c, + uint32_t mask, + Label* on_not_equal) { + __ movl(rax, current_character()); + __ and_(rax, Immediate(mask)); + __ cmpl(rax, Immediate(c)); + BranchOrBacktrack(not_equal, on_not_equal); +} + + +void RegExpMacroAssemblerX64::CheckNotCharacterAfterMinusAnd( + uc16 c, + uc16 minus, + uc16 mask, + Label* on_not_equal) { + ASSERT(minus < String::kMaxUC16CharCode); + __ lea(rax, Operand(current_character(), -minus)); + __ and_(rax, Immediate(mask)); + __ cmpl(rax, Immediate(c)); + BranchOrBacktrack(not_equal, on_not_equal); +} + + +bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type, + int cp_offset, + bool check_offset, + Label* on_no_match) { + // Range checks (c in min..max) are generally implemented by an unsigned + // (c - min) <= (max - min) check + switch (type) { + case 's': + // Match space-characters + if (mode_ == ASCII) { + // ASCII space characters are '\t'..'\r' and ' '. + if (check_offset) { + LoadCurrentCharacter(cp_offset, on_no_match); + } else { + LoadCurrentCharacterUnchecked(cp_offset, 1); + } + Label success; + __ cmpl(current_character(), Immediate(' ')); + __ j(equal, &success); + // Check range 0x09..0x0d + __ subl(current_character(), Immediate('\t')); + __ cmpl(current_character(), Immediate('\r' - '\t')); + BranchOrBacktrack(above, on_no_match); + __ bind(&success); + return true; + } + return false; + case 'S': + // Match non-space characters. + if (check_offset) { + LoadCurrentCharacter(cp_offset, on_no_match, 1); + } else { + LoadCurrentCharacterUnchecked(cp_offset, 1); + } + if (mode_ == ASCII) { + // ASCII space characters are '\t'..'\r' and ' '. + __ cmpl(current_character(), Immediate(' ')); + BranchOrBacktrack(equal, on_no_match); + __ subl(current_character(), Immediate('\t')); + __ cmpl(current_character(), Immediate('\r' - '\t')); + BranchOrBacktrack(below_equal, on_no_match); + return true; + } + return false; + case 'd': + // Match ASCII digits ('0'..'9') + if (check_offset) { + LoadCurrentCharacter(cp_offset, on_no_match, 1); + } else { + LoadCurrentCharacterUnchecked(cp_offset, 1); + } + __ subl(current_character(), Immediate('0')); + __ cmpl(current_character(), Immediate('9' - '0')); + BranchOrBacktrack(above, on_no_match); + return true; + case 'D': + // Match non ASCII-digits + if (check_offset) { + LoadCurrentCharacter(cp_offset, on_no_match, 1); + } else { + LoadCurrentCharacterUnchecked(cp_offset, 1); + } + __ subl(current_character(), Immediate('0')); + __ cmpl(current_character(), Immediate('9' - '0')); + BranchOrBacktrack(below_equal, on_no_match); + return true; + case '.': { + // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) + if (check_offset) { + LoadCurrentCharacter(cp_offset, on_no_match, 1); + } else { + LoadCurrentCharacterUnchecked(cp_offset, 1); + } + __ xor_(current_character(), Immediate(0x01)); + // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c + __ subl(current_character(), Immediate(0x0b)); + __ cmpl(current_character(), Immediate(0x0c - 0x0b)); + BranchOrBacktrack(below_equal, on_no_match); + if (mode_ == UC16) { + // Compare original value to 0x2028 and 0x2029, using the already + // computed (current_char ^ 0x01 - 0x0b). I.e., check for + // 0x201d (0x2028 - 0x0b) or 0x201e. + __ subl(current_character(), Immediate(0x2028 - 0x0b)); + __ cmpl(current_character(), Immediate(1)); + BranchOrBacktrack(below_equal, on_no_match); + } + return true; + } + case '*': + // Match any character. + if (check_offset) { + CheckPosition(cp_offset, on_no_match); + } + return true; + // No custom implementation (yet): w, W, s(UC16), S(UC16). + default: + return false; + } +} + + +void RegExpMacroAssemblerX64::Fail() { + ASSERT(FAILURE == 0); // Return value for failure is zero. + __ xor_(rax, rax); // zero rax. + __ jmp(&exit_label_); +} + + +Handle<Object> RegExpMacroAssemblerX64::GetCode(Handle<String> source) { + // Finalize code - write the entry point code now we know how many + // registers we need. + + // Entry code: + __ bind(&entry_label_); + // Start new stack frame. + __ push(rbp); + __ movq(rbp, rsp); + // Save parameters and callee-save registers. Order here should correspond + // to order of kBackup_ebx etc. +#ifdef __MSVC__ + // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. + // Store register parameters in pre-allocated stack slots, + __ movq(Operand(rbp, kInputString), rcx); + __ movq(Operand(rbp, kStartIndex), rdx); + __ movq(Operand(rbp, kInputStart), r8); + __ movq(Operand(rbp, kInputEnd), r9); + // Callee-save on Win64. + __ push(rsi); + __ push(rdi); + __ push(rbx); +#else + // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). + // Push register parameters on stack for reference. + ASSERT_EQ(kInputString, -1 * kPointerSize); + ASSERT_EQ(kStartIndex, -2 * kPointerSize); + ASSERT_EQ(kInputStart, -3 * kPointerSize); + ASSERT_EQ(kInputEnd, -4 * kPointerSize); + ASSERT_EQ(kRegisterOutput, -5 * kPointerSize); + ASSERT_EQ(kAtStart, -6 * kPointerSize); + __ push(rdi); + __ push(rsi); + __ push(rdx); + __ push(rcx); + __ push(r8); + __ push(r9); + + __ push(rbx); // Callee-save +#endif + __ push(Immediate(0)); // Make room for "input start - 1" constant. + + // Check if we have space on the stack for registers. + Label stack_limit_hit; + Label stack_ok; + + ExternalReference stack_guard_limit = + ExternalReference::address_of_stack_guard_limit(); + __ movq(rcx, rsp); + __ movq(kScratchRegister, stack_guard_limit); + __ subq(rcx, Operand(kScratchRegister, 0)); + // Handle it if the stack pointer is already below the stack limit. + __ j(below_equal, &stack_limit_hit); + // Check if there is room for the variable number of registers above + // the stack limit. + __ cmpq(rcx, Immediate(num_registers_ * kPointerSize)); + __ j(above_equal, &stack_ok); + // Exit with OutOfMemory exception. There is not enough space on the stack + // for our working registers. + __ movq(rax, Immediate(EXCEPTION)); + __ jmp(&exit_label_); + + __ bind(&stack_limit_hit); + __ Move(code_object_pointer(), masm_->CodeObject()); + CallCheckStackGuardState(); // Preserves no registers beside rbp and rsp. + __ testq(rax, rax); + // If returned value is non-zero, we exit with the returned value as result. + __ j(not_zero, &exit_label_); + + __ bind(&stack_ok); + + // Allocate space on stack for registers. + __ subq(rsp, Immediate(num_registers_ * kPointerSize)); + // Load string length. + __ movq(rsi, Operand(rbp, kInputEnd)); + // Load input position. + __ movq(rdi, Operand(rbp, kInputStart)); + // Set up rdi to be negative offset from string end. + __ subq(rdi, rsi); + // Set rax to address of char before start of input + // (effectively string position -1). + __ lea(rax, Operand(rdi, -char_size())); + // Store this value in a local variable, for use when clearing + // position registers. + __ movq(Operand(rbp, kInputStartMinusOne), rax); + if (num_saved_registers_ > 0) { + // 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). + __ movq(rcx, Immediate(kRegisterZero)); + Label init_loop; + __ bind(&init_loop); + __ movq(Operand(rbp, rcx, times_1, 0), rax); + __ subq(rcx, Immediate(kPointerSize)); + __ cmpq(rcx, + Immediate(kRegisterZero - num_saved_registers_ * kPointerSize)); + __ j(greater, &init_loop); + } + // Ensure that we have written to each stack page, in order. Skipping a page + // on Windows can cause segmentation faults. Assuming page size is 4k. + const int kPageSize = 4096; + const int kRegistersPerPage = kPageSize / kPointerSize; + for (int i = num_saved_registers_ + kRegistersPerPage - 1; + i < num_registers_; + i += kRegistersPerPage) { + __ movq(register_location(i), rax); // One write every page. + } + + // Initialize backtrack stack pointer. + __ movq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); + // Initialize code object pointer. + __ Move(code_object_pointer(), masm_->CodeObject()); + // Load previous char as initial value of current-character. + Label at_start; + __ cmpq(Operand(rbp, kAtStart), Immediate(0)); + __ j(not_equal, &at_start); + LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. + __ jmp(&start_label_); + __ bind(&at_start); + __ movq(current_character(), Immediate('\n')); + __ jmp(&start_label_); + + + // Exit code: + if (success_label_.is_linked()) { + // Save captures when successful. + __ bind(&success_label_); + if (num_saved_registers_ > 0) { + // copy captures to output + __ movq(rbx, Operand(rbp, kRegisterOutput)); + __ movq(rcx, Operand(rbp, kInputEnd)); + __ subq(rcx, Operand(rbp, kInputStart)); + for (int i = 0; i < num_saved_registers_; i++) { + __ movq(rax, register_location(i)); + __ addq(rax, rcx); // Convert to index from start, not end. + if (mode_ == UC16) { + __ sar(rax, Immediate(1)); // Convert byte index to character index. + } + __ movl(Operand(rbx, i * kIntSize), rax); + } + } + __ movq(rax, Immediate(SUCCESS)); + } + + // Exit and return rax + __ bind(&exit_label_); + +#ifdef __MSVC__ + // Restore callee save registers. + __ lea(rsp, Operand(rbp, kLastCalleeSaveRegister)); + __ pop(rbx); + __ pop(rdi); + __ pop(rsi); + // Stack now at rbp. +#else + // Restore callee save register. + __ movq(rbx, Operand(rbp, kBackup_rbx)); + // Skip rsp to rbp. + __ movq(rsp, rbp); +#endif + // Exit function frame, restore previous one. + __ pop(rbp); + __ ret(0); + + // Backtrack code (branch target for conditional backtracks). + if (backtrack_label_.is_linked()) { + __ bind(&backtrack_label_); + Backtrack(); + } + + Label exit_with_exception; + + // Preempt-code + if (check_preempt_label_.is_linked()) { + SafeCallTarget(&check_preempt_label_); + + __ push(backtrack_stackpointer()); + __ push(rdi); + + CallCheckStackGuardState(); + __ testq(rax, rax); + // If returning non-zero, we should end execution with the given + // result as return value. + __ j(not_zero, &exit_label_); + + // Restore registers. + __ Move(code_object_pointer(), masm_->CodeObject()); + __ pop(rdi); + __ pop(backtrack_stackpointer()); + // String might have moved: Reload esi from frame. + __ movq(rsi, Operand(rbp, kInputEnd)); + SafeReturn(); + } + + // Backtrack stack overflow code. + if (stack_overflow_label_.is_linked()) { + SafeCallTarget(&stack_overflow_label_); + // Reached if the backtrack-stack limit has been hit. + + Label grow_failed; + // Save registers before calling C function +#ifndef __MSVC__ + // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. + __ push(rsi); + __ push(rdi); +#endif + + // Call GrowStack(backtrack_stackpointer()) + int num_arguments = 2; + FrameAlign(num_arguments); +#ifdef __MSVC__ + // Microsoft passes parameters in rcx, rdx. + // First argument, backtrack stackpointer, is already in rcx. + __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument +#else + // AMD64 ABI passes paremeters in rdi, rsi. + __ movq(rdi, backtrack_stackpointer()); // First argument. + __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. +#endif + CallCFunction(FUNCTION_ADDR(&GrowStack), num_arguments); + // If return NULL, we have failed to grow the stack, and + // must exit with a stack-overflow exception. + __ testq(rax, rax); + __ j(equal, &exit_with_exception); + // Otherwise use return value as new stack pointer. + __ movq(backtrack_stackpointer(), rax); + // Restore saved registers and continue. + __ Move(code_object_pointer(), masm_->CodeObject()); +#ifndef __MSVC__ + __ pop(rdi); + __ pop(rsi); +#endif + SafeReturn(); + } + + if (exit_with_exception.is_linked()) { + // If any of the code above needed to exit with an exception. + __ bind(&exit_with_exception); + // Exit with Result EXCEPTION(-1) to signal thrown exception. + __ movq(rax, Immediate(EXCEPTION)); + __ jmp(&exit_label_); + } + + FixupCodeRelativePositions(); + + CodeDesc code_desc; + masm_->GetCode(&code_desc); + Handle<Code> code = Factory::NewCode(code_desc, + NULL, + Code::ComputeFlags(Code::REGEXP), + masm_->CodeObject()); + LOG(RegExpCodeCreateEvent(*code, *source)); + return Handle<Object>::cast(code); +} + + +void RegExpMacroAssemblerX64::GoTo(Label* to) { + BranchOrBacktrack(no_condition, to); +} + + +void RegExpMacroAssemblerX64::IfRegisterGE(int reg, + int comparand, + Label* if_ge) { + __ cmpq(register_location(reg), Immediate(comparand)); + BranchOrBacktrack(greater_equal, if_ge); +} + + +void RegExpMacroAssemblerX64::IfRegisterLT(int reg, + int comparand, + Label* if_lt) { + __ cmpq(register_location(reg), Immediate(comparand)); + BranchOrBacktrack(less, if_lt); +} + + +void RegExpMacroAssemblerX64::IfRegisterEqPos(int reg, + Label* if_eq) { + __ cmpq(rdi, register_location(reg)); + BranchOrBacktrack(equal, if_eq); +} + + +RegExpMacroAssembler::IrregexpImplementation + RegExpMacroAssemblerX64::Implementation() { + return kX64Implementation; +} + + +void RegExpMacroAssemblerX64::LoadCurrentCharacter(int cp_offset, + Label* on_end_of_input, + bool check_bounds, + int characters) { + ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. + ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) + CheckPosition(cp_offset + characters - 1, on_end_of_input); + LoadCurrentCharacterUnchecked(cp_offset, characters); +} + + +void RegExpMacroAssemblerX64::PopCurrentPosition() { + Pop(rdi); +} + + +void RegExpMacroAssemblerX64::PopRegister(int register_index) { + Pop(rax); + __ movq(register_location(register_index), rax); +} + + +void RegExpMacroAssemblerX64::PushBacktrack(Label* label) { + Push(label); + CheckStackLimit(); +} + + +void RegExpMacroAssemblerX64::PushCurrentPosition() { + Push(rdi); +} + + +void RegExpMacroAssemblerX64::PushRegister(int register_index, + StackCheckFlag check_stack_limit) { + __ movq(rax, register_location(register_index)); + Push(rax); + if (check_stack_limit) CheckStackLimit(); +} + + +void RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(int reg) { + __ movq(rdi, register_location(reg)); +} + + +void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) { + __ movq(backtrack_stackpointer(), register_location(reg)); + __ addq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); +} + + +void RegExpMacroAssemblerX64::SetRegister(int register_index, int to) { + ASSERT(register_index >= num_saved_registers_); // Reserved for positions! + __ movq(register_location(register_index), Immediate(to)); +} + + +void RegExpMacroAssemblerX64::Succeed() { + __ jmp(&success_label_); +} + + +void RegExpMacroAssemblerX64::WriteCurrentPositionToRegister(int reg, + int cp_offset) { + if (cp_offset == 0) { + __ movq(register_location(reg), rdi); + } else { + __ lea(rax, Operand(rdi, cp_offset * char_size())); + __ movq(register_location(reg), rax); + } +} + + +void RegExpMacroAssemblerX64::ClearRegisters(int reg_from, int reg_to) { + ASSERT(reg_from <= reg_to); + __ movq(rax, Operand(rbp, kInputStartMinusOne)); + for (int reg = reg_from; reg <= reg_to; reg++) { + __ movq(register_location(reg), rax); + } +} + + +void RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) { + __ movq(rax, backtrack_stackpointer()); + __ subq(rax, Operand(rbp, kStackHighEnd)); + __ movq(register_location(reg), rax); +} + + +// Private methods: + +void RegExpMacroAssemblerX64::CallCheckStackGuardState() { + // This function call preserves no register values. Caller should + // store anything volatile in a C call or overwritten by this function. + int num_arguments = 3; + FrameAlign(num_arguments); +#ifdef __MSVC__ + // Second argument: Code* of self. (Do this before overwriting r8). + __ movq(rdx, code_object_pointer()); + // Third argument: RegExp code frame pointer. + __ movq(r8, rbp); + // First argument: Next address on the stack (will be address of + // return address). + __ lea(rcx, Operand(rsp, -kPointerSize)); +#else + // Third argument: RegExp code frame pointer. + __ movq(rdx, rbp); + // Second argument: Code* of self. + __ movq(rsi, code_object_pointer()); + // First argument: Next address on the stack (will be address of + // return address). + __ lea(rdi, Operand(rsp, -kPointerSize)); +#endif + CallCFunction(FUNCTION_ADDR(&CheckStackGuardState), num_arguments); +} + + +// Helper function for reading a value out of a stack frame. +template <typename T> +static T& frame_entry(Address re_frame, int frame_offset) { + return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); +} + + +int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address, + Code* re_code, + Address re_frame) { + if (StackGuard::IsStackOverflow()) { + Top::StackOverflow(); + return EXCEPTION; + } + + // If not real stack overflow the stack guard was used to interrupt + // execution for another purpose. + + // Prepare for possible GC. + HandleScope handles; + Handle<Code> code_handle(re_code); + + Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); + // Current string. + bool is_ascii = subject->IsAsciiRepresentation(); + + ASSERT(re_code->instruction_start() <= *return_address); + ASSERT(*return_address <= + re_code->instruction_start() + re_code->instruction_size()); + + Object* result = Execution::HandleStackGuardInterrupt(); + + if (*code_handle != re_code) { // Return address no longer valid + intptr_t delta = *code_handle - re_code; + // Overwrite the return address on the stack. + *return_address += delta; + } + + if (result->IsException()) { + return EXCEPTION; + } + + // String might have changed. + if (subject->IsAsciiRepresentation() != is_ascii) { + // If we changed between an ASCII and an UC16 string, the specialized + // code cannot be used, and we need to restart regexp matching from + // scratch (including, potentially, compiling a new version of the code). + return RETRY; + } + + // Otherwise, the content of the string might have moved. It must still + // be a sequential or external string with the same content. + // Update the start and end pointers in the stack frame to the current + // location (whether it has actually moved or not). + ASSERT(StringShape(*subject).IsSequential() || + StringShape(*subject).IsExternal()); + + // The original start address of the characters to match. + const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart); + + // Find the current start address of the same character at the current string + // position. + int start_index = frame_entry<int>(re_frame, kStartIndex); + const byte* new_address = StringCharacterPosition(*subject, start_index); + + if (start_address != new_address) { + // If there is a difference, update the object pointer and start and end + // addresses in the RegExp stack frame to match the new value. + const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd); + int byte_length = end_address - start_address; + frame_entry<const String*>(re_frame, kInputString) = *subject; + frame_entry<const byte*>(re_frame, kInputStart) = new_address; + frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length; + } + + return 0; +} + + +Address RegExpMacroAssemblerX64::GrowStack(Address stack_pointer, + Address* stack_base) { + size_t size = RegExpStack::stack_capacity(); + 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_base = new_stack_base; + intptr_t stack_content_size = old_stack_base - stack_pointer; + return new_stack_base - stack_content_size; +} + + +Operand RegExpMacroAssemblerX64::register_location(int register_index) { + ASSERT(register_index < (1<<30)); + if (num_registers_ <= register_index) { + num_registers_ = register_index + 1; + } + return Operand(rbp, kRegisterZero - register_index * kPointerSize); +} + + +void RegExpMacroAssemblerX64::CheckPosition(int cp_offset, + Label* on_outside_input) { + __ cmpl(rdi, Immediate(-cp_offset * char_size())); + BranchOrBacktrack(greater_equal, on_outside_input); +} + + +void RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition, + Label* to) { + if (condition < 0) { // No condition + if (to == NULL) { + Backtrack(); + return; + } + __ jmp(to); + return; + } + if (to == NULL) { + __ j(condition, &backtrack_label_); + return; + } + __ j(condition, to); +} + + +void RegExpMacroAssemblerX64::SafeCall(Label* to) { + __ call(to); +} + + +void RegExpMacroAssemblerX64::SafeCallTarget(Label* label) { + __ bind(label); + __ subq(Operand(rsp, 0), code_object_pointer()); +} + + +void RegExpMacroAssemblerX64::SafeReturn() { + __ addq(Operand(rsp, 0), code_object_pointer()); + __ ret(0); +} + + +void RegExpMacroAssemblerX64::Push(Register source) { + ASSERT(!source.is(backtrack_stackpointer())); + // Notice: This updates flags, unlike normal Push. + __ subq(backtrack_stackpointer(), Immediate(kIntSize)); + __ movl(Operand(backtrack_stackpointer(), 0), source); +} + + +void RegExpMacroAssemblerX64::Push(Immediate value) { + // Notice: This updates flags, unlike normal Push. + __ subq(backtrack_stackpointer(), Immediate(kIntSize)); + __ movl(Operand(backtrack_stackpointer(), 0), value); +} + + +void RegExpMacroAssemblerX64::FixupCodeRelativePositions() { + for (int i = 0, n = code_relative_fixup_positions_.length(); i < n; i++) { + int position = code_relative_fixup_positions_[i]; + // The position succeeds a relative label offset from position. + // Patch the relative offset to be relative to the Code object pointer + // instead. + int patch_position = position - kIntSize; + int offset = masm_->long_at(patch_position); + masm_->long_at_put(patch_position, + offset + + position + + Code::kHeaderSize + - kHeapObjectTag); + } + code_relative_fixup_positions_.Clear(); +} + + +void RegExpMacroAssemblerX64::Push(Label* backtrack_target) { + __ subq(backtrack_stackpointer(), Immediate(kIntSize)); + __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target); + MarkPositionForCodeRelativeFixup(); +} + + +void RegExpMacroAssemblerX64::Pop(Register target) { + ASSERT(!target.is(backtrack_stackpointer())); + __ movsxlq(target, Operand(backtrack_stackpointer(), 0)); + // Notice: This updates flags, unlike normal Pop. + __ addq(backtrack_stackpointer(), Immediate(kIntSize)); +} + + +void RegExpMacroAssemblerX64::Drop() { + __ addq(backtrack_stackpointer(), Immediate(kIntSize)); +} + + +void RegExpMacroAssemblerX64::CheckPreemption() { + // Check for preemption. + Label no_preempt; + ExternalReference stack_guard_limit = + ExternalReference::address_of_stack_guard_limit(); + __ load_rax(stack_guard_limit); + __ cmpq(rsp, rax); + __ j(above, &no_preempt); + + SafeCall(&check_preempt_label_); + + __ bind(&no_preempt); +} + + +void RegExpMacroAssemblerX64::CheckStackLimit() { + if (FLAG_check_stack) { + Label no_stack_overflow; + ExternalReference stack_limit = + ExternalReference::address_of_regexp_stack_limit(); + __ load_rax(stack_limit); + __ cmpq(backtrack_stackpointer(), rax); + __ j(above, &no_stack_overflow); + + SafeCall(&stack_overflow_label_); + + __ bind(&no_stack_overflow); + } +} + + +void RegExpMacroAssemblerX64::FrameAlign(int num_arguments) { + // TODO(lrn): Since we no longer use the system stack arbitrarily (but we do + // use it, e.g., for SafeCall), we know the number of elements on the stack + // since the last frame alignment. We might be able to do this simpler then. + int frameAlignment = OS::ActivationFrameAlignment(); + ASSERT(frameAlignment != 0); + // Make stack end at alignment and make room for num_arguments pointers + // (on Win64 only) and the original value of rsp. + __ movq(kScratchRegister, rsp); + ASSERT(IsPowerOf2(frameAlignment)); +#ifdef __MSVC__ + // Allocate space for parameters and old rsp. + __ subq(rsp, Immediate((num_arguments + 1) * kPointerSize)); + __ and_(rsp, -frameAlignment); + __ movq(Operand(rsp, num_arguments * kPointerSize), kScratchRegister); +#else + // Allocate space for old rsp. + __ subq(rsp, Immediate(kPointerSize)); + __ and_(rsp, Immediate(-frameAlignment)); + __ movq(Operand(rsp, 0), kScratchRegister); +#endif +} + + +void RegExpMacroAssemblerX64::CallCFunction(Address function_address, + int num_arguments) { + // Don't compile regexps with serialization enabled. The addresses of the C++ + // function being called isn't relocatable. + ASSERT(!Serializer::enabled()); + __ movq(rax, reinterpret_cast<intptr_t>(function_address), RelocInfo::NONE); + __ call(rax); + ASSERT(OS::ActivationFrameAlignment() != 0); +#ifdef __MSVC__ + __ movq(rsp, Operand(rsp, num_arguments * kPointerSize)); +#else + __ pop(rsp); +#endif +} + + +void RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(int cp_offset, + int characters) { + if (mode_ == ASCII) { + if (characters == 4) { + __ movl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); + } else if (characters == 2) { + __ movzxwl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); + } else { + ASSERT(characters == 1); + __ movzxbl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); + } + } else { + ASSERT(mode_ == UC16); + if (characters == 2) { + __ movl(current_character(), + Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); + } else { + ASSERT(characters == 1); + __ movzxwl(current_character(), + Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); + } + } +} + + +#undef __ +}} // namespace v8::internal diff --git a/deps/v8/src/x64/regexp-macro-assembler-x64.h b/deps/v8/src/x64/regexp-macro-assembler-x64.h index 209aa2d307..a270bc1865 100644 --- a/deps/v8/src/x64/regexp-macro-assembler-x64.h +++ b/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_ diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status index 9abe408948..68aabb5165 100644 --- a/deps/v8/test/cctest/cctest.status +++ b/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 diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index 35ac031a55..e1caba3c83 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/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); +} diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc index 9e2c38dbee..f5e4f3a4fc 100644 --- a/deps/v8/test/cctest/test-debug.cc +++ b/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()); +} diff --git a/deps/v8/test/cctest/test-decls.cc b/deps/v8/test/cctest/test-decls.cc index 6c48f64f72..f083027d0b 100644 --- a/deps/v8/test/cctest/test-decls.cc +++ b/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())); } diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc index 6b5907c2e8..37dbdd7c60 100644 --- a/deps/v8/test/cctest/test-heap.cc +++ b/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))); } diff --git a/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc index 8d8326ccad..89c7868d83 100644 --- a/deps/v8/test/cctest/test-regexp.cc +++ b/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(¬_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) { diff --git a/deps/v8/test/message/message.status b/deps/v8/test/message/message.status index 9afaa0f148..fc2896b1c9 100644 --- a/deps/v8/test/message/message.status +++ b/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 diff --git a/deps/v8/test/mjsunit/div-mod.js b/deps/v8/test/mjsunit/div-mod.js index 39fab27829..a8a19b30c1 100644 --- a/deps/v8/test/mjsunit/div-mod.js +++ b/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]); } - diff --git a/deps/v8/test/mjsunit/mjsunit.js b/deps/v8/test/mjsunit/mjsunit.js index 2c52a31e60..1fb3f02afb 100644 --- a/deps/v8/test/mjsunit/mjsunit.js +++ b/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)); } } diff --git a/deps/v8/test/mjsunit/mjsunit.status b/deps/v8/test/mjsunit/mjsunit.status index 6853cdc65a..4bf67e80d6 100644 --- a/deps/v8/test/mjsunit/mjsunit.status +++ b/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 diff --git a/deps/v8/test/mjsunit/simple-constructor.js b/deps/v8/test/mjsunit/simple-constructor.js new file mode 100755 index 0000000000..b26d6519b0 --- /dev/null +++ b/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)); diff --git a/deps/v8/test/mjsunit/stack-traces.js b/deps/v8/test/mjsunit/stack-traces.js index 3bb5755aed..d7ece2c6f2 100644 --- a/deps/v8/test/mjsunit/stack-traces.js +++ b/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(); diff --git a/deps/v8/test/mjsunit/tools/logreader.js b/deps/v8/test/mjsunit/tools/logreader.js index dfd7f9f54e..8ed5ffd267 100644 --- a/deps/v8/test/mjsunit/tools/logreader.js +++ b/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'); + }); +})(); diff --git a/deps/v8/test/mjsunit/tools/tickprocessor.js b/deps/v8/test/mjsunit/tools/tickprocessor.js index 00c3fb176b..83bdac8ab8 100644 --- a/deps/v8/test/mjsunit/tools/tickprocessor.js +++ b/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() { }; diff --git a/deps/v8/test/mozilla/mozilla.status b/deps/v8/test/mozilla/mozilla.status index c4628a00b0..a1551dcdd4 100644 --- a/deps/v8/test/mozilla/mozilla.status +++ b/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 diff --git a/deps/v8/tools/gyp/v8.gyp b/deps/v8/tools/gyp/v8.gyp index 365d87cff4..b0c33318fe 100644 --- a/deps/v8/tools/gyp/v8.gyp +++ b/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': [ diff --git a/deps/v8/tools/logreader.js b/deps/v8/tools/logreader.js index 78085a451e..88ab907740 100644 --- a/deps/v8/tools/logreader.js +++ b/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; + } } }; diff --git a/deps/v8/tools/mac-nm b/deps/v8/tools/mac-nm index 9c18177978..07efb07bae 100755 --- a/deps/v8/tools/mac-nm +++ b/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 diff --git a/deps/v8/tools/tickprocessor.js b/deps/v8/tools/tickprocessor.js index 34c6195d9a..72b3059dca 100644 --- a/deps/v8/tools/tickprocessor.js +++ b/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) } : diff --git a/deps/v8/tools/visual_studio/common.vsprops b/deps/v8/tools/visual_studio/common.vsprops index f131a4a0ca..d23e4fcfe8 100644 --- a/deps/v8/tools/visual_studio/common.vsprops +++ b/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" diff --git a/deps/v8/tools/visual_studio/d8_x64.vcproj b/deps/v8/tools/visual_studio/d8_x64.vcproj new file mode 100644 index 0000000000..dd2b83d06e --- /dev/null +++ b/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 "$(IntDir)\DerivedSources"" + 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 "$(IntDir)\DerivedSources"" + 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> diff --git a/deps/v8/tools/visual_studio/ia32.vsprops b/deps/v8/tools/visual_studio/ia32.vsprops index aff08716fd..f48e808d84 100644 --- a/deps/v8/tools/visual_studio/ia32.vsprops +++ b/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> diff --git a/deps/v8/tools/visual_studio/v8_base_x64.vcproj b/deps/v8/tools/visual_studio/v8_base_x64.vcproj new file mode 100644 index 0000000000..1e27824629 --- /dev/null +++ b/deps/v8/tools/visual_studio/v8_base_x64.vcproj @@ -0,0 +1,963 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="v8_base" + ProjectGUID="{EC8B7909-62AF-470D-A75D-E1D89C837142}" + RootNamespace="v8_base" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="x64" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|x64" + ConfigurationType="4" + 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="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|x64" + ConfigurationType="4" + 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="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="dtoa" + > + <File + RelativePath="..\..\src\dtoa-config.c" + > + <FileConfiguration + Name="Debug|x64" + > + <Tool + Name="VCCLCompilerTool" + DisableSpecificWarnings="4018;4244" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|x64" + > + <Tool + Name="VCCLCompilerTool" + DisableSpecificWarnings="4018;4244" + /> + </FileConfiguration> + </File> + </Filter> + <Filter + Name="src" + > + <File + RelativePath="..\..\src\accessors.cc" + > + </File> + <File + RelativePath="..\..\src\accessors.h" + > + </File> + <File + RelativePath="..\..\src\allocation.cc" + > + </File> + <File + RelativePath="..\..\src\allocation.h" + > + </File> + <File + RelativePath="..\..\src\api.cc" + > + </File> + <File + RelativePath="..\..\src\api.h" + > + </File> + <File + RelativePath="..\..\src\arguments.h" + > + </File> + <File + RelativePath="..\..\src\x64\assembler-x64-inl.h" + > + </File> + <File + RelativePath="..\..\src\x64\assembler-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\assembler-x64.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp-inl.h" + > + </File> + <File + RelativePath="..\..\src\regexp-stack.h" + > + </File> + <File + RelativePath="..\..\src\assembler.cc" + > + </File> + <File + RelativePath="..\..\src\assembler.h" + > + </File> + <File + RelativePath="..\..\src\ast.cc" + > + </File> + <File + RelativePath="..\..\src\ast.h" + > + </File> + <File + RelativePath="..\..\src\bootstrapper.cc" + > + </File> + <File + RelativePath="..\..\src\bootstrapper.h" + > + </File> + <File + RelativePath="..\..\src\x64\builtins-x64.cc" + > + </File> + <File + RelativePath="..\..\src\builtins.cc" + > + </File> + <File + RelativePath="..\..\src\builtins.h" + > + </File> + <File + RelativePath="..\..\src\bytecodes-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\x64\cfg-x64.cc" + > + </File> + <File + RelativePath="..\..\src\cfg.cc" + > + </File> + <File + RelativePath="..\..\src\cfg.h" + > + </File> + <File + RelativePath="..\..\src\char-predicates-inl.h" + > + </File> + <File + RelativePath="..\..\src\char-predicates.h" + > + </File> + <File + RelativePath="..\..\src\checks.cc" + > + </File> + <File + RelativePath="..\..\src\checks.h" + > + </File> + <File + RelativePath="..\..\src\code-stubs.cc" + > + </File> + <File + RelativePath="..\..\src\code-stubs.h" + > + </File> + <File + RelativePath="..\..\src\code.h" + > + </File> + <File + RelativePath="..\..\src\x64\codegen-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\codegen-x64.h" + > + </File> + <File + RelativePath="..\..\src\codegen-inl.h" + > + </File> + <File + RelativePath="..\..\src\codegen.cc" + > + </File> + <File + RelativePath="..\..\src\codegen.h" + > + </File> + <File + RelativePath="..\..\src\compilation-cache.cc" + > + </File> + <File + RelativePath="..\..\src\compilation-cache.h" + > + </File> + <File + RelativePath="..\..\src\compiler.cc" + > + </File> + <File + RelativePath="..\..\src\compiler.h" + > + </File> + <File + RelativePath="..\..\src\contexts.cc" + > + </File> + <File + RelativePath="..\..\src\contexts.h" + > + </File> + <File + RelativePath="..\..\src\conversions-inl.h" + > + </File> + <File + RelativePath="..\..\src\conversions.cc" + > + </File> + <File + RelativePath="..\..\src\conversions.h" + > + </File> + <File + RelativePath="..\..\src\counters.cc" + > + </File> + <File + RelativePath="..\..\src\counters.h" + > + </File> + <File + RelativePath="..\..\src\x64\cpu-x64.cc" + > + </File> + <File + RelativePath="..\..\src\cpu.h" + > + </File> + <File + RelativePath="..\..\src\dateparser.cc" + > + </File> + <File + RelativePath="..\..\src\dateparser.h" + > + </File> + <File + RelativePath="..\..\src\debug-agent.cc" + > + </File> + <File + RelativePath="..\..\src\debug-agent.h" + > + </File> + <File + RelativePath="..\..\src\x64\debug-x64.cc" + > + </File> + <File + RelativePath="..\..\src\debug.cc" + > + </File> + <File + RelativePath="..\..\src\debug.h" + > + </File> + <File + RelativePath="..\..\src\disassembler.cc" + > + </File> + <File + RelativePath="..\..\src\disassembler.h" + > + </File> + <File + RelativePath="..\..\src\execution.cc" + > + </File> + <File + RelativePath="..\..\src\execution.h" + > + </File> + <File + RelativePath="..\..\src\factory.cc" + > + </File> + <File + RelativePath="..\..\src\factory.h" + > + </File> + <File + RelativePath="..\..\src\flags.cc" + > + </File> + <File + RelativePath="..\..\src\flags.h" + > + </File> + <File + RelativePath="..\..\src\frame-element.cc" + > + </File> + <File + RelativePath="..\..\src\frame-element.h" + > + </File> + <File + RelativePath="..\..\src\x64\frames-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\frames-x64.h" + > + </File> + <File + RelativePath="..\..\src\frames-inl.h" + > + </File> + <File + RelativePath="..\..\src\frames.cc" + > + </File> + <File + RelativePath="..\..\src\frames.h" + > + </File> + <File + RelativePath="..\..\src\func-name-inferrer.cc" + > + </File> + <File + RelativePath="..\..\src\func-name-inferrer.h" + > + </File> + <File + RelativePath="..\..\src\global-handles.cc" + > + </File> + <File + RelativePath="..\..\src\global-handles.h" + > + </File> + <File + RelativePath="..\..\src\globals.h" + > + </File> + <File + RelativePath="..\..\src\handles-inl.h" + > + </File> + <File + RelativePath="..\..\src\handles.cc" + > + </File> + <File + RelativePath="..\..\src\handles.h" + > + </File> + <File + RelativePath="..\..\src\hashmap.cc" + > + </File> + <File + RelativePath="..\..\src\hashmap.h" + > + </File> + <File + RelativePath="..\..\src\heap-inl.h" + > + </File> + <File + RelativePath="..\..\src\heap.cc" + > + </File> + <File + RelativePath="..\..\src\heap.h" + > + </File> + <File + RelativePath="..\..\src\x64\ic-x64.cc" + > + </File> + <File + RelativePath="..\..\src\ic-inl.h" + > + </File> + <File + RelativePath="..\..\src\ic.cc" + > + </File> + <File + RelativePath="..\..\src\ic.h" + > + </File> + <File + RelativePath="..\..\src\interceptors.h" + > + </File> + <File + RelativePath="..\..\src\interpreter-irregexp.cc" + > + </File> + <File + RelativePath="..\..\src\interpreter-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\jump-target.h" + > + </File> + <File + RelativePath="..\..\src\jump-target-inl.h" + > + </File> + <File + RelativePath="..\..\src\jump-target.cc" + > + </File> + <File + RelativePath="..\..\src\x64\jump-target-x64.cc" + > + </File> + <File + RelativePath="..\..\src\jsregexp.cc" + > + </File> + <File + RelativePath="..\..\src\jsregexp.h" + > + </File> + <File + RelativePath="..\..\src\list-inl.h" + > + </File> + <File + RelativePath="..\..\src\list.h" + > + </File> + <File + RelativePath="..\..\src\log.cc" + > + </File> + <File + RelativePath="..\..\src\log-inl.h" + > + </File> + <File + RelativePath="..\..\src\log.h" + > + </File> + <File + RelativePath="..\..\src\log-utils.cc" + > + </File> + <File + RelativePath="..\..\src\log-utils.h" + > + </File> + <File + RelativePath="..\..\src\x64\macro-assembler-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\macro-assembler-x64.h" + > + </File> + <File + RelativePath="..\..\src\macro-assembler.h" + > + </File> + <File + RelativePath="..\..\src\mark-compact.cc" + > + </File> + <File + RelativePath="..\..\src\mark-compact.h" + > + </File> + <File + RelativePath="..\..\src\memory.h" + > + </File> + <File + RelativePath="..\..\src\messages.cc" + > + </File> + <File + RelativePath="..\..\src\messages.h" + > + </File> + <File + RelativePath="..\..\src\natives.h" + > + </File> + <File + RelativePath="..\..\src\objects-debug.cc" + > + <FileConfiguration + Name="Release|x64" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\objects-inl.h" + > + </File> + <File + RelativePath="..\..\src\objects.cc" + > + </File> + <File + RelativePath="..\..\src\objects.h" + > + </File> + <File + RelativePath="..\..\src\oprofile-agent.cc" + > + </File> + <File + RelativePath="..\..\src\oprofile-agent.h" + > + </File> + <File + RelativePath="..\..\src\parser.cc" + > + </File> + <File + RelativePath="..\..\src\parser.h" + > + </File> + <File + RelativePath="..\..\src\platform-win32.cc" + > + </File> + <File + RelativePath="..\..\src\platform.h" + > + </File> + <File + RelativePath="..\..\src\prettyprinter.cc" + > + <FileConfiguration + Name="Release|x64" + ExcludedFromBuild="true" + > + <Tool + Name="VCCLCompilerTool" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\src\prettyprinter.h" + > + </File> + <File + RelativePath="..\..\src\property.cc" + > + </File> + <File + RelativePath="..\..\src\property.h" + > + </File> + <File + RelativePath="..\..\src\x64\regexp-macro-assembler-x64.cc" + > + </File> + <File + RelativePath="..\..\src\x64\regexp-macro-assembler-x64.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-irregexp.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler.h" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-tracer.cc" + > + </File> + <File + RelativePath="..\..\src\regexp-macro-assembler-tracer.h" + > + </File> + <File + RelativePath="..\..\src\regexp-stack.cc" + > + </File> + <File + RelativePath="..\..\src\register-allocator.h" + > + </File> + <File + RelativePath="..\..\src\register-allocator.cc" + > + </File> + <File + RelativePath="..\..\src\x64\register-allocator-x64.cc" + > + </File> + <File + RelativePath="..\..\src\rewriter.cc" + > + </File> + <File + RelativePath="..\..\src\rewriter.h" + > + </File> + <File + RelativePath="..\..\src\runtime.cc" + > + </File> + <File + RelativePath="..\..\src\runtime.h" + > + </File> + <File + RelativePath="..\..\src\scanner.cc" + > + </File> + <File + RelativePath="..\..\src\scanner.h" + > + </File> + <File + RelativePath="..\..\src\scopeinfo.cc" + > + </File> + <File + RelativePath="..\..\src\scopeinfo.h" + > + </File> + <File + RelativePath="..\..\src\scopes.cc" + > + </File> + <File + RelativePath="..\..\src\scopes.h" + > + </File> + <File + RelativePath="..\..\src\serialize.cc" + > + </File> + <File + RelativePath="..\..\src\serialize.h" + > + </File> + <File + RelativePath="..\..\src\shell.h" + > + </File> + <File + RelativePath="..\..\src\snapshot-common.cc" + > + </File> + <File + RelativePath="..\..\src\snapshot.h" + > + </File> + <File + RelativePath="..\..\src\spaces-inl.h" + > + </File> + <File + RelativePath="..\..\src\spaces.cc" + > + </File> + <File + RelativePath="..\..\src\spaces.h" + > + </File> + <File + RelativePath="..\..\src\string-stream.cc" + > + </File> + <File + RelativePath="..\..\src\string-stream.h" + > + </File> + <File + RelativePath="..\..\src\x64\stub-cache-x64.cc" + > + </File> + <File + RelativePath="..\..\src\stub-cache.cc" + > + </File> + <File + RelativePath="..\..\src\stub-cache.h" + > + </File> + <File + RelativePath="..\..\src\token.cc" + > + </File> + <File + RelativePath="..\..\src\token.h" + > + </File> + <File + RelativePath="..\..\src\top.cc" + > + </File> + <File + RelativePath="..\..\src\top.h" + > + </File> + <File + RelativePath="..\..\src\unicode-inl.h" + > + </File> + <File + RelativePath="..\..\src\unicode.h" + > + </File> + <File + RelativePath="..\..\src\usage-analyzer.cc" + > + </File> + <File + RelativePath="..\..\src\usage-analyzer.h" + > + </File> + <File + RelativePath="..\..\src\utils.cc" + > + </File> + <File + RelativePath="..\..\src\utils.h" + > + </File> + <File + RelativePath="..\..\src\v8-counters.cc" + > + </File> + <File + RelativePath="..\..\src\v8-counters.h" + > + </File> + <File + RelativePath="..\..\src\v8.cc" + > + </File> + <File + RelativePath="..\..\src\v8.h" + > + </File> + <File + RelativePath="..\..\src\v8threads.cc" + > + </File> + <File + RelativePath="..\..\src\v8threads.h" + > + </File> + <File + RelativePath="..\..\src\variables.cc" + > + </File> + <File + RelativePath="..\..\src\variables.h" + > + </File> + <File + RelativePath="..\..\src\version.cc" + > + </File> + <File + RelativePath="..\..\src\version.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame.h" + > + </File> + <File + RelativePath="..\..\src\x64\virtual-frame-x64.h" + > + </File> + <File + RelativePath="..\..\src\virtual-frame.cc" + > + </File> + <File + RelativePath="..\..\src\x64\virtual-frame-x64.cc" + > + </File> + <File + RelativePath="..\..\src\zone-inl.h" + > + </File> + <File + RelativePath="..\..\src\zone.cc" + > + </File> + <File + RelativePath="..\..\src\zone.h" + > + </File> + <Filter + Name="third party" + > + <File + RelativePath="..\..\src\x64\disasm-x64.cc" + > + </File> + <File + RelativePath="..\..\src\disasm.h" + > + </File> + </Filter> + <Filter + Name="generated files" + > + <File + RelativePath="..\..\src\unicode.cc" + > + </File> + </Filter> + </Filter> + <Filter + Name="include" + > + <File + RelativePath="..\..\include\debug.h" + > + </File> + <File + RelativePath="..\..\include\v8.h" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_cctest_x64.vcproj b/deps/v8/tools/visual_studio/v8_cctest_x64.vcproj new file mode 100644 index 0000000000..fc7ac4be8b --- /dev/null +++ b/deps/v8/tools/visual_studio/v8_cctest_x64.vcproj @@ -0,0 +1,251 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="v8_cctest" + ProjectGUID="{97ECC711-7430-4FC4-90FD-004DA880E72A}" + RootNamespace="v8_cctest" + 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="..\..\test\cctest\cctest.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-alloc.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-api.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-assembler-x64.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-ast.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-compiler.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-conversions.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-debug.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-decls.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-disasm-x64.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-flags.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-func-name-inference.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-hashmap.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-heap.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-lock.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-log.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-log-utils.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-log-stack-tracer.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-mark-compact.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-platform-win32.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-serialize.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-sockets.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-spaces.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-strings.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-utils.cc" + > + </File> + <File + RelativePath="..\..\test\cctest\test-version.cc" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_mksnapshot_x64.vcproj b/deps/v8/tools/visual_studio/v8_mksnapshot_x64.vcproj new file mode 100644 index 0000000000..1c460e4db6 --- /dev/null +++ b/deps/v8/tools/visual_studio/v8_mksnapshot_x64.vcproj @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="v8_mksnapshot" + ProjectGUID="{865575D0-37E2-405E-8CBA-5F6C485B5A26}" + RootNamespace="v8_mksnapshot" + 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\mksnapshot.cc" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_process_sample_x64.vcproj b/deps/v8/tools/visual_studio/v8_process_sample_x64.vcproj new file mode 100644 index 0000000000..81adbe0fb4 --- /dev/null +++ b/deps/v8/tools/visual_studio/v8_process_sample_x64.vcproj @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="v8_process_sample" + ProjectGUID="{EF019874-D38A-40E3-B17C-DB5923F0A79C}" + RootNamespace="v8_process_sample" + 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="..\..\samples\process.cc" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_shell_sample_x64.vcproj b/deps/v8/tools/visual_studio/v8_shell_sample_x64.vcproj new file mode 100644 index 0000000000..ab276f4876 --- /dev/null +++ b/deps/v8/tools/visual_studio/v8_shell_sample_x64.vcproj @@ -0,0 +1,151 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="v8_shell_sample" + ProjectGUID="{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}" + RootNamespace="v8_shell_sample" + 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="..\..\samples\shell.cc" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_snapshot_cc_x64.vcproj b/deps/v8/tools/visual_studio/v8_snapshot_cc_x64.vcproj new file mode 100644 index 0000000000..9c6f9d2f00 --- /dev/null +++ b/deps/v8/tools/visual_studio/v8_snapshot_cc_x64.vcproj @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="v8_snapshot_cc" + ProjectGUID="{0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}" + RootNamespace="v8_snapshot_cc" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="x64" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|x64" + ConfigurationType="10" + InheritedPropertySheets=".\common.vsprops;.\x64.vsprops;.\debug.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|x64" + ConfigurationType="10" + InheritedPropertySheets=".\common.vsprops;.\x64.vsprops;.\release.vsprops" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="generated files" + SourceControlFiles="false" + > + <File + RelativePath="$(OutDir)\v8_mksnapshot.exe" + > + <FileConfiguration + Name="Debug|x64" + > + <Tool + Name="VCCustomBuildTool" + Description="Building snapshot..." + CommandLine=""$(OutDir)\v8_mksnapshot.exe" "$(IntDir)\DerivedSources\snapshot.cc"
" + AdditionalDependencies="$(OutDir)\v8_mksnapshot.exe" + Outputs="$(IntDir)\DerivedSources\snapshot.cc" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|x64" + > + <Tool + Name="VCCustomBuildTool" + Description="Building snapshot..." + CommandLine=""$(OutDir)\v8_mksnapshot.exe" "$(IntDir)\DerivedSources\snapshot.cc"
" + AdditionalDependencies="$(OutDir)\v8_mksnapshot.exe" + Outputs="$(IntDir)\DerivedSources\snapshot.cc" + /> + </FileConfiguration> + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_snapshot_x64.vcproj b/deps/v8/tools/visual_studio/v8_snapshot_x64.vcproj new file mode 100644 index 0000000000..0f6c70faf9 --- /dev/null +++ b/deps/v8/tools/visual_studio/v8_snapshot_x64.vcproj @@ -0,0 +1,142 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="v8_snapshot" + ProjectGUID="{C0334F9A-1168-4101-9DD8-C30FB252D435}" + RootNamespace="v8_snapshot" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="x64" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|x64" + ConfigurationType="4" + 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="VCLibrarianTool" + LinkLibraryDependencies="true" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|x64" + ConfigurationType="4" + 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="VCLibrarianTool" + LinkLibraryDependencies="true" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="generated files" + SourceControlFiles="false" + > + <File + RelativePath="$(IntDir)\..\v8\DerivedSources\natives-empty.cc" + > + </File> + <File + RelativePath="$(IntDir)\..\v8_snapshot_cc\DerivedSources\snapshot.cc" + > + </File> + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/v8_x64.sln b/deps/v8/tools/visual_studio/v8_x64.sln new file mode 100644 index 0000000000..1fa2f16cb7 --- /dev/null +++ b/deps/v8/tools/visual_studio/v8_x64.sln @@ -0,0 +1,101 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_base", "v8_base_x64.vcproj", "{EC8B7909-62AF-470D-A75D-E1D89C837142}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8", "v8_x64.vcproj", "{21E22961-22BF-4493-BD3A-868F93DA5179}" + ProjectSection(ProjectDependencies) = postProject + {EC8B7909-62AF-470D-A75D-E1D89C837142} = {EC8B7909-62AF-470D-A75D-E1D89C837142} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_mksnapshot", "v8_mksnapshot_x64.vcproj", "{865575D0-37E2-405E-8CBA-5F6C485B5A26}" + ProjectSection(ProjectDependencies) = postProject + {21E22961-22BF-4493-BD3A-868F93DA5179} = {21E22961-22BF-4493-BD3A-868F93DA5179} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_snapshot", "v8_snapshot_x64.vcproj", "{C0334F9A-1168-4101-9DD8-C30FB252D435}" + ProjectSection(ProjectDependencies) = postProject + {0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F} = {0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F} + {EC8B7909-62AF-470D-A75D-E1D89C837142} = {EC8B7909-62AF-470D-A75D-E1D89C837142} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_shell_sample", "v8_shell_sample_x64.vcproj", "{2DE20FFA-6F5E-48D9-84D8-09B044A5B119}" + ProjectSection(ProjectDependencies) = postProject + {C0334F9A-1168-4101-9DD8-C30FB252D435} = {C0334F9A-1168-4101-9DD8-C30FB252D435} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E131F77D-B713-48F3-B86D-097ECDCC4C3A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_process_sample", "v8_process_sample_x64.vcproj", "{EF019874-D38A-40E3-B17C-DB5923F0A79C}" + ProjectSection(ProjectDependencies) = postProject + {C0334F9A-1168-4101-9DD8-C30FB252D435} = {C0334F9A-1168-4101-9DD8-C30FB252D435} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_cctest", "v8_cctest_x64.vcproj", "{97ECC711-7430-4FC4-90FD-004DA880E72A}" + ProjectSection(ProjectDependencies) = postProject + {C0334F9A-1168-4101-9DD8-C30FB252D435} = {C0334F9A-1168-4101-9DD8-C30FB252D435} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{AD933CE2-1303-448E-89C8-60B1FDD18EC3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d8", "d8_x64.vcproj", "{7E4C7D2D-A4B9-40B9-8192-22654E626F6C}" + ProjectSection(ProjectDependencies) = postProject + {C0334F9A-1168-4101-9DD8-C30FB252D435} = {C0334F9A-1168-4101-9DD8-C30FB252D435} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "v8_snapshot_cc", "v8_snapshot_cc_x64.vcproj", "{0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}" + ProjectSection(ProjectDependencies) = postProject + {865575D0-37E2-405E-8CBA-5F6C485B5A26} = {865575D0-37E2-405E-8CBA-5F6C485B5A26} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}.Debug|x64.ActiveCfg = Debug|x64 + {0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}.Debug|x64.Build.0 = Debug|x64 + {0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}.Release|x64.ActiveCfg = Release|x64 + {0DDBDA8B-A49F-4CC7-A1D5-5BB8297C8A3F}.Release|x64.Build.0 = Release|x64 + {21E22961-22BF-4493-BD3A-868F93DA5179}.Debug|x64.ActiveCfg = Debug|x64 + {21E22961-22BF-4493-BD3A-868F93DA5179}.Debug|x64.Build.0 = Debug|x64 + {21E22961-22BF-4493-BD3A-868F93DA5179}.Release|x64.ActiveCfg = Release|x64 + {21E22961-22BF-4493-BD3A-868F93DA5179}.Release|x64.Build.0 = Release|x64 + {2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Debug|x64.ActiveCfg = Debug|x64 + {2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Debug|x64.Build.0 = Debug|x64 + {2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Release|x64.ActiveCfg = Release|x64 + {2DE20FFA-6F5E-48D9-84D8-09B044A5B119}.Release|x64.Build.0 = Release|x64 + {7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Debug|x64.ActiveCfg = Debug|x64 + {7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Debug|x64.Build.0 = Debug|x64 + {7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Release|x64.ActiveCfg = Release|x64 + {7E4C7D2D-A4B9-40B9-8192-22654E626F6C}.Release|x64.Build.0 = Release|x64 + {865575D0-37E2-405E-8CBA-5F6C485B5A26}.Debug|x64.ActiveCfg = Debug|x64 + {865575D0-37E2-405E-8CBA-5F6C485B5A26}.Debug|x64.Build.0 = Debug|x64 + {865575D0-37E2-405E-8CBA-5F6C485B5A26}.Release|x64.ActiveCfg = Release|x64 + {865575D0-37E2-405E-8CBA-5F6C485B5A26}.Release|x64.Build.0 = Release|x64 + {97ECC711-7430-4FC4-90FD-004DA880E72A}.Debug|x64.ActiveCfg = Debug|x64 + {97ECC711-7430-4FC4-90FD-004DA880E72A}.Debug|x64.Build.0 = Debug|x64 + {97ECC711-7430-4FC4-90FD-004DA880E72A}.Release|x64.ActiveCfg = Release|x64 + {97ECC711-7430-4FC4-90FD-004DA880E72A}.Release|x64.Build.0 = Release|x64 + {C0334F9A-1168-4101-9DD8-C30FB252D435}.Debug|x64.ActiveCfg = Debug|x64 + {C0334F9A-1168-4101-9DD8-C30FB252D435}.Debug|x64.Build.0 = Debug|x64 + {C0334F9A-1168-4101-9DD8-C30FB252D435}.Release|x64.ActiveCfg = Release|x64 + {C0334F9A-1168-4101-9DD8-C30FB252D435}.Release|x64.Build.0 = Release|x64 + {EC8B7909-62AF-470D-A75D-E1D89C837142}.Debug|x64.ActiveCfg = Debug|x64 + {EC8B7909-62AF-470D-A75D-E1D89C837142}.Debug|x64.Build.0 = Debug|x64 + {EC8B7909-62AF-470D-A75D-E1D89C837142}.Release|x64.ActiveCfg = Release|x64 + {EC8B7909-62AF-470D-A75D-E1D89C837142}.Release|x64.Build.0 = Release|x64 + {EF019874-D38A-40E3-B17C-DB5923F0A79C}.Debug|x64.ActiveCfg = Debug|x64 + {EF019874-D38A-40E3-B17C-DB5923F0A79C}.Debug|x64.Build.0 = Debug|x64 + {EF019874-D38A-40E3-B17C-DB5923F0A79C}.Release|x64.ActiveCfg = Release|x64 + {EF019874-D38A-40E3-B17C-DB5923F0A79C}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {2DE20FFA-6F5E-48D9-84D8-09B044A5B119} = {E131F77D-B713-48F3-B86D-097ECDCC4C3A} + {97ECC711-7430-4FC4-90FD-004DA880E72A} = {AD933CE2-1303-448E-89C8-60B1FDD18EC3} + {EF019874-D38A-40E3-B17C-DB5923F0A79C} = {E131F77D-B713-48F3-B86D-097ECDCC4C3A} + EndGlobalSection +EndGlobal diff --git a/deps/v8/tools/visual_studio/v8_x64.vcproj b/deps/v8/tools/visual_studio/v8_x64.vcproj new file mode 100644 index 0000000000..cbf88c918d --- /dev/null +++ b/deps/v8/tools/visual_studio/v8_x64.vcproj @@ -0,0 +1,223 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="v8" + ProjectGUID="{21E22961-22BF-4493-BD3A-868F93DA5179}" + RootNamespace="v8" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="x64" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|x64" + ConfigurationType="4" + 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="VCLibrarianTool" + LinkLibraryDependencies="true" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|x64" + ConfigurationType="4" + 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="VCLibrarianTool" + LinkLibraryDependencies="true" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="js" + > + <File + RelativePath="..\..\src\apinatives.js" + > + </File> + <File + RelativePath="..\..\src\array.js" + > + </File> + <File + RelativePath="..\..\src\date-delay.js" + > + </File> + <File + RelativePath="..\..\src\debug-delay.js" + > + </File> + <File + RelativePath="..\..\src\macros.py" + > + </File> + <File + RelativePath="..\..\src\math.js" + > + </File> + <File + RelativePath="..\..\src\messages.js" + > + </File> + <File + RelativePath="..\..\src\mirror-delay.js" + > + </File> + <File + RelativePath="..\..\src\regexp-delay.js" + > + </File> + <File + RelativePath="..\..\src\json-delay.js" + > + </File> + <File + RelativePath="..\..\src\runtime.js" + > + </File> + <File + RelativePath="..\..\src\string.js" + > + </File> + <File + RelativePath="..\..\src\uri.js" + > + </File> + <File + RelativePath="..\..\src\v8natives.js" + > + <FileConfiguration + Name="Debug|x64" + > + <Tool + Name="VCCustomBuildTool" + Description="Processing js files..." + CommandLine=".\js2c.cmd ..\..\src "$(IntDir)\DerivedSources"" + AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js;..\..\src\json-delay.js" + Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|x64" + > + <Tool + Name="VCCustomBuildTool" + Description="Processing js files..." + CommandLine=".\js2c.cmd ..\..\src "$(IntDir)\DerivedSources"" + AdditionalDependencies="..\..\src\macros.py;..\..\src\runtime.js;..\..\src\v8natives.js;..\..\src\array.js;..\..\src\string.js;..\..\src\uri.js;..\..\src\math.js;..\..\src\messages.js;..\..\src\apinatives.js;..\..\src\debug-delay.js;..\..\src\mirror-delay.js;..\..\src\date-delay.js;..\..\src\regexp-delay.js;..\..\src\json-delay.js" + Outputs="$(IntDir)\DerivedSources\natives.cc;$(IntDir)\DerivedSources\natives-empty.cc" + /> + </FileConfiguration> + </File> + </Filter> + <Filter + Name="generated files" + > + <File + RelativePath="$(IntDir)\DerivedSources\natives.cc" + > + </File> + </Filter> + <File + RelativePath="..\..\src\snapshot-empty.cc" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/deps/v8/tools/visual_studio/x64.vsprops b/deps/v8/tools/visual_studio/x64.vsprops new file mode 100644 index 0000000000..af0e47c4b6 --- /dev/null +++ b/deps/v8/tools/visual_studio/x64.vsprops @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioPropertySheet + ProjectType="Visual C++" + Version="8.00" + Name="x64" + > + <Tool + Name="VCCLCompilerTool" + PreprocessorDefinitions="V8_TARGET_ARCH_X64;V8_NATIVE_REGEXP" + /> +</VisualStudioPropertySheet> |