diff --git a/deps/http_parser/Makefile b/deps/http_parser/Makefile index 0636bd0b28..42f643cc9e 100644 --- a/deps/http_parser/Makefile +++ b/deps/http_parser/Makefile @@ -1,5 +1,5 @@ -OPT_DEBUG=-O0 -g -Wall -Wextra -Werror -OPT_FAST=-O3 -DHTTP_PARSER_STRICT=0 +OPT_DEBUG=-O0 -g -Wall -Wextra -Werror -I. +OPT_FAST=-O3 -DHTTP_PARSER_STRICT=0 -I. test: test_debug diff --git a/deps/http_parser/http_parser.c b/deps/http_parser/http_parser.c index 95afa18142..36257fd013 100644 --- a/deps/http_parser/http_parser.c +++ b/deps/http_parser/http_parser.c @@ -106,11 +106,10 @@ static inline int message_complete_callback (http_parser *parser) #define KEEP_ALIVE "keep-alive" #define CLOSE "close" - static const unsigned char lowcase[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0-\0\0" "0123456789\0\0\0\0\0\0" - "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0" + "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0_" "\0abcdefghijklmnopqrstuvwxyz\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" @@ -199,7 +198,10 @@ enum state , s_header_almost_done , s_headers_almost_done - + /* Important: 's_headers_almost_done' must be the last 'header' state. All + * states beyond this must be 'body' states. It is used for overflow + * checking. See the PARSING_HEADER() macro. + */ , s_chunk_size_start , s_chunk_size , s_chunk_size_almost_done @@ -212,6 +214,8 @@ enum state , s_body_identity_eof }; +#define PARSING_HEADER(state) (state <= s_headers_almost_done) + enum header_states { h_general = 0 , h_C @@ -262,12 +266,13 @@ size_t http_parser_execute (http_parser *parser, size_t len) { char c, ch; - const char *p, *pe; + const char *p = data, *pe; ssize_t to_read; enum state state = parser->state; enum header_states header_state = parser->header_state; size_t index = parser->index; + size_t nread = parser->nread; if (len == 0) { if (state == s_body_identity_eof) { @@ -285,6 +290,12 @@ size_t http_parser_execute (http_parser *parser, for (p=data, pe=data+len; p != pe; p++) { ch = *p; + + if (++nread > HTTP_MAX_HEADER_SIZE && PARSING_HEADER(state)) { + /* Buffer overflow attack */ + goto error; + } + switch (state) { case s_dead: @@ -442,6 +453,8 @@ size_t http_parser_execute (http_parser *parser, case s_start_req: { + if (ch == CR || ch == LF) + break; parser->flags = 0; parser->content_length = -1; @@ -739,6 +752,9 @@ size_t http_parser_execute (http_parser *parser, if (USUAL(ch)) break; switch (ch) { + case '?': + // allow extra '?' in query string + break; case ' ': CALLBACK(url); CALLBACK(query_string); @@ -1262,6 +1278,7 @@ size_t http_parser_execute (http_parser *parser, } parser->body_read = 0; + nread = 0; CALLBACK2(headers_complete); @@ -1421,6 +1438,7 @@ size_t http_parser_execute (http_parser *parser, parser->state = state; parser->header_state = header_state; parser->index = index; + parser->nread = nread; return len; @@ -1455,6 +1473,8 @@ http_parser_init (http_parser *parser, enum http_parser_type t) { parser->type = t; parser->state = (t == HTTP_REQUEST ? s_start_req : s_start_res); + parser->nread = 0; + parser->on_message_begin = NULL; parser->on_path = NULL; parser->on_query_string = NULL; diff --git a/deps/http_parser/http_parser.h b/deps/http_parser/http_parser.h index a1439ea364..7fb00840fe 100644 --- a/deps/http_parser/http_parser.h +++ b/deps/http_parser/http_parser.h @@ -38,6 +38,9 @@ extern "C" { # define HTTP_PARSER_STRICT 0 #endif +/* Maximium header size allowed */ +#define HTTP_MAX_HEADER_SIZE (80*1024) + typedef struct http_parser http_parser; /* Callbacks should return non-zero to indicate an error. The parse will @@ -85,6 +88,7 @@ struct http_parser { char flags; + size_t nread; ssize_t body_read; ssize_t content_length; diff --git a/deps/http_parser/test.c b/deps/http_parser/test.c index 07f0f8119e..63d4800186 100644 --- a/deps/http_parser/test.c +++ b/deps/http_parser/test.c @@ -58,7 +58,7 @@ struct message { int message_begin_cb_called; int headers_complete_cb_called; int message_complete_cb_called; - int eof_indicates_message_end; + int message_complete_on_eof; }; static int currently_parsing_eof; @@ -85,7 +85,7 @@ const struct message requests[] = "Accept: */*\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -116,7 +116,7 @@ const struct message requests[] = "Connection: keep-alive\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -145,7 +145,7 @@ const struct message requests[] = "aaaaaaaaaaaaa:++++++++++\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -166,7 +166,7 @@ const struct message requests[] = ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -185,7 +185,7 @@ const struct message requests[] = ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE /* would need Connection: close */ + ,.message_complete_on_eof= FALSE /* would need Connection: close */ ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -204,7 +204,7 @@ const struct message requests[] = "Accept: */*\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE /* would need Connection: close */ + ,.message_complete_on_eof= FALSE /* would need Connection: close */ ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -227,7 +227,7 @@ const struct message requests[] = "\r\n" "HELLO" ,.should_keep_alive= FALSE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_GET @@ -252,7 +252,7 @@ const struct message requests[] = "\r\n" "World" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -279,7 +279,7 @@ const struct message requests[] = "0\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -305,7 +305,7 @@ const struct message requests[] = "000\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -333,7 +333,7 @@ const struct message requests[] = "Content-Type: text/plain\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -361,7 +361,7 @@ const struct message requests[] = "0\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_POST @@ -381,7 +381,7 @@ const struct message requests[] = ,.type= HTTP_REQUEST ,.raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.method= HTTP_GET @@ -397,7 +397,7 @@ const struct message requests[] = #define APACHEBENCH_GET 13 /* The server receiving this request SHOULD NOT wait for EOF * to know that content-length == 0. - * How to represent this in a unit test? eof_indicates_message_end + * How to represent this in a unit test? message_complete_on_eof * Compare with NO_CONTENT_LENGTH_RESPONSE. */ , {.name = "apachebench get" @@ -407,7 +407,7 @@ const struct message requests[] = "User-Agent: ApacheBench/2.3\r\n" "Accept: */*\r\n\r\n" ,.should_keep_alive= FALSE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_GET @@ -423,6 +423,47 @@ const struct message requests[] = ,.body= "" } +#define QUERY_URL_WITH_QUESTION_MARK_GET 14 +/* Some clients include '?' characters in query strings. + */ +, {.name = "query url with question mark" + ,.type= HTTP_REQUEST + ,.raw= "GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n" + ,.should_keep_alive= TRUE + ,.message_complete_on_eof= FALSE + ,.http_major= 1 + ,.http_minor= 1 + ,.method= HTTP_GET + ,.query_string= "foo=bar?baz" + ,.fragment= "" + ,.request_path= "/test.cgi" + ,.request_url= "/test.cgi?foo=bar?baz" + ,.num_headers= 0 + ,.headers= {} + ,.body= "" + } + +#define PREFIX_NEWLINE_GET 15 +/* Some clients, especially after a POST in a keep-alive connection, + * will send an extra CRLF before the next request + */ +, {.name = "newline prefix get" + ,.type= HTTP_REQUEST + ,.raw= "\r\nGET /test HTTP/1.1\r\n\r\n" + ,.should_keep_alive= TRUE + ,.message_complete_on_eof= FALSE + ,.http_major= 1 + ,.http_minor= 1 + ,.method= HTTP_GET + ,.query_string= "" + ,.fragment= "" + ,.request_path= "/test" + ,.request_url= "/test" + ,.num_headers= 0 + ,.headers= { } + ,.body= "" + } + , {.name= NULL } /* sentinel */ }; @@ -447,7 +488,7 @@ const struct message responses[] = "here.\r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 301 @@ -494,7 +535,7 @@ const struct message responses[] = " \n" "" ,.should_keep_alive= FALSE - ,.eof_indicates_message_end= TRUE + ,.message_complete_on_eof= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 @@ -522,7 +563,7 @@ const struct message responses[] = ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 404 @@ -536,7 +577,7 @@ const struct message responses[] = ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 301\r\n\r\n" ,.should_keep_alive = TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 301 @@ -561,7 +602,7 @@ const struct message responses[] = "0 \r\n" "\r\n" ,.should_keep_alive= TRUE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 @@ -585,7 +626,7 @@ const struct message responses[] = "\n" "these headers are from http://news.ycombinator.com/" ,.should_keep_alive= FALSE - ,.eof_indicates_message_end= TRUE + ,.message_complete_on_eof= TRUE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 @@ -608,7 +649,7 @@ const struct message responses[] = "\r\n" "hello world" ,.should_keep_alive= FALSE - ,.eof_indicates_message_end= FALSE + ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 ,.status_code= 200 @@ -622,6 +663,31 @@ const struct message responses[] = ,.body= "hello world" } +#define UNDERSTORE_HEADER_KEY 7 + // shown by + // curl -o /dev/null -v "http://ad.doubleclick.net/pfadx/DARTSHELLCONFIGXML;dcmt=text/xml;" +, {.name="underscore header key" + ,.type= HTTP_RESPONSE + ,.raw= "HTTP/1.1 200 OK\r\n" + "Server: DCLK-AdSvr\r\n" + "Content-Type: text/xml\r\n" + "Content-Length: 0\r\n" + "DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n" + ,.should_keep_alive= TRUE + ,.message_complete_on_eof= FALSE + ,.http_major= 1 + ,.http_minor= 1 + ,.status_code= 200 + ,.num_headers= 4 + ,.headers= + { {"Server", "DCLK-AdSvr" } + , {"Content-Type", "text/xml" } + , {"Content-Length", "0" } + , {"DCLK_imp", "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" } + } + ,.body= "" + } + , {.name= NULL } /* sentinel */ }; @@ -730,7 +796,7 @@ message_complete_cb (http_parser *p) } messages[num_messages].message_complete_cb_called = TRUE; - messages[num_messages].eof_indicates_message_end = currently_parsing_eof; + messages[num_messages].message_complete_on_eof = currently_parsing_eof; num_messages++; return 0; @@ -820,7 +886,7 @@ message_eq (int index, const struct message *expected) } MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive); - MESSAGE_CHECK_NUM_EQ(expected, m, eof_indicates_message_end); + MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof); assert(m->message_begin_cb_called); assert(m->headers_complete_cb_called); diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index af0ecded71..5d712fc271 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -10,6 +10,7 @@ Alexandre Vassalotti Craig Schlenter Daniel Andersson Daniel James +Erich Ocean Jan de Mooij Jay Freeman Joel Stanley diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index 192dd25002..29ecccd7d8 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,3 +1,32 @@ +2010-02-03: Version 2.1.0 + + Values are now always wrapped in objects when used as a receiver. + (issue 223). + + [ES5] Implemented Object.getOwnPropertyNames. + + [ES5] Restrict JSON.parse to only accept strings that conforms to the + JSON grammar. + + Improvement of debugger agent (issue 549 and 554). + + Fixed problem with skipped stack frame in profiles (issue 553). + + Solaris support by Erich Ocean and Ryan Dahl + . + + Fix a bug that Math.round() returns incorrect results for huge + integers. + + Fix enumeration order for objects created from some constructor + functions (isue http://crbug.com/3867). + + Fix arithmetic on some integer constants (issue 580). + + Numerous performance improvements including porting of previous IA-32 + optimizations to x64 and ARM architectures. + + 2010-01-14: Version 2.0.6 Added ES5 Object.getPrototypeOf, GetOwnPropertyDescriptor, diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct index d68cec7c57..98fc22fba1 100644 --- a/deps/v8/SConstruct +++ b/deps/v8/SConstruct @@ -280,18 +280,12 @@ V8_EXTRA_FLAGS = { }, 'msvc': { 'all': { - 'WARNINGFLAGS': ['/WX', '/wd4355', '/wd4800'] + 'WARNINGFLAGS': ['/W3', '/WX', '/wd4355', '/wd4800'] }, 'library:shared': { 'CPPDEFINES': ['BUILDING_V8_SHARED'], 'LIBS': ['winmm', 'ws2_32'] }, - 'arch:ia32': { - 'WARNINGFLAGS': ['/W3'] - }, - 'arch:x64': { - 'WARNINGFLAGS': ['/W3'] - }, 'arch:arm': { 'CPPDEFINES': ['V8_TARGET_ARCH_ARM'], # /wd4996 is to silence the warning about sscanf @@ -317,7 +311,8 @@ MKSNAPSHOT_EXTRA_FLAGS = { 'LIBS': ['execinfo', 'pthread'] }, 'os:solaris': { - 'LIBS': ['pthread', 'socket', 'nsl', 'rt'] + 'LIBS': ['m', 'pthread', 'socket', 'nsl', 'rt'], + 'LINKFLAGS': ['-mt'] }, 'os:openbsd': { 'LIBS': ['execinfo', 'pthread'] @@ -369,7 +364,8 @@ CCTEST_EXTRA_FLAGS = { 'LIBS': ['execinfo', 'pthread'] }, 'os:solaris': { - 'LIBS': ['pthread', 'socket', 'nsl', 'rt'] + 'LIBS': ['m', 'pthread', 'socket', 'nsl', 'rt'], + 'LINKFLAGS': ['-mt'] }, 'os:openbsd': { 'LIBS': ['execinfo', 'pthread'] @@ -431,7 +427,8 @@ SAMPLE_FLAGS = { }, 'os:solaris': { 'LIBPATH' : ['/usr/local/lib'], - 'LIBS': ['pthread', 'socket', 'nsl', 'rt'] + 'LIBS': ['m', 'pthread', 'socket', 'nsl', 'rt'], + 'LINKFLAGS': ['-mt'] }, 'os:openbsd': { 'LIBPATH' : ['/usr/local/lib'], @@ -543,7 +540,8 @@ D8_FLAGS = { 'LIBS': ['pthread'], }, 'os:solaris': { - 'LIBS': ['pthread', 'socket', 'nsl', 'rt'] + 'LIBS': ['m', 'pthread', 'socket', 'nsl', 'rt'], + 'LINKFLAGS': ['-mt'] }, 'os:openbsd': { 'LIBS': ['pthread'], @@ -693,7 +691,7 @@ SIMPLE_OPTIONS = { def GetOptions(): result = Options() result.Add('mode', 'compilation mode (debug, release)', 'release') - result.Add('sample', 'build sample (shell, process)', '') + result.Add('sample', 'build sample (shell, process, lineprocessor)', '') result.Add('env', 'override environment settings (NAME0:value0,NAME1:value1,...)', '') result.Add('importenv', 'import environment settings (NAME0,NAME1,...)', '') for (name, option) in SIMPLE_OPTIONS.iteritems(): @@ -761,7 +759,7 @@ def IsLegal(env, option, values): def VerifyOptions(env): if not IsLegal(env, 'mode', ['debug', 'release']): return False - if not IsLegal(env, 'sample', ["shell", "process"]): + if not IsLegal(env, 'sample', ["shell", "process", "lineprocessor"]): return False if not IsLegal(env, 'regexp', ["native", "interpreted"]): return False diff --git a/deps/v8/include/v8-debug.h b/deps/v8/include/v8-debug.h index 10b41e2368..2e5fb3fde9 100644 --- a/deps/v8/include/v8-debug.h +++ b/deps/v8/include/v8-debug.h @@ -224,9 +224,11 @@ class EXPORT Debug { * be processed. Note that debug messages will only be processed if there is * a V8 break. This can happen automatically by using the option * --debugger-auto-break. + * \param provide_locker requires that V8 acquires v8::Locker for you before + * calling handler */ static void SetDebugMessageDispatchHandler( - DebugMessageDispatchHandler handler); + DebugMessageDispatchHandler handler, bool provide_locker = false); /** * Run a JavaScript function in the debugger. @@ -263,6 +265,43 @@ class EXPORT Debug { */ static bool EnableAgent(const char* name, int port, bool wait_for_connection = false); + + /** + * Makes V8 process all pending debug messages. + * + * From V8 point of view all debug messages come asynchronously (e.g. from + * remote debugger) but they all must be handled synchronously: V8 cannot + * do 2 things at one time so normal script execution must be interrupted + * for a while. + * + * Generally when message arrives V8 may be in one of 3 states: + * 1. V8 is running script; V8 will automatically interrupt and process all + * pending messages (however auto_break flag should be enabled); + * 2. V8 is suspended on debug breakpoint; in this state V8 is dedicated + * to reading and processing debug messages; + * 3. V8 is not running at all or has called some long-working C++ function; + * by default it means that processing of all debug message will be deferred + * until V8 gets control again; however, embedding application may improve + * this by manually calling this method. + * + * It makes sense to call this method whenever a new debug message arrived and + * V8 is not already running. Method v8::Debug::SetDebugMessageDispatchHandler + * should help with the former condition. + * + * Technically this method in many senses is equivalent to executing empty + * script: + * 1. It does nothing except for processing all pending debug messages. + * 2. It should be invoked with the same precautions and from the same context + * as V8 script would be invoked from, because: + * a. with "evaluate" command it can do whatever normal script can do, + * including all native calls; + * b. no other thread should call V8 while this method is running + * (v8::Locker may be used here). + * + * "Evaluate" debug command behavior currently is not specified in scope + * of this method. + */ + static void ProcessDebugMessages(); }; diff --git a/deps/v8/samples/lineprocessor.cc b/deps/v8/samples/lineprocessor.cc new file mode 100644 index 0000000000..505dabf945 --- /dev/null +++ b/deps/v8/samples/lineprocessor.cc @@ -0,0 +1,425 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include +#include +#include +#include +#include +#include + +/** + * This sample program should demonstrate certain aspects of debugging + * standalone V8-based application. + * + * The program reads input stream, processes it line by line and print + * the result to output. The actual processing is done by custom JavaScript + * script. The script is specified with command line parameters. + * + * The main cycle of the program will sequentially read lines from standard + * input, process them and print to standard output until input closes. + * There are 2 possible configuration in regard to main cycle. + * + * 1. The main cycle is on C++ side. Program should be run with + * --main-cycle-in-cpp option. Script must declare a function named + * "ProcessLine". The main cycle in C++ reads lines and calls this function + * for processing every time. This is a sample script: + +function ProcessLine(input_line) { + return ">>>" + input_line + "<<<"; +} + + * + * 2. The main cycle is in JavaScript. Program should be run with + * --main-cycle-in-js option. Script gets run one time at all and gets + * API of 2 global functions: "read_line" and "print". It should read input + * and print converted lines to output itself. This a sample script: + +while (true) { + var line = read_line(); + if (!line) { + break; + } + var res = line + " | " + line; + print(res); +} + + * + * When run with "-p" argument, the program starts V8 Debugger Agent and + * allows remote debugger to attach and debug JavaScript code. + * + * Interesting aspects: + * 1. Wait for remote debugger to attach + * Normally the program compiles custom script and immediately runs it. + * If programmer needs to debug script from the very beginning, he should + * run this sample program with "--wait-for-connection" command line parameter. + * This way V8 will suspend on the first statement and wait for + * debugger to attach. + * + * 2. Unresponsive V8 + * V8 Debugger Agent holds a connection with remote debugger, but it does + * respond only when V8 is running some script. In particular, when this program + * is waiting for input, all requests from debugger get deferred until V8 + * is called again. See how "--callback" command-line parameter in this sample + * fixes this issue. + */ + +enum MainCycleType { + CycleInCpp, + CycleInJs +}; + +const char* ToCString(const v8::String::Utf8Value& value); +void ReportException(v8::TryCatch* handler); +v8::Handle ReadFile(const char* name); +v8::Handle ReadLine(); + +v8::Handle Print(const v8::Arguments& args); +v8::Handle ReadLine(const v8::Arguments& args); +bool RunCppCycle(v8::Handle script, v8::Local context, + bool report_exceptions); + +v8::Persistent debug_message_context; + + +void DispatchDebugMessages() { + // We are in some random thread. We should already have v8::Locker acquired + // (we requested this when registered this callback). We was called + // because new debug messages arrived; they may have already been processed, + // but we shouldn't worry about this. + // + // All we have to do is to set context and call ProcessDebugMessages. + // + // We should decide which V8 context to use here. This is important for + // "evaluate" command, because it must be executed some context. + // In our sample we have only one context, so there is nothing really to + // think about. + v8::Context::Scope scope(debug_message_context); + + v8::Debug::ProcessDebugMessages(); +} + + +int RunMain(int argc, char* argv[]) { + v8::V8::SetFlagsFromCommandLine(&argc, argv, true); + v8::HandleScope handle_scope; + + v8::Handle script_source(NULL); + v8::Handle script_name(NULL); + int script_param_counter = 0; + + int port_number = -1; + bool wait_for_connection = false; + bool support_callback = false; + MainCycleType cycle_type = CycleInCpp; + + for (int i = 1; i < argc; i++) { + const char* str = argv[i]; + if (strcmp(str, "-f") == 0) { + // Ignore any -f flags for compatibility with the other stand- + // alone JavaScript engines. + continue; + } else if (strcmp(str, "--callback") == 0) { + support_callback = true; + } else if (strcmp(str, "--wait-for-connection") == 0) { + wait_for_connection = true; + } else if (strcmp(str, "--main-cycle-in-cpp") == 0) { + cycle_type = CycleInCpp; + } else if (strcmp(str, "--main-cycle-in-js") == 0) { + cycle_type = CycleInJs; + } else if (strcmp(str, "-p") == 0 && i + 1 < argc) { + port_number = atoi(argv[i + 1]); + i++; + } else if (strncmp(str, "--", 2) == 0) { + printf("Warning: unknown flag %s.\nTry --help for options\n", str); + } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { + script_source = v8::String::New(argv[i + 1]); + script_name = v8::String::New("unnamed"); + i++; + script_param_counter++; + } else { + // Use argument as a name of file to load. + script_source = ReadFile(str); + script_name = v8::String::New(str); + if (script_source.IsEmpty()) { + printf("Error reading '%s'\n", str); + return 1; + } + script_param_counter++; + } + } + + if (script_param_counter == 0) { + printf("Script is not specified\n"); + return 1; + } + if (script_param_counter != 1) { + printf("Only one script may be specified\n"); + return 1; + } + + // Create a template for the global object. + v8::Handle global = v8::ObjectTemplate::New(); + + // Bind the global 'print' function to the C++ Print callback. + global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); + + if (cycle_type == CycleInJs) { + // Bind the global 'read_line' function to the C++ Print callback. + global->Set(v8::String::New("read_line"), + v8::FunctionTemplate::New(ReadLine)); + } + + // Create a new execution environment containing the built-in + // functions + v8::Handle context = v8::Context::New(NULL, global); + debug_message_context = v8::Persistent::New(context); + + + // Enter the newly created execution environment. + v8::Context::Scope context_scope(context); + + v8::Locker locker; + + if (support_callback) { + v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true); + } + + if (port_number != -1) { + const char* auto_break_param = "--debugger_auto_break"; + v8::V8::SetFlagsFromString(auto_break_param, strlen(auto_break_param)); + v8::Debug::EnableAgent("lineprocessor", port_number, wait_for_connection); + } + + bool report_exceptions = true; + + v8::Handle script; + { + // Compile script in try/catch context. + v8::TryCatch try_catch; + script = v8::Script::Compile(script_source, script_name); + if (script.IsEmpty()) { + // Print errors that happened during compilation. + if (report_exceptions) + ReportException(&try_catch); + return 1; + } + } + + { + v8::TryCatch try_catch; + + script->Run(); + if (try_catch.HasCaught()) { + if (report_exceptions) + ReportException(&try_catch); + return 1; + } + } + + if (cycle_type == CycleInCpp) { + bool res = RunCppCycle(script, v8::Context::GetCurrent(), + report_exceptions); + return !res; + } else { + // All is already done. + } + return 0; +} + + +bool RunCppCycle(v8::Handle script, v8::Local context, + bool report_exceptions) { + v8::Locker lock; + + v8::Handle fun_name = v8::String::New("ProcessLine"); + v8::Handle process_val = + v8::Context::GetCurrent()->Global()->Get(fun_name); + + // If there is no Process function, or if it is not a function, + // bail out + if (!process_val->IsFunction()) { + printf("Error: Script does not declare 'ProcessLine' global function.\n"); + return 1; + } + + // It is a function; cast it to a Function + v8::Handle process_fun = + v8::Handle::Cast(process_val); + + + while (!feof(stdin)) { + v8::HandleScope handle_scope; + + v8::Handle input_line = ReadLine(); + if (input_line == v8::Undefined()) { + continue; + } + + const int argc = 1; + v8::Handle argv[argc] = { input_line }; + + v8::Handle result; + { + v8::TryCatch try_catch; + result = process_fun->Call(v8::Context::GetCurrent()->Global(), + argc, argv); + if (try_catch.HasCaught()) { + if (report_exceptions) + ReportException(&try_catch); + return false; + } + } + v8::String::Utf8Value str(result); + const char* cstr = ToCString(str); + printf("%s\n", cstr); + } + + return true; +} + +int main(int argc, char* argv[]) { + int result = RunMain(argc, argv); + v8::V8::Dispose(); + return result; +} + + +// Extracts a C string from a V8 Utf8Value. +const char* ToCString(const v8::String::Utf8Value& value) { + return *value ? *value : ""; +} + + +// Reads a file into a v8 string. +v8::Handle ReadFile(const char* name) { + FILE* file = fopen(name, "rb"); + if (file == NULL) return v8::Handle(); + + fseek(file, 0, SEEK_END); + int size = ftell(file); + rewind(file); + + char* chars = new char[size + 1]; + chars[size] = '\0'; + for (int i = 0; i < size;) { + int read = fread(&chars[i], 1, size - i, file); + i += read; + } + fclose(file); + v8::Handle result = v8::String::New(chars, size); + delete[] chars; + return result; +} + + +void ReportException(v8::TryCatch* try_catch) { + v8::HandleScope handle_scope; + v8::String::Utf8Value exception(try_catch->Exception()); + const char* exception_string = ToCString(exception); + v8::Handle message = try_catch->Message(); + if (message.IsEmpty()) { + // V8 didn't provide any extra information about this error; just + // print the exception. + printf("%s\n", exception_string); + } else { + // Print (filename):(line number): (message). + v8::String::Utf8Value filename(message->GetScriptResourceName()); + const char* filename_string = ToCString(filename); + int linenum = message->GetLineNumber(); + printf("%s:%i: %s\n", filename_string, linenum, exception_string); + // Print line of source code. + v8::String::Utf8Value sourceline(message->GetSourceLine()); + const char* sourceline_string = ToCString(sourceline); + printf("%s\n", sourceline_string); + // Print wavy underline (GetUnderline is deprecated). + int start = message->GetStartColumn(); + for (int i = 0; i < start; i++) { + printf(" "); + } + int end = message->GetEndColumn(); + for (int i = start; i < end; i++) { + printf("^"); + } + printf("\n"); + } +} + + +// The callback that is invoked by v8 whenever the JavaScript 'print' +// function is called. Prints its arguments on stdout separated by +// spaces and ending with a newline. +v8::Handle Print(const v8::Arguments& args) { + bool first = true; + for (int i = 0; i < args.Length(); i++) { + v8::HandleScope handle_scope; + if (first) { + first = false; + } else { + printf(" "); + } + v8::String::Utf8Value str(args[i]); + const char* cstr = ToCString(str); + printf("%s", cstr); + } + printf("\n"); + fflush(stdout); + return v8::Undefined(); +} + + +// The callback that is invoked by v8 whenever the JavaScript 'read_line' +// function is called. Reads a string from standard input and returns. +v8::Handle ReadLine(const v8::Arguments& args) { + if (args.Length() > 0) { + return v8::ThrowException(v8::String::New("Unexpected arguments")); + } + return ReadLine(); +} + +v8::Handle ReadLine() { + const int kBufferSize = 1024 + 1; + char buffer[kBufferSize]; + + char* res; + { + v8::Unlocker unlocker; + res = fgets(buffer, kBufferSize, stdin); + } + if (res == NULL) { + v8::Handle t = v8::Undefined(); + return reinterpret_cast&>(t); + } + // remove newline char + for (char* pos = buffer; *pos != '\0'; pos++) { + if (*pos == '\n') { + *pos = '\0'; + break; + } + } + return v8::String::New(buffer); +} diff --git a/deps/v8/src/SConscript b/deps/v8/src/SConscript index 9f8e4190bf..ebda77ac20 100755 --- a/deps/v8/src/SConscript +++ b/deps/v8/src/SConscript @@ -50,6 +50,7 @@ SOURCES = { contexts.cc conversions.cc counters.cc + data-flow.cc dateparser.cc debug-agent.cc debug.cc @@ -60,6 +61,7 @@ SOURCES = { flags.cc frame-element.cc frames.cc + full-codegen.cc func-name-inferrer.cc global-handles.cc handles.cc @@ -114,6 +116,7 @@ SOURCES = { arm/disasm-arm.cc arm/fast-codegen-arm.cc arm/frames-arm.cc + arm/full-codegen-arm.cc arm/ic-arm.cc arm/jump-target-arm.cc arm/macro-assembler-arm.cc @@ -137,6 +140,7 @@ SOURCES = { ia32/disasm-ia32.cc ia32/fast-codegen-ia32.cc ia32/frames-ia32.cc + ia32/full-codegen-ia32.cc ia32/ic-ia32.cc ia32/jump-target-ia32.cc ia32/macro-assembler-ia32.cc @@ -154,6 +158,7 @@ SOURCES = { x64/disasm-x64.cc x64/fast-codegen-x64.cc x64/frames-x64.cc + x64/full-codegen-x64.cc x64/ic-x64.cc x64/jump-target-x64.cc x64/macro-assembler-x64.cc @@ -239,7 +244,7 @@ def ConfigureObjectFiles(): env.Replace(**context.flags['v8']) context.ApplyEnvOverrides(env) env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C) - env['BUILDERS']['Snapshot'] = Builder(action='$SOURCE $TARGET --logfile "$LOGFILE"') + env['BUILDERS']['Snapshot'] = Builder(action='$SOURCE $TARGET --logfile "$LOGFILE" --log-snapshot-positions') # Build the standard platform-independent source files. source_files = context.GetRelevantSources(SOURCES) diff --git a/deps/v8/src/accessors.cc b/deps/v8/src/accessors.cc index 56cf135981..5a029285e8 100644 --- a/deps/v8/src/accessors.cc +++ b/deps/v8/src/accessors.cc @@ -493,11 +493,11 @@ Object* Accessors::FunctionGetLength(Object* object, void*) { // If the function isn't compiled yet, the length is not computed // correctly yet. Compile it now and return the right length. HandleScope scope; - Handle function_handle(function); - if (!CompileLazy(function_handle, KEEP_EXCEPTION)) { + Handle shared(function->shared()); + if (!CompileLazyShared(shared, KEEP_EXCEPTION)) { return Failure::Exception(); } - return Smi::FromInt(function_handle->shared()->length()); + return Smi::FromInt(shared->length()); } else { return Smi::FromInt(function->shared()->length()); } diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index ab5d0a5608..322c90fc5a 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -3669,7 +3669,6 @@ void Debug::SetMessageHandler(v8::Debug::MessageHandler handler, void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) { EnsureInitialized("v8::Debug::SetMessageHandler"); ENTER_V8; - HandleScope scope; i::Debugger::SetMessageHandler(handler); } @@ -3691,10 +3690,10 @@ void Debug::SetHostDispatchHandler(HostDispatchHandler handler, void Debug::SetDebugMessageDispatchHandler( - DebugMessageDispatchHandler handler) { + DebugMessageDispatchHandler handler, bool provide_locker) { EnsureInitialized("v8::Debug::SetDebugMessageDispatchHandler"); ENTER_V8; - i::Debugger::SetDebugMessageDispatchHandler(handler); + i::Debugger::SetDebugMessageDispatchHandler(handler, provide_locker); } @@ -3744,6 +3743,11 @@ Local Debug::GetMirror(v8::Handle obj) { bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) { return i::Debugger::StartAgent(name, port, wait_for_connection); } + +void Debug::ProcessDebugMessages() { + i::Execution::ProcessDebugMesssages(true); +} + #endif // ENABLE_DEBUGGER_SUPPORT namespace internal { diff --git a/deps/v8/src/arm/assembler-arm-inl.h b/deps/v8/src/arm/assembler-arm-inl.h index fd2fcd3059..354436cb14 100644 --- a/deps/v8/src/arm/assembler-arm-inl.h +++ b/deps/v8/src/arm/assembler-arm-inl.h @@ -174,20 +174,6 @@ Operand::Operand(const ExternalReference& f) { } -Operand::Operand(Object** opp) { - rm_ = no_reg; - imm32_ = reinterpret_cast(opp); - rmode_ = RelocInfo::NONE; -} - - -Operand::Operand(Context** cpp) { - rm_ = no_reg; - imm32_ = reinterpret_cast(cpp); - rmode_ = RelocInfo::NONE; -} - - Operand::Operand(Smi* value) { rm_ = no_reg; imm32_ = reinterpret_cast(value); diff --git a/deps/v8/src/arm/assembler-arm.cc b/deps/v8/src/arm/assembler-arm.cc index 07da800903..74547be6e2 100644 --- a/deps/v8/src/arm/assembler-arm.cc +++ b/deps/v8/src/arm/assembler-arm.cc @@ -30,9 +30,9 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -// The original source code covered by the above license above has been modified -// significantly by Google Inc. -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// The original source code covered by the above license above has been +// modified significantly by Google Inc. +// Copyright 2010 the V8 project authors. All rights reserved. #include "v8.h" @@ -1371,6 +1371,36 @@ void Assembler::stc2(Coprocessor coproc, // Support for VFP. +void Assembler::vldr(const DwVfpRegister dst, + const Register base, + int offset, + const Condition cond) { + // Ddst = MEM(Rbase + offset). + // Instruction details available in ARM DDI 0406A, A8-628. + // cond(31-28) | 1101(27-24)| 1001(23-20) | Rbase(19-16) | + // Vdst(15-12) | 1011(11-8) | offset + ASSERT(CpuFeatures::IsEnabled(VFP3)); + ASSERT(offset % 4 == 0); + emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 | + 0xB*B8 | ((offset / 4) & 255)); +} + + +void Assembler::vstr(const DwVfpRegister src, + const Register base, + int offset, + const Condition cond) { + // MEM(Rbase + offset) = Dsrc. + // Instruction details available in ARM DDI 0406A, A8-786. + // cond(31-28) | 1101(27-24)| 1000(23-20) | | Rbase(19-16) | + // Vsrc(15-12) | 1011(11-8) | (offset/4) + ASSERT(CpuFeatures::IsEnabled(VFP3)); + ASSERT(offset % 4 == 0); + emit(cond | 0xD8*B20 | base.code()*B16 | src.code()*B12 | + 0xB*B8 | ((offset / 4) & 255)); +} + + void Assembler::vmov(const DwVfpRegister dst, const Register src1, const Register src2, diff --git a/deps/v8/src/arm/assembler-arm.h b/deps/v8/src/arm/assembler-arm.h index cd53dd6097..208d583ce1 100644 --- a/deps/v8/src/arm/assembler-arm.h +++ b/deps/v8/src/arm/assembler-arm.h @@ -30,9 +30,9 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED // OF THE POSSIBILITY OF SUCH DAMAGE. -// The original source code covered by the above license above has been modified -// significantly by Google Inc. -// Copyright 2006-2008 the V8 project authors. All rights reserved. +// The original source code covered by the above license above has been +// modified significantly by Google Inc. +// Copyright 2010 the V8 project authors. All rights reserved. // A light-weight ARM Assembler // Generates user mode instructions for the ARM architecture up to version 5 @@ -398,8 +398,6 @@ class Operand BASE_EMBEDDED { RelocInfo::Mode rmode = RelocInfo::NONE)); INLINE(explicit Operand(const ExternalReference& f)); INLINE(explicit Operand(const char* s)); - INLINE(explicit Operand(Object** opp)); - INLINE(explicit Operand(Context** cpp)); explicit Operand(Handle handle); INLINE(explicit Operand(Smi* value)); @@ -796,6 +794,14 @@ class Assembler : public Malloced { // However, some simple modifications can allow // these APIs to support D16 to D31. + void vldr(const DwVfpRegister dst, + const Register base, + int offset, // Offset must be a multiple of 4. + const Condition cond = al); + void vstr(const DwVfpRegister src, + const Register base, + int offset, // Offset must be a multiple of 4. + const Condition cond = al); void vmov(const DwVfpRegister dst, const Register src1, const Register src2, diff --git a/deps/v8/src/arm/builtins-arm.cc b/deps/v8/src/arm/builtins-arm.cc index 5389a3c5f5..ae7dae3b08 100644 --- a/deps/v8/src/arm/builtins-arm.cc +++ b/deps/v8/src/arm/builtins-arm.cc @@ -38,15 +38,32 @@ namespace internal { #define __ ACCESS_MASM(masm) -void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) { - // TODO(428): Don't pass the function in a static variable. - __ mov(ip, Operand(ExternalReference::builtin_passed_function())); - __ str(r1, MemOperand(ip, 0)); - - // The actual argument count has already been loaded into register - // r0, but JumpToRuntime expects r0 to contain the number of - // arguments including the receiver. - __ add(r0, r0, Operand(1)); +void Builtins::Generate_Adaptor(MacroAssembler* masm, + CFunctionId id, + BuiltinExtraArguments extra_args) { + // ----------- S t a t e ------------- + // -- r0 : number of arguments excluding receiver + // -- r1 : called function (only guaranteed when + // extra_args requires it) + // -- cp : context + // -- sp[0] : last argument + // -- ... + // -- sp[4 * (argc - 1)] : first argument (argc == r0) + // -- sp[4 * argc] : receiver + // ----------------------------------- + + // Insert extra arguments. + int num_extra_args = 0; + if (extra_args == NEEDS_CALLED_FUNCTION) { + num_extra_args = 1; + __ push(r1); + } else { + ASSERT(extra_args == NO_EXTRA_ARGUMENTS); + } + + // JumpToRuntime expects r0 to contain the number of arguments + // including the receiver and the extra arguments. + __ add(r0, r0, Operand(num_extra_args + 1)); __ JumpToRuntime(ExternalReference(id)); } @@ -491,7 +508,8 @@ void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { } -void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { +static void Generate_JSConstructStubHelper(MacroAssembler* masm, + bool is_api_function) { // Enter a construct frame. __ EnterConstructFrame(); @@ -727,8 +745,17 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { // Call the function. // r0: number of arguments // r1: constructor function - ParameterCount actual(r0); - __ InvokeFunction(r1, actual, CALL_FUNCTION); + if (is_api_function) { + __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); + Handle code = Handle( + Builtins::builtin(Builtins::HandleApiCallConstruct)); + ParameterCount expected(0); + __ InvokeCode(code, expected, expected, + RelocInfo::CODE_TARGET, CALL_FUNCTION); + } else { + ParameterCount actual(r0); + __ InvokeFunction(r1, actual, CALL_FUNCTION); + } // Pop the function from the stack. // sp[0]: constructor function @@ -783,6 +810,16 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { } +void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { + Generate_JSConstructStubHelper(masm, false); +} + + +void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { + Generate_JSConstructStubHelper(masm, true); +} + + static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, bool is_construct) { // Called from Generate_JS_Entry diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc index 70d8ab4955..ea4b165fd3 100644 --- a/deps/v8/src/arm/codegen-arm.cc +++ b/deps/v8/src/arm/codegen-arm.cc @@ -1,4 +1,4 @@ -// Copyright 2006-2009 the V8 project authors. All rights reserved. +// Copyright 2010 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -47,7 +47,7 @@ static void EmitIdenticalObjectComparison(MacroAssembler* masm, Condition cc, bool never_nan_nan); static void EmitSmiNonsmiComparison(MacroAssembler* masm, - Label* rhs_not_nan, + Label* lhs_not_nan, Label* slow, bool strict); static void EmitTwoNonNanDoubleComparison(MacroAssembler* masm, Condition cc); @@ -121,12 +121,13 @@ CodeGenState::~CodeGenState() { // ------------------------------------------------------------------------- // CodeGenerator implementation -CodeGenerator::CodeGenerator(int buffer_size, Handle