Upgrade V8 to 3.5.7
This commit is contained in:
parent
42529ddfb5
commit
b15ab5de51
9
deps/v8/ChangeLog
vendored
9
deps/v8/ChangeLog
vendored
@ -1,3 +1,12 @@
|
||||
2011-08-22: Version 3.5.7
|
||||
|
||||
Make scanner handle invalid unicode escapes in identifiers correctly.
|
||||
|
||||
Make regexp flag parsing stricter.
|
||||
|
||||
Fix several memory leaks.
|
||||
|
||||
|
||||
2011-08-17: Version 3.5.6
|
||||
|
||||
Fixed issue that could cause crashes when running with --heap-stats.
|
||||
|
40
deps/v8/build/common.gypi
vendored
40
deps/v8/build/common.gypi
vendored
@ -32,25 +32,30 @@
|
||||
'visibility%': 'hidden',
|
||||
'msvs_multi_core_compile%': '1',
|
||||
'variables': {
|
||||
'conditions': [
|
||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||
# This handles the Linux platforms we generally deal with. Anything
|
||||
# else gets passed through, which probably won't work very well; such
|
||||
# hosts should pass an explicit target_arch to gyp.
|
||||
'host_arch%':
|
||||
'<!(uname -m | sed -e "s/i.86/ia32/;s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/")',
|
||||
}, { # OS!="linux" and OS!="freebsd" and OS!="openbsd"
|
||||
'host_arch%': 'ia32',
|
||||
}],
|
||||
],
|
||||
'variables': {
|
||||
'conditions': [
|
||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||
# This handles the Linux platforms we generally deal with. Anything
|
||||
# else gets passed through, which probably won't work very well; such
|
||||
# hosts should pass an explicit target_arch to gyp.
|
||||
'host_arch%':
|
||||
'<!(uname -m | sed -e "s/i.86/ia32/;s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/")',
|
||||
}, { # OS!="linux" and OS!="freebsd" and OS!="openbsd"
|
||||
'host_arch%': 'ia32',
|
||||
}],
|
||||
],
|
||||
},
|
||||
'host_arch%': '<(host_arch)',
|
||||
'target_arch%': '<(host_arch)',
|
||||
'v8_target_arch%': '<(target_arch)',
|
||||
},
|
||||
'host_arch%': '<(host_arch)',
|
||||
'target_arch%': '<(host_arch)',
|
||||
'v8_target_arch%': '<(target_arch)',
|
||||
'target_arch%': '<(target_arch)',
|
||||
'v8_target_arch%': '<(v8_target_arch)',
|
||||
'v8_enable_debugger_support%': 1,
|
||||
'conditions': [
|
||||
['(target_arch=="arm" and host_arch!="arm") or \
|
||||
(target_arch=="x64" and host_arch!="x64")', {
|
||||
['(v8_target_arch=="arm" and host_arch!="arm") or \
|
||||
(v8_target_arch=="x64" and host_arch!="x64")', {
|
||||
'want_separate_host_toolset': 1,
|
||||
}, {
|
||||
'want_separate_host_toolset': 0,
|
||||
@ -80,8 +85,9 @@
|
||||
'conditions': [
|
||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
|
||||
'target_defaults': {
|
||||
'cflags': [ '-Wall', '-pthread', '-fno-rtti', '-fno-exceptions',
|
||||
'-pedantic' ],
|
||||
'cflags': [ '-Wall', '-Werror', '-W', '-Wno-unused-parameter',
|
||||
'-Wnon-virtual-dtor', '-pthread', '-fno-rtti',
|
||||
'-fno-exceptions', '-pedantic' ],
|
||||
'ldflags': [ '-pthread', ],
|
||||
'conditions': [
|
||||
[ 'target_arch=="ia32"', {
|
||||
|
485
deps/v8/samples/shell.cc
vendored
485
deps/v8/samples/shell.cc
vendored
@ -26,39 +26,28 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <v8.h>
|
||||
#include <v8-testing.h>
|
||||
#include <assert.h>
|
||||
#ifdef COMPRESS_STARTUP_DATA_BZ2
|
||||
#include <bzlib.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// When building with V8 in a shared library we cannot use functions which
|
||||
// is not explicitly a part of the public V8 API. This extensive use of
|
||||
// #ifndef USING_V8_SHARED/#endif is a hack until we can resolve whether to
|
||||
// still use the shell sample for testing or change to use the developer
|
||||
// shell d8 TODO(1272).
|
||||
#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
|
||||
#include "../src/v8.h"
|
||||
#endif // USING_V8_SHARED
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <unistd.h> // NOLINT
|
||||
#ifdef COMPRESS_STARTUP_DATA_BZ2
|
||||
#error Using compressed startup data is not supported for this sample
|
||||
#endif
|
||||
|
||||
static void ExitShell(int exit_code) {
|
||||
// Use _exit instead of exit to avoid races between isolate
|
||||
// threads and static destructors.
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
_exit(exit_code);
|
||||
}
|
||||
/**
|
||||
* This sample program shows how to implement a simple javascript shell
|
||||
* based on V8. This includes initializing V8 with command line options,
|
||||
* creating global functions, compiling and executing strings.
|
||||
*
|
||||
* For a more sophisticated shell, consider using the debug shell D8.
|
||||
*/
|
||||
|
||||
|
||||
v8::Persistent<v8::Context> CreateShellContext();
|
||||
void RunShell(v8::Handle<v8::Context> context);
|
||||
int RunMain(int argc, char* argv[]);
|
||||
bool ExecuteString(v8::Handle<v8::String> source,
|
||||
v8::Handle<v8::Value> name,
|
||||
bool print_result,
|
||||
@ -68,305 +57,28 @@ v8::Handle<v8::Value> Read(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Load(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Quit(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Version(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Int8Array(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Uint8Array(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Int16Array(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Uint16Array(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Int32Array(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Uint32Array(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Float32Array(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> Float64Array(const v8::Arguments& args);
|
||||
v8::Handle<v8::Value> PixelArray(const v8::Arguments& args);
|
||||
v8::Handle<v8::String> ReadFile(const char* name);
|
||||
void ReportException(v8::TryCatch* handler);
|
||||
|
||||
|
||||
static bool last_run = true;
|
||||
|
||||
class SourceGroup {
|
||||
public:
|
||||
SourceGroup() :
|
||||
#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
|
||||
next_semaphore_(v8::internal::OS::CreateSemaphore(0)),
|
||||
done_semaphore_(v8::internal::OS::CreateSemaphore(0)),
|
||||
thread_(NULL),
|
||||
#endif // USING_V8_SHARED
|
||||
argv_(NULL),
|
||||
begin_offset_(0),
|
||||
end_offset_(0) { }
|
||||
|
||||
#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
|
||||
~SourceGroup() {
|
||||
delete next_semaphore_;
|
||||
delete done_semaphore_;
|
||||
}
|
||||
#endif // USING_V8_SHARED
|
||||
|
||||
void Begin(char** argv, int offset) {
|
||||
argv_ = const_cast<const char**>(argv);
|
||||
begin_offset_ = offset;
|
||||
}
|
||||
|
||||
void End(int offset) { end_offset_ = offset; }
|
||||
|
||||
void Execute() {
|
||||
for (int i = begin_offset_; i < end_offset_; ++i) {
|
||||
const char* arg = argv_[i];
|
||||
if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) {
|
||||
// Execute argument given to -e option directly.
|
||||
v8::HandleScope handle_scope;
|
||||
v8::Handle<v8::String> file_name = v8::String::New("unnamed");
|
||||
v8::Handle<v8::String> source = v8::String::New(argv_[i + 1]);
|
||||
if (!ExecuteString(source, file_name, false, true)) {
|
||||
ExitShell(1);
|
||||
return;
|
||||
}
|
||||
++i;
|
||||
} else if (arg[0] == '-') {
|
||||
// Ignore other options. They have been parsed already.
|
||||
} else {
|
||||
// Use all other arguments as names of files to load and run.
|
||||
v8::HandleScope handle_scope;
|
||||
v8::Handle<v8::String> file_name = v8::String::New(arg);
|
||||
v8::Handle<v8::String> source = ReadFile(arg);
|
||||
if (source.IsEmpty()) {
|
||||
printf("Error reading '%s'\n", arg);
|
||||
continue;
|
||||
}
|
||||
if (!ExecuteString(source, file_name, false, true)) {
|
||||
ExitShell(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
|
||||
void StartExecuteInThread() {
|
||||
if (thread_ == NULL) {
|
||||
thread_ = new IsolateThread(this);
|
||||
thread_->Start();
|
||||
}
|
||||
next_semaphore_->Signal();
|
||||
}
|
||||
|
||||
void WaitForThread() {
|
||||
if (thread_ == NULL) return;
|
||||
if (last_run) {
|
||||
thread_->Join();
|
||||
thread_ = NULL;
|
||||
} else {
|
||||
done_semaphore_->Wait();
|
||||
}
|
||||
}
|
||||
#endif // USING_V8_SHARED
|
||||
|
||||
private:
|
||||
#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
|
||||
static v8::internal::Thread::Options GetThreadOptions() {
|
||||
v8::internal::Thread::Options options;
|
||||
options.name = "IsolateThread";
|
||||
// On some systems (OSX 10.6) the stack size default is 0.5Mb or less
|
||||
// which is not enough to parse the big literal expressions used in tests.
|
||||
// The stack size should be at least StackGuard::kLimitSize + some
|
||||
// OS-specific padding for thread startup code.
|
||||
options.stack_size = 2 << 20; // 2 Mb seems to be enough
|
||||
return options;
|
||||
}
|
||||
|
||||
class IsolateThread : public v8::internal::Thread {
|
||||
public:
|
||||
explicit IsolateThread(SourceGroup* group)
|
||||
: v8::internal::Thread(GetThreadOptions()), group_(group) {}
|
||||
|
||||
virtual void Run() {
|
||||
group_->ExecuteInThread();
|
||||
}
|
||||
|
||||
private:
|
||||
SourceGroup* group_;
|
||||
};
|
||||
|
||||
void ExecuteInThread() {
|
||||
v8::Isolate* isolate = v8::Isolate::New();
|
||||
do {
|
||||
if (next_semaphore_ != NULL) next_semaphore_->Wait();
|
||||
{
|
||||
v8::Isolate::Scope iscope(isolate);
|
||||
v8::HandleScope scope;
|
||||
v8::Persistent<v8::Context> context = CreateShellContext();
|
||||
{
|
||||
v8::Context::Scope cscope(context);
|
||||
Execute();
|
||||
}
|
||||
context.Dispose();
|
||||
}
|
||||
if (done_semaphore_ != NULL) done_semaphore_->Signal();
|
||||
} while (!last_run);
|
||||
isolate->Dispose();
|
||||
}
|
||||
|
||||
v8::internal::Semaphore* next_semaphore_;
|
||||
v8::internal::Semaphore* done_semaphore_;
|
||||
v8::internal::Thread* thread_;
|
||||
#endif // USING_V8_SHARED
|
||||
|
||||
const char** argv_;
|
||||
int begin_offset_;
|
||||
int end_offset_;
|
||||
};
|
||||
static bool run_shell;
|
||||
|
||||
|
||||
static SourceGroup* isolate_sources = NULL;
|
||||
|
||||
|
||||
#ifdef COMPRESS_STARTUP_DATA_BZ2
|
||||
class BZip2Decompressor : public v8::StartupDataDecompressor {
|
||||
public:
|
||||
virtual ~BZip2Decompressor() { }
|
||||
|
||||
protected:
|
||||
virtual int DecompressData(char* raw_data,
|
||||
int* raw_data_size,
|
||||
const char* compressed_data,
|
||||
int compressed_data_size) {
|
||||
ASSERT_EQ(v8::StartupData::kBZip2,
|
||||
v8::V8::GetCompressedStartupDataAlgorithm());
|
||||
unsigned int decompressed_size = *raw_data_size;
|
||||
int result =
|
||||
BZ2_bzBuffToBuffDecompress(raw_data,
|
||||
&decompressed_size,
|
||||
const_cast<char*>(compressed_data),
|
||||
compressed_data_size,
|
||||
0, 1);
|
||||
if (result == BZ_OK) {
|
||||
*raw_data_size = decompressed_size;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
int RunMain(int argc, char* argv[]) {
|
||||
int main(int argc, char* argv[]) {
|
||||
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
||||
run_shell = (argc == 1);
|
||||
v8::HandleScope handle_scope;
|
||||
v8::Persistent<v8::Context> context = CreateShellContext();
|
||||
// Enter the newly created execution environment.
|
||||
context->Enter();
|
||||
if (context.IsEmpty()) {
|
||||
printf("Error creating context\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool run_shell = (argc == 1);
|
||||
int num_isolates = 1;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--isolate") == 0) {
|
||||
#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
|
||||
++num_isolates;
|
||||
#else // USING_V8_SHARED
|
||||
printf("Error: --isolate not supported when linked with shared "
|
||||
"library\n");
|
||||
ExitShell(1);
|
||||
#endif // USING_V8_SHARED
|
||||
}
|
||||
}
|
||||
if (isolate_sources == NULL) {
|
||||
isolate_sources = new SourceGroup[num_isolates];
|
||||
SourceGroup* current = isolate_sources;
|
||||
current->Begin(argv, 1);
|
||||
for (int i = 1; i < argc; i++) {
|
||||
const char* str = argv[i];
|
||||
if (strcmp(str, "--isolate") == 0) {
|
||||
current->End(i);
|
||||
current++;
|
||||
current->Begin(argv, i + 1);
|
||||
} else if (strcmp(str, "--shell") == 0) {
|
||||
run_shell = true;
|
||||
} else if (strcmp(str, "-f") == 0) {
|
||||
// Ignore any -f flags for compatibility with the other stand-
|
||||
// alone JavaScript engines.
|
||||
continue;
|
||||
} else if (strncmp(str, "--", 2) == 0) {
|
||||
printf("Warning: unknown flag %s.\nTry --help for options\n", str);
|
||||
}
|
||||
}
|
||||
current->End(argc);
|
||||
}
|
||||
#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
|
||||
for (int i = 1; i < num_isolates; ++i) {
|
||||
isolate_sources[i].StartExecuteInThread();
|
||||
}
|
||||
#endif // USING_V8_SHARED
|
||||
isolate_sources[0].Execute();
|
||||
context->Enter();
|
||||
int result = RunMain(argc, argv);
|
||||
if (run_shell) RunShell(context);
|
||||
#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
|
||||
for (int i = 1; i < num_isolates; ++i) {
|
||||
isolate_sources[i].WaitForThread();
|
||||
}
|
||||
#endif // USING_V8_SHARED
|
||||
if (last_run) {
|
||||
delete[] isolate_sources;
|
||||
isolate_sources = NULL;
|
||||
}
|
||||
context->Exit();
|
||||
context.Dispose();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Figure out if we're requested to stress the optimization
|
||||
// infrastructure by running tests multiple times and forcing
|
||||
// optimization in the last run.
|
||||
bool FLAG_stress_opt = false;
|
||||
bool FLAG_stress_deopt = false;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--stress-opt") == 0) {
|
||||
FLAG_stress_opt = true;
|
||||
argv[i] = NULL;
|
||||
} else if (strcmp(argv[i], "--stress-deopt") == 0) {
|
||||
FLAG_stress_deopt = true;
|
||||
argv[i] = NULL;
|
||||
} else if (strcmp(argv[i], "--noalways-opt") == 0) {
|
||||
// No support for stressing if we can't use --always-opt.
|
||||
FLAG_stress_opt = false;
|
||||
FLAG_stress_deopt = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPRESS_STARTUP_DATA_BZ2
|
||||
BZip2Decompressor startup_data_decompressor;
|
||||
int bz2_result = startup_data_decompressor.Decompress();
|
||||
if (bz2_result != BZ_OK) {
|
||||
fprintf(stderr, "bzip error code: %d\n", bz2_result);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
||||
int result = 0;
|
||||
if (FLAG_stress_opt || FLAG_stress_deopt) {
|
||||
v8::Testing::SetStressRunType(FLAG_stress_opt
|
||||
? v8::Testing::kStressTypeOpt
|
||||
: v8::Testing::kStressTypeDeopt);
|
||||
int stress_runs = v8::Testing::GetStressRuns();
|
||||
for (int i = 0; i < stress_runs && result == 0; i++) {
|
||||
printf("============ Stress %d/%d ============\n",
|
||||
i + 1, stress_runs);
|
||||
v8::Testing::PrepareStressRun(i);
|
||||
last_run = (i == stress_runs - 1);
|
||||
result = RunMain(argc, argv);
|
||||
}
|
||||
printf("======== Full Deoptimization =======\n");
|
||||
v8::Testing::DeoptimizeAll();
|
||||
} else {
|
||||
result = RunMain(argc, argv);
|
||||
}
|
||||
v8::V8::Dispose();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -393,26 +105,6 @@ v8::Persistent<v8::Context> CreateShellContext() {
|
||||
// Bind the 'version' function
|
||||
global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version));
|
||||
|
||||
// Bind the handlers for external arrays.
|
||||
global->Set(v8::String::New("Int8Array"),
|
||||
v8::FunctionTemplate::New(Int8Array));
|
||||
global->Set(v8::String::New("Uint8Array"),
|
||||
v8::FunctionTemplate::New(Uint8Array));
|
||||
global->Set(v8::String::New("Int16Array"),
|
||||
v8::FunctionTemplate::New(Int16Array));
|
||||
global->Set(v8::String::New("Uint16Array"),
|
||||
v8::FunctionTemplate::New(Uint16Array));
|
||||
global->Set(v8::String::New("Int32Array"),
|
||||
v8::FunctionTemplate::New(Int32Array));
|
||||
global->Set(v8::String::New("Uint32Array"),
|
||||
v8::FunctionTemplate::New(Uint32Array));
|
||||
global->Set(v8::String::New("Float32Array"),
|
||||
v8::FunctionTemplate::New(Float32Array));
|
||||
global->Set(v8::String::New("Float64Array"),
|
||||
v8::FunctionTemplate::New(Float64Array));
|
||||
global->Set(v8::String::New("PixelArray"),
|
||||
v8::FunctionTemplate::New(PixelArray));
|
||||
|
||||
return v8::Context::New(NULL, global);
|
||||
}
|
||||
|
||||
@ -486,7 +178,9 @@ v8::Handle<v8::Value> Quit(const v8::Arguments& args) {
|
||||
// If not arguments are given args[0] will yield undefined which
|
||||
// converts to the integer value 0.
|
||||
int exit_code = args[0]->Int32Value();
|
||||
ExitShell(exit_code);
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
exit(exit_code);
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
@ -496,113 +190,6 @@ v8::Handle<v8::Value> Version(const v8::Arguments& args) {
|
||||
}
|
||||
|
||||
|
||||
void ExternalArrayWeakCallback(v8::Persistent<v8::Value> object, void* data) {
|
||||
free(data);
|
||||
object.Dispose();
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> CreateExternalArray(const v8::Arguments& args,
|
||||
v8::ExternalArrayType type,
|
||||
size_t element_size) {
|
||||
assert(element_size == 1 ||
|
||||
element_size == 2 ||
|
||||
element_size == 4 ||
|
||||
element_size == 8);
|
||||
if (args.Length() != 1) {
|
||||
return v8::ThrowException(
|
||||
v8::String::New("Array constructor needs one parameter."));
|
||||
}
|
||||
static const int kMaxLength = 0x3fffffff;
|
||||
size_t length = 0;
|
||||
if (args[0]->IsUint32()) {
|
||||
length = args[0]->Uint32Value();
|
||||
} else if (args[0]->IsNumber()) {
|
||||
double raw_length = args[0]->NumberValue();
|
||||
if (raw_length < 0) {
|
||||
return v8::ThrowException(
|
||||
v8::String::New("Array length must not be negative."));
|
||||
}
|
||||
if (raw_length > kMaxLength) {
|
||||
return v8::ThrowException(
|
||||
v8::String::New("Array length exceeds maximum length."));
|
||||
}
|
||||
length = static_cast<size_t>(raw_length);
|
||||
} else {
|
||||
return v8::ThrowException(
|
||||
v8::String::New("Array length must be a number."));
|
||||
}
|
||||
if (length > static_cast<size_t>(kMaxLength)) {
|
||||
return v8::ThrowException(
|
||||
v8::String::New("Array length exceeds maximum length."));
|
||||
}
|
||||
void* data = calloc(length, element_size);
|
||||
if (data == NULL) {
|
||||
return v8::ThrowException(v8::String::New("Memory allocation failed."));
|
||||
}
|
||||
v8::Handle<v8::Object> array = v8::Object::New();
|
||||
v8::Persistent<v8::Object> persistent_array =
|
||||
v8::Persistent<v8::Object>::New(array);
|
||||
persistent_array.MakeWeak(data, ExternalArrayWeakCallback);
|
||||
persistent_array.MarkIndependent();
|
||||
array->SetIndexedPropertiesToExternalArrayData(data, type, length);
|
||||
array->Set(v8::String::New("length"), v8::Int32::New(length),
|
||||
v8::ReadOnly);
|
||||
array->Set(v8::String::New("BYTES_PER_ELEMENT"),
|
||||
v8::Int32::New(element_size));
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> Int8Array(const v8::Arguments& args) {
|
||||
return CreateExternalArray(args, v8::kExternalByteArray, sizeof(int8_t));
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> Uint8Array(const v8::Arguments& args) {
|
||||
return CreateExternalArray(args, v8::kExternalUnsignedByteArray,
|
||||
sizeof(uint8_t));
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> Int16Array(const v8::Arguments& args) {
|
||||
return CreateExternalArray(args, v8::kExternalShortArray, sizeof(int16_t));
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> Uint16Array(const v8::Arguments& args) {
|
||||
return CreateExternalArray(args, v8::kExternalUnsignedShortArray,
|
||||
sizeof(uint16_t));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> Int32Array(const v8::Arguments& args) {
|
||||
return CreateExternalArray(args, v8::kExternalIntArray, sizeof(int32_t));
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> Uint32Array(const v8::Arguments& args) {
|
||||
return CreateExternalArray(args, v8::kExternalUnsignedIntArray,
|
||||
sizeof(uint32_t));
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> Float32Array(const v8::Arguments& args) {
|
||||
return CreateExternalArray(args, v8::kExternalFloatArray,
|
||||
sizeof(float)); // NOLINT
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> Float64Array(const v8::Arguments& args) {
|
||||
return CreateExternalArray(args, v8::kExternalDoubleArray,
|
||||
sizeof(double)); // NOLINT
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> PixelArray(const v8::Arguments& args) {
|
||||
return CreateExternalArray(args, v8::kExternalPixelArray, sizeof(uint8_t));
|
||||
}
|
||||
|
||||
|
||||
// Reads a file into a v8 string.
|
||||
v8::Handle<v8::String> ReadFile(const char* name) {
|
||||
FILE* file = fopen(name, "rb");
|
||||
@ -625,9 +212,41 @@ v8::Handle<v8::String> ReadFile(const char* name) {
|
||||
}
|
||||
|
||||
|
||||
// Process remaining command line arguments and execute files
|
||||
int RunMain(int argc, char* argv[]) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
const char* str = argv[i];
|
||||
if (strcmp(str, "--shell") == 0) {
|
||||
run_shell = true;
|
||||
} else if (strcmp(str, "-f") == 0) {
|
||||
// Ignore any -f flags for compatibility with the other stand-
|
||||
// alone JavaScript engines.
|
||||
continue;
|
||||
} 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) {
|
||||
// Execute argument given to -e option directly.
|
||||
v8::Handle<v8::String> file_name = v8::String::New("unnamed");
|
||||
v8::Handle<v8::String> source = v8::String::New(argv[++i]);
|
||||
if (!ExecuteString(source, file_name, false, true)) return 1;
|
||||
} else {
|
||||
// Use all other arguments as names of files to load and run.
|
||||
v8::Handle<v8::String> file_name = v8::String::New(str);
|
||||
v8::Handle<v8::String> source = ReadFile(str);
|
||||
if (source.IsEmpty()) {
|
||||
printf("Error reading '%s'\n", str);
|
||||
continue;
|
||||
}
|
||||
if (!ExecuteString(source, file_name, false, true)) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// The read-eval-execute loop of the shell.
|
||||
void RunShell(v8::Handle<v8::Context> context) {
|
||||
printf("V8 version %s\n", v8::V8::GetVersion());
|
||||
printf("V8 version %s [sample shell]\n", v8::V8::GetVersion());
|
||||
static const int kBufferSize = 256;
|
||||
// Enter the execution environment before evaluating any code.
|
||||
v8::Context::Scope context_scope(context);
|
||||
|
4
deps/v8/src/api.h
vendored
4
deps/v8/src/api.h
vendored
@ -406,6 +406,10 @@ class HandleScopeImplementer {
|
||||
spare_(NULL),
|
||||
call_depth_(0) { }
|
||||
|
||||
~HandleScopeImplementer() {
|
||||
DeleteArray(spare_);
|
||||
}
|
||||
|
||||
// Threading support for handle data.
|
||||
static int ArchiveSpacePerThread();
|
||||
char* RestoreThread(char* from);
|
||||
|
12
deps/v8/src/arm/full-codegen-arm.cc
vendored
12
deps/v8/src/arm/full-codegen-arm.cc
vendored
@ -878,7 +878,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
__ bind(&next_test);
|
||||
__ Drop(1); // Switch value is no longer needed.
|
||||
if (default_clause == NULL) {
|
||||
__ b(nested_statement.break_target());
|
||||
__ b(nested_statement.break_label());
|
||||
} else {
|
||||
__ b(default_clause->body_target());
|
||||
}
|
||||
@ -892,7 +892,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
VisitStatements(clause->statements());
|
||||
}
|
||||
|
||||
__ bind(nested_statement.break_target());
|
||||
__ bind(nested_statement.break_label());
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
}
|
||||
|
||||
@ -1023,7 +1023,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// Load the current count to r0, load the length to r1.
|
||||
__ Ldrd(r0, r1, MemOperand(sp, 0 * kPointerSize));
|
||||
__ cmp(r0, r1); // Compare to the array length.
|
||||
__ b(hs, loop_statement.break_target());
|
||||
__ b(hs, loop_statement.break_label());
|
||||
|
||||
// Get the current entry of the array into register r3.
|
||||
__ ldr(r2, MemOperand(sp, 2 * kPointerSize));
|
||||
@ -1049,7 +1049,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ push(r3); // Current entry.
|
||||
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
|
||||
__ mov(r3, Operand(r0), SetCC);
|
||||
__ b(eq, loop_statement.continue_target());
|
||||
__ b(eq, loop_statement.continue_label());
|
||||
|
||||
// Update the 'each' property or variable from the possibly filtered
|
||||
// entry in register r3.
|
||||
@ -1065,7 +1065,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Generate code for the going to the next element by incrementing
|
||||
// the index (smi) stored on top of the stack.
|
||||
__ bind(loop_statement.continue_target());
|
||||
__ bind(loop_statement.continue_label());
|
||||
__ pop(r0);
|
||||
__ add(r0, r0, Operand(Smi::FromInt(1)));
|
||||
__ push(r0);
|
||||
@ -1074,7 +1074,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ b(&loop);
|
||||
|
||||
// Remove the pointers stored on the stack.
|
||||
__ bind(loop_statement.break_target());
|
||||
__ bind(loop_statement.break_label());
|
||||
__ Drop(5);
|
||||
|
||||
// Exit and decrement the loop depth.
|
||||
|
12
deps/v8/src/d8.js
vendored
12
deps/v8/src/d8.js
vendored
@ -392,14 +392,14 @@ function DebugRequest(cmd_line) {
|
||||
this.frameCommandToJSONRequest_('' +
|
||||
(Debug.State.currentFrame + 1));
|
||||
break;
|
||||
|
||||
|
||||
case 'down':
|
||||
case 'do':
|
||||
this.request_ =
|
||||
this.frameCommandToJSONRequest_('' +
|
||||
(Debug.State.currentFrame - 1));
|
||||
break;
|
||||
|
||||
|
||||
case 'set':
|
||||
case 'print':
|
||||
case 'p':
|
||||
@ -1072,7 +1072,7 @@ DebugRequest.prototype.changeBreakpointCommandToJSONRequest_ =
|
||||
arg2 = 'uncaught';
|
||||
}
|
||||
excType = arg2;
|
||||
|
||||
|
||||
// Check for:
|
||||
// en[able] [all|unc[aught]] exc[eptions]
|
||||
// dis[able] [all|unc[aught]] exc[eptions]
|
||||
@ -1131,7 +1131,7 @@ DebugRequest.prototype.changeBreakpointCommandToJSONRequest_ =
|
||||
request.arguments.ignoreCount = parseInt(otherArgs);
|
||||
break;
|
||||
default:
|
||||
throw new Error('Invalid arguments.');
|
||||
throw new Error('Invalid arguments.');
|
||||
}
|
||||
} else {
|
||||
throw new Error('Invalid arguments.');
|
||||
@ -1252,7 +1252,7 @@ DebugRequest.prototype.lolMakeListRequest =
|
||||
start_index = parseInt(args[i]);
|
||||
// The user input start index starts at 1:
|
||||
if (start_index <= 0) {
|
||||
throw new Error('Invalid index ' + args[i] + '.');
|
||||
throw new Error('Invalid index ' + args[i] + '.');
|
||||
}
|
||||
start_index -= 1;
|
||||
is_verbose = true;
|
||||
@ -2021,7 +2021,7 @@ function DebugResponseDetails(response) {
|
||||
} else if (body.breakOnUncaughtExceptions) {
|
||||
result += '* breaking on UNCAUGHT exceptions is enabled\n';
|
||||
} else {
|
||||
result += '* all exception breakpoints are disabled\n';
|
||||
result += '* all exception breakpoints are disabled\n';
|
||||
}
|
||||
details.text = result;
|
||||
break;
|
||||
|
20
deps/v8/src/debug-debugger.js
vendored
20
deps/v8/src/debug-debugger.js
vendored
@ -404,7 +404,7 @@ ScriptBreakPoint.prototype.matchesScript = function(script) {
|
||||
return this.script_name_ == script.nameOrSourceURL();
|
||||
} else if (this.type_ == Debug.ScriptBreakPointType.ScriptRegExp) {
|
||||
return this.script_regexp_object_.test(script.nameOrSourceURL());
|
||||
} else {
|
||||
} else {
|
||||
throw new Error("Unexpected breakpoint type " + this.type_);
|
||||
}
|
||||
}
|
||||
@ -1579,7 +1579,7 @@ DebugCommandProcessor.prototype.setBreakPointRequest_ =
|
||||
response.failed('Missing argument "type" or "target"');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Either function or script break point.
|
||||
var break_point_number;
|
||||
if (type == 'function') {
|
||||
@ -1623,10 +1623,10 @@ DebugCommandProcessor.prototype.setBreakPointRequest_ =
|
||||
break_point_number =
|
||||
Debug.setScriptBreakPointByName(target, line, column, condition,
|
||||
groupId);
|
||||
} else if (type == 'scriptId') {
|
||||
} else if (type == 'scriptId') {
|
||||
break_point_number =
|
||||
Debug.setScriptBreakPointById(target, line, column, condition, groupId);
|
||||
} else if (type == 'scriptRegExp') {
|
||||
} else if (type == 'scriptRegExp') {
|
||||
break_point_number =
|
||||
Debug.setScriptBreakPointByRegExp(target, line, column, condition,
|
||||
groupId);
|
||||
@ -1797,7 +1797,7 @@ DebugCommandProcessor.prototype.listBreakpointsRequest_ = function(request, resp
|
||||
description.type = 'scriptRegExp';
|
||||
description.script_regexp = break_point.script_regexp_object().source;
|
||||
} else {
|
||||
throw new Error("Internal error: Unexpected breakpoint type: " + break_point.type());
|
||||
throw new Error("Internal error: Unexpected breakpoint type: " + break_point.type());
|
||||
}
|
||||
array.push(description);
|
||||
}
|
||||
@ -1838,7 +1838,7 @@ DebugCommandProcessor.prototype.setExceptionBreakRequest_ =
|
||||
enabled = !Debug.isBreakOnException();
|
||||
} else if (type == 'uncaught') {
|
||||
enabled = !Debug.isBreakOnUncaughtException();
|
||||
}
|
||||
}
|
||||
|
||||
// Pull out and check the 'enabled' argument if present:
|
||||
if (!IS_UNDEFINED(request.arguments.enabled)) {
|
||||
@ -2022,22 +2022,22 @@ DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
|
||||
if (!IS_UNDEFINED(frame) && global) {
|
||||
return response.failed('Arguments "frame" and "global" are exclusive');
|
||||
}
|
||||
|
||||
|
||||
var additional_context_object;
|
||||
if (additional_context) {
|
||||
additional_context_object = {};
|
||||
for (var i = 0; i < additional_context.length; i++) {
|
||||
var mapping = additional_context[i];
|
||||
if (!IS_STRING(mapping.name) || !IS_NUMBER(mapping.handle)) {
|
||||
return response.failed("Context element #" + i +
|
||||
return response.failed("Context element #" + i +
|
||||
" must contain name:string and handle:number");
|
||||
}
|
||||
}
|
||||
var context_value_mirror = LookupMirror(mapping.handle);
|
||||
if (!context_value_mirror) {
|
||||
return response.failed("Context object '" + mapping.name +
|
||||
"' #" + mapping.handle + "# not found");
|
||||
}
|
||||
additional_context_object[mapping.name] = context_value_mirror.value();
|
||||
additional_context_object[mapping.name] = context_value_mirror.value();
|
||||
}
|
||||
}
|
||||
|
||||
|
373
deps/v8/src/elements.cc
vendored
373
deps/v8/src/elements.cc
vendored
@ -29,6 +29,7 @@
|
||||
|
||||
#include "objects.h"
|
||||
#include "elements.h"
|
||||
#include "utils.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -70,24 +71,34 @@ bool HasKey(FixedArray* array, Object* key) {
|
||||
// specialization of SomeElementsAccessor methods).
|
||||
template <typename ElementsAccessorSubclass, typename BackingStoreClass>
|
||||
class ElementsAccessorBase : public ElementsAccessor {
|
||||
public:
|
||||
protected:
|
||||
ElementsAccessorBase() { }
|
||||
virtual MaybeObject* GetWithReceiver(JSObject* obj,
|
||||
Object* receiver,
|
||||
uint32_t index) {
|
||||
BackingStoreClass* backing_store = BackingStoreClass::cast(obj->elements());
|
||||
if (index < ElementsAccessorSubclass::GetLength(backing_store)) {
|
||||
return backing_store->get(index);
|
||||
virtual MaybeObject* Get(FixedArrayBase* backing_store,
|
||||
uint32_t key,
|
||||
JSObject* obj,
|
||||
Object* receiver) {
|
||||
return ElementsAccessorSubclass::Get(
|
||||
BackingStoreClass::cast(backing_store), key, obj, receiver);
|
||||
}
|
||||
|
||||
static MaybeObject* Get(BackingStoreClass* backing_store,
|
||||
uint32_t key,
|
||||
JSObject* obj,
|
||||
Object* receiver) {
|
||||
if (key < ElementsAccessorSubclass::GetCapacity(backing_store)) {
|
||||
return backing_store->get(key);
|
||||
}
|
||||
return obj->GetHeap()->the_hole_value();
|
||||
return backing_store->GetHeap()->the_hole_value();
|
||||
}
|
||||
|
||||
virtual MaybeObject* Delete(JSObject* obj,
|
||||
uint32_t index,
|
||||
uint32_t key,
|
||||
JSReceiver::DeleteMode mode) = 0;
|
||||
|
||||
virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from,
|
||||
FixedArray* to) {
|
||||
FixedArray* to,
|
||||
JSObject* holder,
|
||||
Object* receiver) {
|
||||
int len0 = to->length();
|
||||
#ifdef DEBUG
|
||||
if (FLAG_enable_slow_asserts) {
|
||||
@ -97,7 +108,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
||||
}
|
||||
#endif
|
||||
BackingStoreClass* backing_store = BackingStoreClass::cast(from);
|
||||
int len1 = ElementsAccessorSubclass::GetCapacity(backing_store);
|
||||
uint32_t len1 = ElementsAccessorSubclass::GetCapacity(backing_store);
|
||||
|
||||
// Optimize if 'other' is empty.
|
||||
// We cannot optimize if 'this' is empty, as other may have holes.
|
||||
@ -105,12 +116,22 @@ class ElementsAccessorBase : public ElementsAccessor {
|
||||
|
||||
// Compute how many elements are not in other.
|
||||
int extra = 0;
|
||||
for (int y = 0; y < len1; y++) {
|
||||
Object* value;
|
||||
MaybeObject* maybe_value =
|
||||
ElementsAccessorSubclass::GetElementAtCapacityIndex(backing_store, y);
|
||||
if (!maybe_value->ToObject(&value)) return maybe_value;
|
||||
if (!value->IsTheHole() && !HasKey(to, value)) extra++;
|
||||
for (uint32_t y = 0; y < len1; y++) {
|
||||
if (ElementsAccessorSubclass::HasElementAtIndex(backing_store,
|
||||
y,
|
||||
holder,
|
||||
receiver)) {
|
||||
uint32_t key =
|
||||
ElementsAccessorSubclass::GetKeyForIndex(backing_store, y);
|
||||
MaybeObject* maybe_value =
|
||||
ElementsAccessorSubclass::Get(backing_store, key, holder, receiver);
|
||||
Object* value;
|
||||
if (!maybe_value->ToObject(&value)) return maybe_value;
|
||||
ASSERT(!value->IsTheHole());
|
||||
if (!HasKey(to, value)) {
|
||||
extra++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (extra == 0) return to;
|
||||
@ -133,32 +154,67 @@ class ElementsAccessorBase : public ElementsAccessor {
|
||||
}
|
||||
// Fill in the extra values.
|
||||
int index = 0;
|
||||
for (int y = 0; y < len1; y++) {
|
||||
MaybeObject* maybe_value =
|
||||
ElementsAccessorSubclass::GetElementAtCapacityIndex(backing_store, y);
|
||||
Object* value;
|
||||
if (!maybe_value->ToObject(&value)) return maybe_value;
|
||||
if (!value->IsTheHole() && !HasKey(to, value)) {
|
||||
result->set(len0 + index, value);
|
||||
index++;
|
||||
for (uint32_t y = 0; y < len1; y++) {
|
||||
if (ElementsAccessorSubclass::HasElementAtIndex(backing_store,
|
||||
y,
|
||||
holder,
|
||||
receiver)) {
|
||||
uint32_t key =
|
||||
ElementsAccessorSubclass::GetKeyForIndex(backing_store, y);
|
||||
MaybeObject* maybe_value =
|
||||
ElementsAccessorSubclass::Get(backing_store, key, holder, receiver);
|
||||
Object* value;
|
||||
if (!maybe_value->ToObject(&value)) return maybe_value;
|
||||
if (!value->IsTheHole() && !HasKey(to, value)) {
|
||||
result->set(len0 + index, value);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ASSERT(extra == index);
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t GetLength(BackingStoreClass* backing_store) {
|
||||
protected:
|
||||
static uint32_t GetCapacity(BackingStoreClass* backing_store) {
|
||||
return backing_store->length();
|
||||
}
|
||||
|
||||
static uint32_t GetCapacity(BackingStoreClass* backing_store) {
|
||||
return GetLength(backing_store);
|
||||
virtual uint32_t GetCapacity(FixedArrayBase* backing_store) {
|
||||
return ElementsAccessorSubclass::GetCapacity(
|
||||
BackingStoreClass::cast(backing_store));
|
||||
}
|
||||
|
||||
static MaybeObject* GetElementAtCapacityIndex(
|
||||
BackingStoreClass* backing_store,
|
||||
int index) {
|
||||
return backing_store->get(index);
|
||||
static bool HasElementAtIndex(BackingStoreClass* backing_store,
|
||||
uint32_t index,
|
||||
JSObject* holder,
|
||||
Object* receiver) {
|
||||
uint32_t key =
|
||||
ElementsAccessorSubclass::GetKeyForIndex(backing_store, index);
|
||||
MaybeObject* element = ElementsAccessorSubclass::Get(backing_store,
|
||||
key,
|
||||
holder,
|
||||
receiver);
|
||||
return !element->IsTheHole();
|
||||
}
|
||||
|
||||
virtual bool HasElementAtIndex(FixedArrayBase* backing_store,
|
||||
uint32_t index,
|
||||
JSObject* holder,
|
||||
Object* receiver) {
|
||||
return ElementsAccessorSubclass::HasElementAtIndex(
|
||||
BackingStoreClass::cast(backing_store), index, holder, receiver);
|
||||
}
|
||||
|
||||
static uint32_t GetKeyForIndex(BackingStoreClass* backing_store,
|
||||
uint32_t index) {
|
||||
return index;
|
||||
}
|
||||
|
||||
virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
|
||||
uint32_t index) {
|
||||
return ElementsAccessorSubclass::GetKeyForIndex(
|
||||
BackingStoreClass::cast(backing_store), index);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -170,7 +226,7 @@ class FastElementsAccessor
|
||||
: public ElementsAccessorBase<FastElementsAccessor, FixedArray> {
|
||||
public:
|
||||
static MaybeObject* DeleteCommon(JSObject* obj,
|
||||
uint32_t index) {
|
||||
uint32_t key) {
|
||||
ASSERT(obj->HasFastElements() || obj->HasFastArgumentsElements());
|
||||
Heap* heap = obj->GetHeap();
|
||||
FixedArray* backing_store = FixedArray::cast(obj->elements());
|
||||
@ -186,8 +242,8 @@ class FastElementsAccessor
|
||||
obj->IsJSArray()
|
||||
? Smi::cast(JSArray::cast(obj)->length())->value()
|
||||
: backing_store->length());
|
||||
if (index < length) {
|
||||
backing_store->set_the_hole(index);
|
||||
if (key < length) {
|
||||
backing_store->set_the_hole(key);
|
||||
// If an old space backing store is larger than a certain size and
|
||||
// has too few used values, normalize it.
|
||||
// To avoid doing the check on every delete we require at least
|
||||
@ -196,8 +252,8 @@ class FastElementsAccessor
|
||||
const int kMinLengthForSparsenessCheck = 64;
|
||||
if (backing_store->length() >= kMinLengthForSparsenessCheck &&
|
||||
!heap->InNewSpace(backing_store) &&
|
||||
((index > 0 && backing_store->get(index - 1) == hole) ||
|
||||
(index + 1 < length && backing_store->get(index + 1) == hole))) {
|
||||
((key > 0 && backing_store->get(key - 1) == hole) ||
|
||||
(key + 1 < length && backing_store->get(key + 1) == hole))) {
|
||||
int num_used = 0;
|
||||
for (int i = 0; i < backing_store->length(); ++i) {
|
||||
if (backing_store->get(i) != hole) ++num_used;
|
||||
@ -213,10 +269,11 @@ class FastElementsAccessor
|
||||
return heap->true_value();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual MaybeObject* Delete(JSObject* obj,
|
||||
uint32_t index,
|
||||
uint32_t key,
|
||||
JSReceiver::DeleteMode mode) {
|
||||
return DeleteCommon(obj, index);
|
||||
return DeleteCommon(obj, key);
|
||||
}
|
||||
};
|
||||
|
||||
@ -224,17 +281,28 @@ class FastElementsAccessor
|
||||
class FastDoubleElementsAccessor
|
||||
: public ElementsAccessorBase<FastDoubleElementsAccessor,
|
||||
FixedDoubleArray> {
|
||||
protected:
|
||||
friend class ElementsAccessorBase<FastDoubleElementsAccessor,
|
||||
FixedDoubleArray>;
|
||||
|
||||
virtual MaybeObject* Delete(JSObject* obj,
|
||||
uint32_t index,
|
||||
uint32_t key,
|
||||
JSReceiver::DeleteMode mode) {
|
||||
int length = obj->IsJSArray()
|
||||
? Smi::cast(JSArray::cast(obj)->length())->value()
|
||||
: FixedDoubleArray::cast(obj->elements())->length();
|
||||
if (index < static_cast<uint32_t>(length)) {
|
||||
FixedDoubleArray::cast(obj->elements())->set_the_hole(index);
|
||||
if (key < static_cast<uint32_t>(length)) {
|
||||
FixedDoubleArray::cast(obj->elements())->set_the_hole(key);
|
||||
}
|
||||
return obj->GetHeap()->true_value();
|
||||
}
|
||||
|
||||
static bool HasElementAtIndex(FixedDoubleArray* backing_store,
|
||||
uint32_t index,
|
||||
JSObject* holder,
|
||||
Object* receiver) {
|
||||
return !backing_store->is_the_hole(index);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -244,20 +312,23 @@ template<typename ExternalElementsAccessorSubclass,
|
||||
class ExternalElementsAccessor
|
||||
: public ElementsAccessorBase<ExternalElementsAccessorSubclass,
|
||||
ExternalArray> {
|
||||
public:
|
||||
virtual MaybeObject* GetWithReceiver(JSObject* obj,
|
||||
Object* receiver,
|
||||
uint32_t index) {
|
||||
ExternalArray* backing_store = ExternalArray::cast(obj->elements());
|
||||
if (index < ExternalElementsAccessorSubclass::GetLength(backing_store)) {
|
||||
return backing_store->get(index);
|
||||
protected:
|
||||
friend class ElementsAccessorBase<ExternalElementsAccessorSubclass,
|
||||
ExternalArray>;
|
||||
|
||||
static MaybeObject* Get(ExternalArray* backing_store,
|
||||
uint32_t key,
|
||||
JSObject* obj,
|
||||
Object* receiver) {
|
||||
if (key < ExternalElementsAccessorSubclass::GetCapacity(backing_store)) {
|
||||
return backing_store->get(key);
|
||||
} else {
|
||||
return obj->GetHeap()->undefined_value();
|
||||
return backing_store->GetHeap()->undefined_value();
|
||||
}
|
||||
}
|
||||
|
||||
virtual MaybeObject* Delete(JSObject* obj,
|
||||
uint32_t index,
|
||||
uint32_t key,
|
||||
JSReceiver::DeleteMode mode) {
|
||||
// External arrays always ignore deletes.
|
||||
return obj->GetHeap()->true_value();
|
||||
@ -323,30 +394,8 @@ class DictionaryElementsAccessor
|
||||
: public ElementsAccessorBase<DictionaryElementsAccessor,
|
||||
NumberDictionary> {
|
||||
public:
|
||||
static MaybeObject* GetNumberDictionaryElement(
|
||||
JSObject* obj,
|
||||
Object* receiver,
|
||||
NumberDictionary* backing_store,
|
||||
uint32_t index) {
|
||||
int entry = backing_store->FindEntry(index);
|
||||
if (entry != NumberDictionary::kNotFound) {
|
||||
Object* element = backing_store->ValueAt(entry);
|
||||
PropertyDetails details = backing_store->DetailsAt(entry);
|
||||
if (details.type() == CALLBACKS) {
|
||||
return obj->GetElementWithCallback(receiver,
|
||||
element,
|
||||
index,
|
||||
obj);
|
||||
} else {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return obj->GetHeap()->the_hole_value();
|
||||
}
|
||||
|
||||
|
||||
static MaybeObject* DeleteCommon(JSObject* obj,
|
||||
uint32_t index,
|
||||
uint32_t key,
|
||||
JSReceiver::DeleteMode mode) {
|
||||
Isolate* isolate = obj->GetIsolate();
|
||||
Heap* heap = isolate->heap();
|
||||
@ -357,11 +406,11 @@ class DictionaryElementsAccessor
|
||||
backing_store = FixedArray::cast(backing_store->get(1));
|
||||
}
|
||||
NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
|
||||
int entry = dictionary->FindEntry(index);
|
||||
int entry = dictionary->FindEntry(key);
|
||||
if (entry != NumberDictionary::kNotFound) {
|
||||
Object* result = dictionary->DeleteProperty(entry, mode);
|
||||
if (result == heap->true_value()) {
|
||||
MaybeObject* maybe_elements = dictionary->Shrink(index);
|
||||
MaybeObject* maybe_elements = dictionary->Shrink(key);
|
||||
FixedArray* new_elements = NULL;
|
||||
if (!maybe_elements->To(&new_elements)) {
|
||||
return maybe_elements;
|
||||
@ -378,7 +427,7 @@ class DictionaryElementsAccessor
|
||||
// throws an exception.
|
||||
HandleScope scope(isolate);
|
||||
Handle<Object> holder(obj);
|
||||
Handle<Object> name = isolate->factory()->NewNumberFromUint(index);
|
||||
Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
|
||||
Handle<Object> args[2] = { name, holder };
|
||||
Handle<Object> error =
|
||||
isolate->factory()->NewTypeError("strict_delete_property",
|
||||
@ -389,32 +438,40 @@ class DictionaryElementsAccessor
|
||||
return heap->true_value();
|
||||
}
|
||||
|
||||
protected:
|
||||
friend class ElementsAccessorBase<DictionaryElementsAccessor,
|
||||
NumberDictionary>;
|
||||
|
||||
virtual MaybeObject* Delete(JSObject* obj,
|
||||
uint32_t index,
|
||||
uint32_t key,
|
||||
JSReceiver::DeleteMode mode) {
|
||||
return DeleteCommon(obj, index, mode);
|
||||
return DeleteCommon(obj, key, mode);
|
||||
}
|
||||
|
||||
virtual MaybeObject* GetWithReceiver(JSObject* obj,
|
||||
Object* receiver,
|
||||
uint32_t index) {
|
||||
return GetNumberDictionaryElement(obj,
|
||||
receiver,
|
||||
obj->element_dictionary(),
|
||||
index);
|
||||
}
|
||||
|
||||
static uint32_t GetCapacity(NumberDictionary* dict) {
|
||||
return dict->Capacity();
|
||||
}
|
||||
|
||||
static MaybeObject* GetElementAtCapacityIndex(NumberDictionary* dict,
|
||||
int index) {
|
||||
if (dict->IsKey(dict->KeyAt(index))) {
|
||||
return dict->ValueAt(index);
|
||||
} else {
|
||||
return dict->GetHeap()->the_hole_value();
|
||||
static MaybeObject* Get(NumberDictionary* backing_store,
|
||||
uint32_t key,
|
||||
JSObject* obj,
|
||||
Object* receiver) {
|
||||
int entry = backing_store->FindEntry(key);
|
||||
if (entry != NumberDictionary::kNotFound) {
|
||||
Object* element = backing_store->ValueAt(entry);
|
||||
PropertyDetails details = backing_store->DetailsAt(entry);
|
||||
if (details.type() == CALLBACKS) {
|
||||
return obj->GetElementWithCallback(receiver,
|
||||
element,
|
||||
key,
|
||||
obj);
|
||||
} else {
|
||||
return element;
|
||||
}
|
||||
}
|
||||
return obj->GetHeap()->the_hole_value();
|
||||
}
|
||||
|
||||
static uint32_t GetKeyForIndex(NumberDictionary* dict,
|
||||
uint32_t index) {
|
||||
Object* key = dict->KeyAt(index);
|
||||
return Smi::cast(key)->value();
|
||||
}
|
||||
};
|
||||
|
||||
@ -422,15 +479,16 @@ class DictionaryElementsAccessor
|
||||
class NonStrictArgumentsElementsAccessor
|
||||
: public ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
|
||||
FixedArray> {
|
||||
public:
|
||||
virtual MaybeObject* GetWithReceiver(JSObject* obj,
|
||||
Object* receiver,
|
||||
uint32_t index) {
|
||||
FixedArray* parameter_map = FixedArray::cast(obj->elements());
|
||||
uint32_t length = parameter_map->length();
|
||||
Object* probe =
|
||||
(index < length - 2) ? parameter_map->get(index + 2) : NULL;
|
||||
if (probe != NULL && !probe->IsTheHole()) {
|
||||
protected:
|
||||
friend class ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
|
||||
FixedArray>;
|
||||
|
||||
static MaybeObject* Get(FixedArray* parameter_map,
|
||||
uint32_t key,
|
||||
JSObject* obj,
|
||||
Object* receiver) {
|
||||
Object* probe = GetParameterMapArg(parameter_map, key);
|
||||
if (!probe->IsTheHole()) {
|
||||
Context* context = Context::cast(parameter_map->get(0));
|
||||
int context_index = Smi::cast(probe)->value();
|
||||
ASSERT(!context->get(context_index)->IsTheHole());
|
||||
@ -438,56 +496,105 @@ class NonStrictArgumentsElementsAccessor
|
||||
} else {
|
||||
// Object is not mapped, defer to the arguments.
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
if (arguments->IsDictionary()) {
|
||||
return DictionaryElementsAccessor::GetNumberDictionaryElement(
|
||||
obj,
|
||||
receiver,
|
||||
NumberDictionary::cast(arguments),
|
||||
index);
|
||||
} else if (index < static_cast<uint32_t>(arguments->length())) {
|
||||
return arguments->get(index);
|
||||
}
|
||||
return ElementsAccessor::ForArray(arguments)->Get(arguments,
|
||||
key,
|
||||
obj,
|
||||
receiver);
|
||||
}
|
||||
return obj->GetHeap()->the_hole_value();
|
||||
}
|
||||
|
||||
virtual MaybeObject* Delete(JSObject* obj,
|
||||
uint32_t index,
|
||||
uint32_t key
|
||||
,
|
||||
JSReceiver::DeleteMode mode) {
|
||||
FixedArray* parameter_map = FixedArray::cast(obj->elements());
|
||||
uint32_t length = parameter_map->length();
|
||||
Object* probe =
|
||||
index < (length - 2) ? parameter_map->get(index + 2) : NULL;
|
||||
if (probe != NULL && !probe->IsTheHole()) {
|
||||
Object* probe = GetParameterMapArg(parameter_map, key);
|
||||
if (!probe->IsTheHole()) {
|
||||
// TODO(kmillikin): We could check if this was the last aliased
|
||||
// parameter, and revert to normal elements in that case. That
|
||||
// would enable GC of the context.
|
||||
parameter_map->set_the_hole(index + 2);
|
||||
parameter_map->set_the_hole(key + 2);
|
||||
} else {
|
||||
FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
||||
if (arguments->IsDictionary()) {
|
||||
return DictionaryElementsAccessor::DeleteCommon(obj, index, mode);
|
||||
return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
|
||||
} else {
|
||||
return FastElementsAccessor::DeleteCommon(obj, index);
|
||||
return FastElementsAccessor::DeleteCommon(obj, key);
|
||||
}
|
||||
}
|
||||
return obj->GetHeap()->true_value();
|
||||
}
|
||||
|
||||
static uint32_t GetCapacity(FixedArray* obj) {
|
||||
// TODO(danno): Return max of parameter map length or backing store
|
||||
// capacity.
|
||||
return 0;
|
||||
static uint32_t GetCapacity(FixedArray* parameter_map) {
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
return Max(static_cast<uint32_t>(parameter_map->length() - 2),
|
||||
ForArray(arguments)->GetCapacity(arguments));
|
||||
}
|
||||
|
||||
static MaybeObject* GetElementAtCapacityIndex(FixedArray* obj, int index) {
|
||||
// TODO(danno): Return either value from parameter map of backing
|
||||
// store value at index.
|
||||
return obj->GetHeap()->the_hole_value();
|
||||
static uint32_t GetKeyForIndex(FixedArray* dict,
|
||||
uint32_t index) {
|
||||
return index;
|
||||
}
|
||||
|
||||
static bool HasElementAtIndex(FixedArray* parameter_map,
|
||||
uint32_t index,
|
||||
JSObject* holder,
|
||||
Object* receiver) {
|
||||
Object* probe = GetParameterMapArg(parameter_map, index);
|
||||
if (!probe->IsTheHole()) {
|
||||
return true;
|
||||
} else {
|
||||
FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
||||
ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
|
||||
return !accessor->Get(arguments, index, holder, receiver)->IsTheHole();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static Object* GetParameterMapArg(FixedArray* parameter_map,
|
||||
uint32_t key) {
|
||||
uint32_t length = parameter_map->length();
|
||||
return key < (length - 2 )
|
||||
? parameter_map->get(key + 2)
|
||||
: parameter_map->GetHeap()->the_hole_value();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
|
||||
switch (array->map()->instance_type()) {
|
||||
case FIXED_ARRAY_TYPE:
|
||||
if (array->IsDictionary()) {
|
||||
return elements_accessors_[JSObject::DICTIONARY_ELEMENTS];
|
||||
} else {
|
||||
return elements_accessors_[JSObject::FAST_ELEMENTS];
|
||||
}
|
||||
case EXTERNAL_BYTE_ARRAY_TYPE:
|
||||
return elements_accessors_[JSObject::EXTERNAL_BYTE_ELEMENTS];
|
||||
case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
|
||||
return elements_accessors_[JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS];
|
||||
case EXTERNAL_SHORT_ARRAY_TYPE:
|
||||
return elements_accessors_[JSObject::EXTERNAL_SHORT_ELEMENTS];
|
||||
case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
|
||||
return elements_accessors_[JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS];
|
||||
case EXTERNAL_INT_ARRAY_TYPE:
|
||||
return elements_accessors_[JSObject::EXTERNAL_INT_ELEMENTS];
|
||||
case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
|
||||
return elements_accessors_[JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS];
|
||||
case EXTERNAL_FLOAT_ARRAY_TYPE:
|
||||
return elements_accessors_[JSObject::EXTERNAL_FLOAT_ELEMENTS];
|
||||
case EXTERNAL_DOUBLE_ARRAY_TYPE:
|
||||
return elements_accessors_[JSObject::EXTERNAL_DOUBLE_ELEMENTS];
|
||||
case EXTERNAL_PIXEL_ARRAY_TYPE:
|
||||
return elements_accessors_[JSObject::EXTERNAL_PIXEL_ELEMENTS];
|
||||
default:
|
||||
UNREACHABLE();
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ElementsAccessor::InitializeOncePerProcess() {
|
||||
static struct ConcreteElementsAccessors {
|
||||
FastElementsAccessor fast_elements_handler;
|
||||
|
38
deps/v8/src/elements.h
vendored
38
deps/v8/src/elements.h
vendored
@ -39,16 +39,19 @@ class ElementsAccessor {
|
||||
public:
|
||||
ElementsAccessor() { }
|
||||
virtual ~ElementsAccessor() { }
|
||||
virtual MaybeObject* GetWithReceiver(JSObject* obj,
|
||||
Object* receiver,
|
||||
uint32_t index) = 0;
|
||||
virtual MaybeObject* Get(FixedArrayBase* backing_store,
|
||||
uint32_t key,
|
||||
JSObject* holder,
|
||||
Object* receiver) = 0;
|
||||
|
||||
virtual MaybeObject* Delete(JSObject* obj,
|
||||
uint32_t index,
|
||||
virtual MaybeObject* Delete(JSObject* holder,
|
||||
uint32_t key,
|
||||
JSReceiver::DeleteMode mode) = 0;
|
||||
|
||||
virtual MaybeObject* AddElementsToFixedArray(FixedArrayBase* from,
|
||||
FixedArray* to) = 0;
|
||||
FixedArray* to,
|
||||
JSObject* holder,
|
||||
Object* receiver) = 0;
|
||||
|
||||
// Returns a shared ElementsAccessor for the specified ElementsKind.
|
||||
static ElementsAccessor* ForKind(JSObject::ElementsKind elements_kind) {
|
||||
@ -56,8 +59,31 @@ class ElementsAccessor {
|
||||
return elements_accessors_[elements_kind];
|
||||
}
|
||||
|
||||
static ElementsAccessor* ForArray(FixedArrayBase* array);
|
||||
|
||||
static void InitializeOncePerProcess();
|
||||
|
||||
protected:
|
||||
friend class NonStrictArgumentsElementsAccessor;
|
||||
|
||||
virtual uint32_t GetCapacity(FixedArrayBase* backing_store) = 0;
|
||||
|
||||
virtual bool HasElementAtIndex(FixedArrayBase* backing_store,
|
||||
uint32_t index,
|
||||
JSObject* holder,
|
||||
Object* receiver) = 0;
|
||||
|
||||
// Element handlers distinguish between indexes and keys when the manipulate
|
||||
// elements. Indexes refer to elements in terms of their location in the
|
||||
// underlying storage's backing store representation, and are between 0
|
||||
// GetCapacity. Keys refer to elements in terms of the value that would be
|
||||
// specific in JavaScript to access the element. In most implementations, keys
|
||||
// are equivalent to indexes, and GetKeyForIndex returns the same value it is
|
||||
// passed. In the NumberDictionary ElementsAccessor, GetKeyForIndex maps the
|
||||
// index to a key using the KeyAt method on the NumberDictionary.
|
||||
virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
|
||||
uint32_t index) = 0;
|
||||
|
||||
private:
|
||||
static ElementsAccessor** elements_accessors_;
|
||||
|
||||
|
51
deps/v8/src/full-codegen.cc
vendored
51
deps/v8/src/full-codegen.cc
vendored
@ -862,7 +862,7 @@ void FullCodeGenerator::VisitBlock(Block* stmt) {
|
||||
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
|
||||
VisitStatements(stmt->statements());
|
||||
scope_ = saved_scope;
|
||||
__ bind(nested_statement.break_target());
|
||||
__ bind(nested_statement.break_label());
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
}
|
||||
|
||||
@ -932,8 +932,7 @@ void FullCodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
|
||||
context_register());
|
||||
}
|
||||
|
||||
Iteration* loop = current->AsIteration();
|
||||
__ jmp(loop->continue_target());
|
||||
__ jmp(current->AsIteration()->continue_label());
|
||||
}
|
||||
|
||||
|
||||
@ -961,8 +960,7 @@ void FullCodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
|
||||
context_register());
|
||||
}
|
||||
|
||||
Breakable* target = current->AsBreakable();
|
||||
__ jmp(target->break_target());
|
||||
__ jmp(current->AsBreakable()->break_label());
|
||||
}
|
||||
|
||||
|
||||
@ -1030,12 +1028,12 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
|
||||
// Record the position of the do while condition and make sure it is
|
||||
// possible to break on the condition.
|
||||
__ bind(loop_statement.continue_target());
|
||||
__ bind(loop_statement.continue_label());
|
||||
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
|
||||
SetExpressionPosition(stmt->cond(), stmt->condition_position());
|
||||
VisitForControl(stmt->cond(),
|
||||
&stack_check,
|
||||
loop_statement.break_target(),
|
||||
loop_statement.break_label(),
|
||||
&stack_check);
|
||||
|
||||
// Check stack before looping.
|
||||
@ -1045,7 +1043,7 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
|
||||
__ jmp(&body);
|
||||
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
__ bind(loop_statement.break_target());
|
||||
__ bind(loop_statement.break_label());
|
||||
decrement_loop_depth();
|
||||
}
|
||||
|
||||
@ -1066,7 +1064,7 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
|
||||
|
||||
// Emit the statement position here as this is where the while
|
||||
// statement code starts.
|
||||
__ bind(loop_statement.continue_target());
|
||||
__ bind(loop_statement.continue_label());
|
||||
SetStatementPosition(stmt);
|
||||
|
||||
// Check stack before looping.
|
||||
@ -1075,11 +1073,11 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
|
||||
__ bind(&test);
|
||||
VisitForControl(stmt->cond(),
|
||||
&body,
|
||||
loop_statement.break_target(),
|
||||
loop_statement.break_target());
|
||||
loop_statement.break_label(),
|
||||
loop_statement.break_label());
|
||||
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
__ bind(loop_statement.break_target());
|
||||
__ bind(loop_statement.break_label());
|
||||
decrement_loop_depth();
|
||||
}
|
||||
|
||||
@ -1102,7 +1100,7 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
||||
Visit(stmt->body());
|
||||
|
||||
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
|
||||
__ bind(loop_statement.continue_target());
|
||||
__ bind(loop_statement.continue_label());
|
||||
SetStatementPosition(stmt);
|
||||
if (stmt->next() != NULL) {
|
||||
Visit(stmt->next());
|
||||
@ -1119,14 +1117,14 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
|
||||
if (stmt->cond() != NULL) {
|
||||
VisitForControl(stmt->cond(),
|
||||
&body,
|
||||
loop_statement.break_target(),
|
||||
loop_statement.break_target());
|
||||
loop_statement.break_label(),
|
||||
loop_statement.break_label());
|
||||
} else {
|
||||
__ jmp(&body);
|
||||
}
|
||||
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
__ bind(loop_statement.break_target());
|
||||
__ bind(loop_statement.break_label());
|
||||
decrement_loop_depth();
|
||||
}
|
||||
|
||||
@ -1144,7 +1142,7 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
// to introduce a new scope to bind the catch variable and to remove
|
||||
// that scope again afterwards.
|
||||
|
||||
Label try_handler_setup, catch_entry, done;
|
||||
Label try_handler_setup, done;
|
||||
__ Call(&try_handler_setup);
|
||||
// Try handler code, exception in result register.
|
||||
|
||||
@ -1170,12 +1168,13 @@ void FullCodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
|
||||
// Try block code. Sets up the exception handler chain.
|
||||
__ bind(&try_handler_setup);
|
||||
{
|
||||
TryCatch try_block(this, &catch_entry);
|
||||
const int delta = StackHandlerConstants::kSize / kPointerSize;
|
||||
TryCatch try_block(this);
|
||||
__ PushTryHandler(IN_JAVASCRIPT, TRY_CATCH_HANDLER);
|
||||
increment_stack_height(StackHandlerConstants::kSize / kPointerSize);
|
||||
increment_stack_height(delta);
|
||||
Visit(stmt->try_block());
|
||||
__ PopTryHandler();
|
||||
decrement_stack_height(StackHandlerConstants::kSize / kPointerSize);
|
||||
decrement_stack_height(delta);
|
||||
}
|
||||
__ bind(&done);
|
||||
}
|
||||
@ -1208,9 +1207,6 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
Label finally_entry;
|
||||
Label try_handler_setup;
|
||||
const int original_stack_height = stack_height();
|
||||
const int finally_block_stack_height = original_stack_height + 2;
|
||||
const int try_block_stack_height = original_stack_height + 5;
|
||||
STATIC_ASSERT(StackHandlerConstants::kSize == 5 * kPointerSize);
|
||||
|
||||
// Setup the try-handler chain. Use a call to
|
||||
// Jump to try-handler setup and try-block code. Use call to put try-handler
|
||||
@ -1219,9 +1215,9 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
// Try handler code. Return address of call is pushed on handler stack.
|
||||
{
|
||||
// This code is only executed during stack-handler traversal when an
|
||||
// exception is thrown. The execption is in the result register, which
|
||||
// exception is thrown. The exception is in the result register, which
|
||||
// is retained by the finally block.
|
||||
// Call the finally block and then rethrow the exception.
|
||||
// Call the finally block and then rethrow the exception if it returns.
|
||||
__ Call(&finally_entry);
|
||||
__ push(result_register());
|
||||
__ CallRuntime(Runtime::kReThrow, 1);
|
||||
@ -1232,7 +1228,7 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
// Finally block implementation.
|
||||
Finally finally_block(this);
|
||||
EnterFinallyBlock();
|
||||
set_stack_height(finally_block_stack_height);
|
||||
set_stack_height(original_stack_height + Finally::kElementCount);
|
||||
Visit(stmt->finally_block());
|
||||
ExitFinallyBlock(); // Return to the calling code.
|
||||
}
|
||||
@ -1240,9 +1236,10 @@ void FullCodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
|
||||
__ bind(&try_handler_setup);
|
||||
{
|
||||
// Setup try handler (stack pointer registers).
|
||||
const int delta = StackHandlerConstants::kSize / kPointerSize;
|
||||
TryFinally try_block(this, &finally_entry);
|
||||
__ PushTryHandler(IN_JAVASCRIPT, TRY_FINALLY_HANDLER);
|
||||
set_stack_height(try_block_stack_height);
|
||||
set_stack_height(original_stack_height + delta);
|
||||
Visit(stmt->try_block());
|
||||
__ PopTryHandler();
|
||||
set_stack_height(original_stack_height);
|
||||
|
121
deps/v8/src/full-codegen.h
vendored
121
deps/v8/src/full-codegen.h
vendored
@ -111,10 +111,7 @@ class FullCodeGenerator: public AstVisitor {
|
||||
private:
|
||||
class Breakable;
|
||||
class Iteration;
|
||||
class TryCatch;
|
||||
class TryFinally;
|
||||
class Finally;
|
||||
class ForIn;
|
||||
|
||||
class TestContext;
|
||||
|
||||
class NestedStatement BASE_EMBEDDED {
|
||||
@ -132,10 +129,6 @@ class FullCodeGenerator: public AstVisitor {
|
||||
|
||||
virtual Breakable* AsBreakable() { return NULL; }
|
||||
virtual Iteration* AsIteration() { return NULL; }
|
||||
virtual TryCatch* AsTryCatch() { return NULL; }
|
||||
virtual TryFinally* AsTryFinally() { return NULL; }
|
||||
virtual Finally* AsFinally() { return NULL; }
|
||||
virtual ForIn* AsForIn() { return NULL; }
|
||||
|
||||
virtual bool IsContinueTarget(Statement* target) { return false; }
|
||||
virtual bool IsBreakTarget(Statement* target) { return false; }
|
||||
@ -158,110 +151,102 @@ class FullCodeGenerator: public AstVisitor {
|
||||
DISALLOW_COPY_AND_ASSIGN(NestedStatement);
|
||||
};
|
||||
|
||||
// A breakable statement such as a block.
|
||||
class Breakable : public NestedStatement {
|
||||
public:
|
||||
Breakable(FullCodeGenerator* codegen,
|
||||
BreakableStatement* break_target)
|
||||
: NestedStatement(codegen),
|
||||
target_(break_target) {}
|
||||
virtual ~Breakable() {}
|
||||
virtual Breakable* AsBreakable() { return this; }
|
||||
virtual bool IsBreakTarget(Statement* statement) {
|
||||
return target_ == statement;
|
||||
Breakable(FullCodeGenerator* codegen, BreakableStatement* statement)
|
||||
: NestedStatement(codegen), statement_(statement) {
|
||||
}
|
||||
BreakableStatement* statement() { return target_; }
|
||||
Label* break_target() { return &break_target_label_; }
|
||||
virtual ~Breakable() {}
|
||||
|
||||
virtual Breakable* AsBreakable() { return this; }
|
||||
virtual bool IsBreakTarget(Statement* target) {
|
||||
return statement() == target;
|
||||
}
|
||||
|
||||
BreakableStatement* statement() { return statement_; }
|
||||
Label* break_label() { return &break_label_; }
|
||||
|
||||
private:
|
||||
BreakableStatement* target_;
|
||||
Label break_target_label_;
|
||||
DISALLOW_COPY_AND_ASSIGN(Breakable);
|
||||
BreakableStatement* statement_;
|
||||
Label break_label_;
|
||||
};
|
||||
|
||||
// An iteration statement such as a while, for, or do loop.
|
||||
class Iteration : public Breakable {
|
||||
public:
|
||||
Iteration(FullCodeGenerator* codegen,
|
||||
IterationStatement* iteration_statement)
|
||||
: Breakable(codegen, iteration_statement) {}
|
||||
virtual ~Iteration() {}
|
||||
virtual Iteration* AsIteration() { return this; }
|
||||
virtual bool IsContinueTarget(Statement* statement) {
|
||||
return this->statement() == statement;
|
||||
Iteration(FullCodeGenerator* codegen, IterationStatement* statement)
|
||||
: Breakable(codegen, statement) {
|
||||
}
|
||||
Label* continue_target() { return &continue_target_label_; }
|
||||
virtual ~Iteration() {}
|
||||
|
||||
virtual Iteration* AsIteration() { return this; }
|
||||
virtual bool IsContinueTarget(Statement* target) {
|
||||
return statement() == target;
|
||||
}
|
||||
|
||||
Label* continue_label() { return &continue_label_; }
|
||||
|
||||
private:
|
||||
Label continue_target_label_;
|
||||
DISALLOW_COPY_AND_ASSIGN(Iteration);
|
||||
Label continue_label_;
|
||||
};
|
||||
|
||||
// The environment inside the try block of a try/catch statement.
|
||||
// The try block of a try/catch statement.
|
||||
class TryCatch : public NestedStatement {
|
||||
public:
|
||||
explicit TryCatch(FullCodeGenerator* codegen, Label* catch_entry)
|
||||
: NestedStatement(codegen), catch_entry_(catch_entry) { }
|
||||
explicit TryCatch(FullCodeGenerator* codegen) : NestedStatement(codegen) {
|
||||
}
|
||||
virtual ~TryCatch() {}
|
||||
virtual TryCatch* AsTryCatch() { return this; }
|
||||
Label* catch_entry() { return catch_entry_; }
|
||||
|
||||
virtual NestedStatement* Exit(int* stack_depth, int* context_length);
|
||||
private:
|
||||
Label* catch_entry_;
|
||||
DISALLOW_COPY_AND_ASSIGN(TryCatch);
|
||||
};
|
||||
|
||||
// The environment inside the try block of a try/finally statement.
|
||||
// The try block of a try/finally statement.
|
||||
class TryFinally : public NestedStatement {
|
||||
public:
|
||||
explicit TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
|
||||
: NestedStatement(codegen), finally_entry_(finally_entry) { }
|
||||
TryFinally(FullCodeGenerator* codegen, Label* finally_entry)
|
||||
: NestedStatement(codegen), finally_entry_(finally_entry) {
|
||||
}
|
||||
virtual ~TryFinally() {}
|
||||
virtual TryFinally* AsTryFinally() { return this; }
|
||||
Label* finally_entry() { return finally_entry_; }
|
||||
|
||||
virtual NestedStatement* Exit(int* stack_depth, int* context_length);
|
||||
|
||||
private:
|
||||
Label* finally_entry_;
|
||||
DISALLOW_COPY_AND_ASSIGN(TryFinally);
|
||||
};
|
||||
|
||||
// A FinallyEnvironment represents being inside a finally block.
|
||||
// Abnormal termination of the finally block needs to clean up
|
||||
// the block's parameters from the stack.
|
||||
// The finally block of a try/finally statement.
|
||||
class Finally : public NestedStatement {
|
||||
public:
|
||||
static const int kElementCount = 2;
|
||||
|
||||
explicit Finally(FullCodeGenerator* codegen) : NestedStatement(codegen) { }
|
||||
virtual ~Finally() {}
|
||||
virtual Finally* AsFinally() { return this; }
|
||||
|
||||
virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
|
||||
*stack_depth += kFinallyStackElementCount;
|
||||
*stack_depth += kElementCount;
|
||||
return previous_;
|
||||
}
|
||||
private:
|
||||
// Number of extra stack slots occupied during a finally block.
|
||||
static const int kFinallyStackElementCount = 2;
|
||||
DISALLOW_COPY_AND_ASSIGN(Finally);
|
||||
};
|
||||
|
||||
// A ForInEnvironment represents being inside a for-in loop.
|
||||
// Abnormal termination of the for-in block needs to clean up
|
||||
// the block's temporary storage from the stack.
|
||||
// The body of a for/in loop.
|
||||
class ForIn : public Iteration {
|
||||
public:
|
||||
ForIn(FullCodeGenerator* codegen,
|
||||
ForInStatement* statement)
|
||||
: Iteration(codegen, statement) { }
|
||||
static const int kElementCount = 5;
|
||||
|
||||
ForIn(FullCodeGenerator* codegen, ForInStatement* statement)
|
||||
: Iteration(codegen, statement) {
|
||||
}
|
||||
virtual ~ForIn() {}
|
||||
virtual ForIn* AsForIn() { return this; }
|
||||
|
||||
virtual NestedStatement* Exit(int* stack_depth, int* context_length) {
|
||||
*stack_depth += kForInStackElementCount;
|
||||
*stack_depth += kElementCount;
|
||||
return previous_;
|
||||
}
|
||||
private:
|
||||
static const int kForInStackElementCount = 5;
|
||||
DISALLOW_COPY_AND_ASSIGN(ForIn);
|
||||
};
|
||||
|
||||
|
||||
// A WithOrCatch represents being inside the body of a with or catch
|
||||
// statement. Exiting the body needs to remove a link from the context
|
||||
// chain.
|
||||
// The body of a with or catch.
|
||||
class WithOrCatch : public NestedStatement {
|
||||
public:
|
||||
explicit WithOrCatch(FullCodeGenerator* codegen)
|
||||
|
17
deps/v8/src/ia32/full-codegen-ia32.cc
vendored
17
deps/v8/src/ia32/full-codegen-ia32.cc
vendored
@ -875,7 +875,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
__ bind(&next_test);
|
||||
__ Drop(1); // Switch value is no longer needed.
|
||||
if (default_clause == NULL) {
|
||||
__ jmp(nested_statement.break_target());
|
||||
__ jmp(nested_statement.break_label());
|
||||
} else {
|
||||
__ jmp(default_clause->body_target());
|
||||
}
|
||||
@ -890,7 +890,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
VisitStatements(clause->statements());
|
||||
}
|
||||
|
||||
__ bind(nested_statement.break_target());
|
||||
__ bind(nested_statement.break_label());
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
}
|
||||
|
||||
@ -1006,12 +1006,13 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ push(eax); // Fixed array length (as smi).
|
||||
__ push(Immediate(Smi::FromInt(0))); // Initial index.
|
||||
|
||||
increment_stack_height(4);
|
||||
// 1 ~ The object has already been pushed.
|
||||
increment_stack_height(ForIn::kElementCount - 1);
|
||||
// Generate code for doing the condition check.
|
||||
__ bind(&loop);
|
||||
__ mov(eax, Operand(esp, 0 * kPointerSize)); // Get the current index.
|
||||
__ cmp(eax, Operand(esp, 1 * kPointerSize)); // Compare to the array length.
|
||||
__ j(above_equal, loop_statement.break_target());
|
||||
__ j(above_equal, loop_statement.break_label());
|
||||
|
||||
// Get the current entry of the array into register ebx.
|
||||
__ mov(ebx, Operand(esp, 2 * kPointerSize));
|
||||
@ -1035,7 +1036,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ push(ebx); // Current entry.
|
||||
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
|
||||
__ test(eax, Operand(eax));
|
||||
__ j(equal, loop_statement.continue_target());
|
||||
__ j(equal, loop_statement.continue_label());
|
||||
__ mov(ebx, Operand(eax));
|
||||
|
||||
// Update the 'each' property or variable from the possibly filtered
|
||||
@ -1052,17 +1053,17 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Generate code for going to the next element by incrementing the
|
||||
// index (smi) stored on top of the stack.
|
||||
__ bind(loop_statement.continue_target());
|
||||
__ bind(loop_statement.continue_label());
|
||||
__ add(Operand(esp, 0 * kPointerSize), Immediate(Smi::FromInt(1)));
|
||||
|
||||
EmitStackCheck(stmt);
|
||||
__ jmp(&loop);
|
||||
|
||||
// Remove the pointers stored on the stack.
|
||||
__ bind(loop_statement.break_target());
|
||||
__ bind(loop_statement.break_label());
|
||||
__ add(Operand(esp), Immediate(5 * kPointerSize));
|
||||
|
||||
decrement_stack_height(5);
|
||||
decrement_stack_height(ForIn::kElementCount);
|
||||
// Exit and decrement the loop depth.
|
||||
__ bind(&exit);
|
||||
decrement_loop_depth();
|
||||
|
2
deps/v8/src/ia32/macro-assembler-ia32.cc
vendored
2
deps/v8/src/ia32/macro-assembler-ia32.cc
vendored
@ -69,8 +69,8 @@ void MacroAssembler::RecordWriteHelper(Register object,
|
||||
|
||||
// Compute number of region covering addr. See Page::GetRegionNumberForAddress
|
||||
// method for more details.
|
||||
and_(addr, Page::kPageAlignmentMask);
|
||||
shr(addr, Page::kRegionSizeLog2);
|
||||
and_(addr, Page::kPageAlignmentMask >> Page::kRegionSizeLog2);
|
||||
|
||||
// Set dirty mark for region.
|
||||
// Bit tests with a memory operand should be avoided on Intel processors,
|
||||
|
6
deps/v8/src/isolate.cc
vendored
6
deps/v8/src/isolate.cc
vendored
@ -1335,6 +1335,7 @@ void Isolate::ThreadDataTable::Remove(PerIsolateThreadData* data) {
|
||||
if (list_ == data) list_ = data->next_;
|
||||
if (data->next_ != NULL) data->next_->prev_ = data->prev_;
|
||||
if (data->prev_ != NULL) data->prev_->next_ = data->next_;
|
||||
delete data;
|
||||
}
|
||||
|
||||
|
||||
@ -1536,6 +1537,9 @@ Isolate::~Isolate() {
|
||||
// Has to be called while counters_ are still alive.
|
||||
zone_.DeleteKeptSegment();
|
||||
|
||||
delete[] assembler_spare_buffer_;
|
||||
assembler_spare_buffer_ = NULL;
|
||||
|
||||
delete unicode_cache_;
|
||||
unicode_cache_ = NULL;
|
||||
|
||||
@ -1569,6 +1573,8 @@ Isolate::~Isolate() {
|
||||
handle_scope_implementer_ = NULL;
|
||||
delete break_access_;
|
||||
break_access_ = NULL;
|
||||
delete debugger_access_;
|
||||
debugger_access_ = NULL;
|
||||
|
||||
delete compilation_cache_;
|
||||
compilation_cache_ = NULL;
|
||||
|
2
deps/v8/src/json.js
vendored
2
deps/v8/src/json.js
vendored
@ -237,7 +237,7 @@ function BasicSerializeArray(value, stack, builder) {
|
||||
}
|
||||
}
|
||||
stack.pop();
|
||||
builder.push("]");
|
||||
builder.push("]");
|
||||
}
|
||||
|
||||
|
||||
|
52
deps/v8/src/messages.js
vendored
52
deps/v8/src/messages.js
vendored
@ -1,4 +1,4 @@
|
||||
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -57,7 +57,7 @@ function FormatString(format, message) {
|
||||
for (var i = 0; i < format.length; i++) {
|
||||
var str = format[i];
|
||||
for (arg_num = 0; arg_num < kReplacementMarkers.length; arg_num++) {
|
||||
if (format[i] !== kReplacementMarkers[arg_num]) continue;
|
||||
if (str !== kReplacementMarkers[arg_num]) continue;
|
||||
try {
|
||||
str = ToDetailString(args[arg_num]);
|
||||
} catch (e) {
|
||||
@ -100,7 +100,8 @@ function ToStringCheckErrorObject(obj) {
|
||||
|
||||
|
||||
function ToDetailString(obj) {
|
||||
if (obj != null && IS_OBJECT(obj) && obj.toString === $Object.prototype.toString) {
|
||||
if (obj != null && IS_OBJECT(obj) &&
|
||||
obj.toString === $Object.prototype.toString) {
|
||||
var constructor = obj.constructor;
|
||||
if (!constructor) return ToStringCheckErrorObject(obj);
|
||||
var constructorName = constructor.name;
|
||||
@ -207,7 +208,7 @@ function FormatMessage(message) {
|
||||
stack_overflow: ["Maximum call stack size exceeded"],
|
||||
// SyntaxError
|
||||
unable_to_parse: ["Parse error"],
|
||||
duplicate_regexp_flag: ["Duplicate RegExp flag ", "%0"],
|
||||
invalid_regexp_flags: ["Invalid flags supplied to RegExp constructor '", "%0", "'"],
|
||||
invalid_regexp: ["Invalid RegExp pattern /", "%0", "/"],
|
||||
illegal_break: ["Illegal break statement"],
|
||||
illegal_continue: ["Illegal continue statement"],
|
||||
@ -560,6 +561,7 @@ function SourceLocation(script, position, line, column, start, end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
SourceLocation.prototype.__proto__ = null;
|
||||
|
||||
const kLineLengthLimit = 78;
|
||||
|
||||
@ -649,6 +651,7 @@ function SourceSlice(script, from_line, to_line, from_position, to_position) {
|
||||
this.to_position = to_position;
|
||||
}
|
||||
|
||||
SourceSlice.prototype.__proto__ = null;
|
||||
|
||||
/**
|
||||
* Get the source text for a SourceSlice
|
||||
@ -716,23 +719,28 @@ function CallSite(receiver, fun, pos) {
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
CallSite.prototype.__proto__ = null;
|
||||
|
||||
CallSite.prototype.getThis = function () {
|
||||
return this.receiver;
|
||||
};
|
||||
|
||||
CallSite.prototype.getTypeName = function () {
|
||||
var constructor = this.receiver.constructor;
|
||||
if (!constructor)
|
||||
if (!constructor) {
|
||||
return %_CallFunction(this.receiver, ObjectToString);
|
||||
}
|
||||
var constructorName = constructor.name;
|
||||
if (!constructorName)
|
||||
if (!constructorName) {
|
||||
return %_CallFunction(this.receiver, ObjectToString);
|
||||
}
|
||||
return constructorName;
|
||||
};
|
||||
|
||||
CallSite.prototype.isToplevel = function () {
|
||||
if (this.receiver == null)
|
||||
if (this.receiver == null) {
|
||||
return true;
|
||||
}
|
||||
return IS_GLOBAL(this.receiver);
|
||||
};
|
||||
|
||||
@ -765,8 +773,9 @@ CallSite.prototype.getFunctionName = function () {
|
||||
}
|
||||
// Maybe this is an evaluation?
|
||||
var script = %FunctionGetScript(this.fun);
|
||||
if (script && script.compilation_type == COMPILATION_TYPE_EVAL)
|
||||
if (script && script.compilation_type == COMPILATION_TYPE_EVAL) {
|
||||
return "eval";
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -788,13 +797,15 @@ CallSite.prototype.getMethodName = function () {
|
||||
this.receiver.__lookupSetter__(prop) === this.fun ||
|
||||
(!this.receiver.__lookupGetter__(prop) && this.receiver[prop] === this.fun)) {
|
||||
// If we find more than one match bail out to avoid confusion.
|
||||
if (name)
|
||||
if (name) {
|
||||
return null;
|
||||
}
|
||||
name = prop;
|
||||
}
|
||||
}
|
||||
if (name)
|
||||
if (name) {
|
||||
return name;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -804,8 +815,9 @@ CallSite.prototype.getFileName = function () {
|
||||
};
|
||||
|
||||
CallSite.prototype.getLineNumber = function () {
|
||||
if (this.pos == -1)
|
||||
if (this.pos == -1) {
|
||||
return null;
|
||||
}
|
||||
var script = %FunctionGetScript(this.fun);
|
||||
var location = null;
|
||||
if (script) {
|
||||
@ -815,8 +827,9 @@ CallSite.prototype.getLineNumber = function () {
|
||||
};
|
||||
|
||||
CallSite.prototype.getColumnNumber = function () {
|
||||
if (this.pos == -1)
|
||||
if (this.pos == -1) {
|
||||
return null;
|
||||
}
|
||||
var script = %FunctionGetScript(this.fun);
|
||||
var location = null;
|
||||
if (script) {
|
||||
@ -836,15 +849,17 @@ CallSite.prototype.getPosition = function () {
|
||||
|
||||
CallSite.prototype.isConstructor = function () {
|
||||
var constructor = this.receiver ? this.receiver.constructor : null;
|
||||
if (!constructor)
|
||||
if (!constructor) {
|
||||
return false;
|
||||
}
|
||||
return this.fun === constructor;
|
||||
};
|
||||
|
||||
function FormatEvalOrigin(script) {
|
||||
var sourceURL = script.nameOrSourceURL();
|
||||
if (sourceURL)
|
||||
if (sourceURL) {
|
||||
return sourceURL;
|
||||
}
|
||||
|
||||
var eval_origin = "eval at ";
|
||||
if (script.eval_from_function_name) {
|
||||
@ -1042,8 +1057,9 @@ function DefineError(f) {
|
||||
function captureStackTrace(obj, cons_opt) {
|
||||
var stackTraceLimit = $Error.stackTraceLimit;
|
||||
if (!stackTraceLimit || !IS_NUMBER(stackTraceLimit)) return;
|
||||
if (stackTraceLimit < 0 || stackTraceLimit > 10000)
|
||||
if (stackTraceLimit < 0 || stackTraceLimit > 10000) {
|
||||
stackTraceLimit = 10000;
|
||||
}
|
||||
var raw_stack = %CollectStackTrace(cons_opt
|
||||
? cons_opt
|
||||
: captureStackTrace, stackTraceLimit);
|
||||
@ -1117,8 +1133,10 @@ function errorToString() {
|
||||
} catch(e) {
|
||||
// If this error message was encountered already return the empty
|
||||
// string for it instead of recursively formatting it.
|
||||
if (isCyclicErrorMarker(e)) return '';
|
||||
else throw e;
|
||||
if (isCyclicErrorMarker(e)) {
|
||||
return '';
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
18
deps/v8/src/mips/full-codegen-mips.cc
vendored
18
deps/v8/src/mips/full-codegen-mips.cc
vendored
@ -747,9 +747,9 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
|
||||
__ li(a2, Operand(variable->name()));
|
||||
// Declaration nodes are always introduced in one of two modes.
|
||||
ASSERT(mode == Variable::VAR ||
|
||||
mode == Variable::CONST);
|
||||
PropertyAttributes attr =
|
||||
(mode == Variable::VAR) ? NONE : READ_ONLY;
|
||||
mode == Variable::CONST ||
|
||||
mode == Variable::LET);
|
||||
PropertyAttributes attr = (mode == Variable::CONST) ? READ_ONLY : NONE;
|
||||
__ li(a1, Operand(Smi::FromInt(attr)));
|
||||
// Push initial value, if any.
|
||||
// Note: For variables we must not push an initial value (such as
|
||||
@ -886,7 +886,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
__ bind(&next_test);
|
||||
__ Drop(1); // Switch value is no longer needed.
|
||||
if (default_clause == NULL) {
|
||||
__ Branch(nested_statement.break_target());
|
||||
__ Branch(nested_statement.break_label());
|
||||
} else {
|
||||
__ Branch(default_clause->body_target());
|
||||
}
|
||||
@ -900,7 +900,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
VisitStatements(clause->statements());
|
||||
}
|
||||
|
||||
__ bind(nested_statement.break_target());
|
||||
__ bind(nested_statement.break_label());
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
}
|
||||
|
||||
@ -1026,7 +1026,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
// Load the current count to a0, load the length to a1.
|
||||
__ lw(a0, MemOperand(sp, 0 * kPointerSize));
|
||||
__ lw(a1, MemOperand(sp, 1 * kPointerSize));
|
||||
__ Branch(loop_statement.break_target(), hs, a0, Operand(a1));
|
||||
__ Branch(loop_statement.break_label(), hs, a0, Operand(a1));
|
||||
|
||||
// Get the current entry of the array into register a3.
|
||||
__ lw(a2, MemOperand(sp, 2 * kPointerSize));
|
||||
@ -1053,7 +1053,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ push(a3); // Current entry.
|
||||
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
|
||||
__ mov(a3, result_register());
|
||||
__ Branch(loop_statement.continue_target(), eq, a3, Operand(zero_reg));
|
||||
__ Branch(loop_statement.continue_label(), eq, a3, Operand(zero_reg));
|
||||
|
||||
// Update the 'each' property or variable from the possibly filtered
|
||||
// entry in register a3.
|
||||
@ -1069,7 +1069,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Generate code for the going to the next element by incrementing
|
||||
// the index (smi) stored on top of the stack.
|
||||
__ bind(loop_statement.continue_target());
|
||||
__ bind(loop_statement.continue_label());
|
||||
__ pop(a0);
|
||||
__ Addu(a0, a0, Operand(Smi::FromInt(1)));
|
||||
__ push(a0);
|
||||
@ -1078,7 +1078,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ Branch(&loop);
|
||||
|
||||
// Remove the pointers stored on the stack.
|
||||
__ bind(loop_statement.break_target());
|
||||
__ bind(loop_statement.break_label());
|
||||
__ Drop(5);
|
||||
|
||||
// Exit and decrement the loop depth.
|
||||
|
82
deps/v8/src/objects.cc
vendored
82
deps/v8/src/objects.cc
vendored
@ -656,10 +656,11 @@ MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) {
|
||||
}
|
||||
|
||||
if (js_object->elements() != heap->empty_fixed_array()) {
|
||||
MaybeObject* result = js_object->GetElementsAccessor()->GetWithReceiver(
|
||||
MaybeObject* result = js_object->GetElementsAccessor()->Get(
|
||||
js_object->elements(),
|
||||
index,
|
||||
js_object,
|
||||
receiver,
|
||||
index);
|
||||
receiver);
|
||||
if (result != heap->the_hole_value()) return result;
|
||||
}
|
||||
}
|
||||
@ -4466,20 +4467,6 @@ void CodeCacheHashTable::RemoveByIndex(int index) {
|
||||
}
|
||||
|
||||
|
||||
static bool HasKey(FixedArray* array, Object* key) {
|
||||
int len0 = array->length();
|
||||
for (int i = 0; i < len0; i++) {
|
||||
Object* element = array->get(i);
|
||||
if (element->IsSmi() && key->IsSmi() && (element == key)) return true;
|
||||
if (element->IsString() &&
|
||||
key->IsString() && String::cast(element)->Equals(String::cast(key))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* PolymorphicCodeCache::Update(MapList* maps,
|
||||
Code::Flags flags,
|
||||
Code* code) {
|
||||
@ -4641,7 +4628,7 @@ MaybeObject* PolymorphicCodeCacheHashTable::Put(MapList* maps,
|
||||
MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
|
||||
ElementsAccessor* accessor = array->GetElementsAccessor();
|
||||
MaybeObject* maybe_result =
|
||||
accessor->AddElementsToFixedArray(array->elements(), this);
|
||||
accessor->AddElementsToFixedArray(array->elements(), this, array, array);
|
||||
FixedArray* result;
|
||||
if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
|
||||
#ifdef DEBUG
|
||||
@ -4657,55 +4644,19 @@ MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
|
||||
|
||||
|
||||
MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
|
||||
int len0 = length();
|
||||
ElementsAccessor* accessor = ElementsAccessor::ForArray(other);
|
||||
MaybeObject* maybe_result =
|
||||
accessor->AddElementsToFixedArray(other, this, NULL, NULL);
|
||||
FixedArray* result;
|
||||
if (!maybe_result->To<FixedArray>(&result)) return maybe_result;
|
||||
#ifdef DEBUG
|
||||
if (FLAG_enable_slow_asserts) {
|
||||
for (int i = 0; i < len0; i++) {
|
||||
ASSERT(get(i)->IsString() || get(i)->IsNumber());
|
||||
for (int i = 0; i < result->length(); i++) {
|
||||
Object* current = result->get(i);
|
||||
ASSERT(current->IsNumber() || current->IsString());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
int len1 = other->length();
|
||||
// Optimize if 'other' is empty.
|
||||
// We cannot optimize if 'this' is empty, as other may have holes
|
||||
// or non keys.
|
||||
if (len1 == 0) return this;
|
||||
|
||||
// Compute how many elements are not in this.
|
||||
int extra = 0;
|
||||
for (int y = 0; y < len1; y++) {
|
||||
Object* value = other->get(y);
|
||||
if (!value->IsTheHole() && !HasKey(this, value)) extra++;
|
||||
}
|
||||
|
||||
if (extra == 0) return this;
|
||||
|
||||
// Allocate the result
|
||||
Object* obj;
|
||||
{ MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(len0 + extra);
|
||||
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
||||
}
|
||||
// Fill in the content
|
||||
AssertNoAllocation no_gc;
|
||||
FixedArray* result = FixedArray::cast(obj);
|
||||
WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
|
||||
for (int i = 0; i < len0; i++) {
|
||||
Object* e = get(i);
|
||||
ASSERT(e->IsString() || e->IsNumber());
|
||||
result->set(i, e, mode);
|
||||
}
|
||||
// Fill in the extra keys.
|
||||
int index = 0;
|
||||
for (int y = 0; y < len1; y++) {
|
||||
Object* value = other->get(y);
|
||||
if (!value->IsTheHole() && !HasKey(this, value)) {
|
||||
Object* e = other->get(y);
|
||||
ASSERT(e->IsString() || e->IsNumber());
|
||||
result->set(len0 + index, e, mode);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
ASSERT(extra == index);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -8718,9 +8669,10 @@ MaybeObject* JSObject::GetElementWithInterceptor(Object* receiver,
|
||||
|
||||
Heap* heap = holder_handle->GetHeap();
|
||||
ElementsAccessor* handler = holder_handle->GetElementsAccessor();
|
||||
MaybeObject* raw_result = handler->GetWithReceiver(*holder_handle,
|
||||
*this_handle,
|
||||
index);
|
||||
MaybeObject* raw_result = handler->Get(holder_handle->elements(),
|
||||
index,
|
||||
*holder_handle,
|
||||
*this_handle);
|
||||
if (raw_result != heap->the_hole_value()) return raw_result;
|
||||
|
||||
RETURN_IF_SCHEDULED_EXCEPTION(isolate);
|
||||
|
15
deps/v8/src/regexp.js
vendored
15
deps/v8/src/regexp.js
vendored
@ -50,24 +50,29 @@ function DoConstructRegExp(object, pattern, flags) {
|
||||
var global = false;
|
||||
var ignoreCase = false;
|
||||
var multiline = false;
|
||||
|
||||
for (var i = 0; i < flags.length; i++) {
|
||||
var c = %_CallFunction(flags, i, StringCharAt);
|
||||
switch (c) {
|
||||
case 'g':
|
||||
// Allow duplicate flags to be consistent with JSC and others.
|
||||
if (global) {
|
||||
throw MakeSyntaxError("invalid_regexp_flags", [flags]);
|
||||
}
|
||||
global = true;
|
||||
break;
|
||||
case 'i':
|
||||
if (ignoreCase) {
|
||||
throw MakeSyntaxError("invalid_regexp_flags", [flags]);
|
||||
}
|
||||
ignoreCase = true;
|
||||
break;
|
||||
case 'm':
|
||||
if (multiline) {
|
||||
throw MakeSyntaxError("invalid_regexp_flags", [flags]);
|
||||
}
|
||||
multiline = true;
|
||||
break;
|
||||
default:
|
||||
// Ignore flags that have no meaning to be consistent with
|
||||
// JSC.
|
||||
break;
|
||||
throw MakeSyntaxError("invalid_regexp_flags", [flags]);
|
||||
}
|
||||
}
|
||||
|
||||
|
93
deps/v8/src/scanner-base.cc
vendored
93
deps/v8/src/scanner-base.cc
vendored
@ -41,12 +41,12 @@ Scanner::Scanner(UnicodeCache* unicode_cache)
|
||||
: unicode_cache_(unicode_cache) { }
|
||||
|
||||
|
||||
uc32 Scanner::ScanHexEscape(uc32 c, int length) {
|
||||
ASSERT(length <= 4); // prevent overflow
|
||||
uc32 Scanner::ScanHexNumber(int expected_length) {
|
||||
ASSERT(expected_length <= 4); // prevent overflow
|
||||
|
||||
uc32 digits[4];
|
||||
uc32 digits[4] = { 0, 0, 0, 0 };
|
||||
uc32 x = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (int i = 0; i < expected_length; i++) {
|
||||
digits[i] = c0_;
|
||||
int d = HexValue(c0_);
|
||||
if (d < 0) {
|
||||
@ -54,12 +54,11 @@ uc32 Scanner::ScanHexEscape(uc32 c, int length) {
|
||||
// should be illegal, but other JS VMs just return the
|
||||
// non-escaped version of the original character.
|
||||
|
||||
// Push back digits read, except the last one (in c0_).
|
||||
// Push back digits that we have advanced past.
|
||||
for (int j = i-1; j >= 0; j--) {
|
||||
PushBack(digits[j]);
|
||||
}
|
||||
// Notice: No handling of error - treat it as "\u"->"u".
|
||||
return c;
|
||||
return -1;
|
||||
}
|
||||
x = x * 16 + d;
|
||||
Advance();
|
||||
@ -640,9 +639,17 @@ void JavaScriptScanner::ScanEscape() {
|
||||
case 'n' : c = '\n'; break;
|
||||
case 'r' : c = '\r'; break;
|
||||
case 't' : c = '\t'; break;
|
||||
case 'u' : c = ScanHexEscape(c, 4); break;
|
||||
case 'u' : {
|
||||
c = ScanHexNumber(4);
|
||||
if (c < 0) c = 'u';
|
||||
break;
|
||||
}
|
||||
case 'v' : c = '\v'; break;
|
||||
case 'x' : c = ScanHexEscape(c, 2); break;
|
||||
case 'x' : {
|
||||
c = ScanHexNumber(2);
|
||||
if (c < 0) c = 'x';
|
||||
break;
|
||||
}
|
||||
case '0' : // fall through
|
||||
case '1' : // fall through
|
||||
case '2' : // fall through
|
||||
@ -802,13 +809,11 @@ Token::Value JavaScriptScanner::ScanNumber(bool seen_period) {
|
||||
|
||||
uc32 JavaScriptScanner::ScanIdentifierUnicodeEscape() {
|
||||
Advance();
|
||||
if (c0_ != 'u') return unibrow::Utf8::kBadChar;
|
||||
if (c0_ != 'u') return -1;
|
||||
Advance();
|
||||
uc32 c = ScanHexEscape('u', 4);
|
||||
// We do not allow a unicode escape sequence to start another
|
||||
// unicode escape sequence.
|
||||
if (c == '\\') return unibrow::Utf8::kBadChar;
|
||||
return c;
|
||||
uc32 result = ScanHexNumber(4);
|
||||
if (result < 0) PushBack('u');
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -926,7 +931,11 @@ Token::Value JavaScriptScanner::ScanIdentifierOrKeyword() {
|
||||
if (c0_ == '\\') {
|
||||
uc32 c = ScanIdentifierUnicodeEscape();
|
||||
// Only allow legal identifier start characters.
|
||||
if (!unicode_cache_->IsIdentifierStart(c)) return Token::ILLEGAL;
|
||||
if (c < 0 ||
|
||||
c == '\\' || // No recursive escapes.
|
||||
!unicode_cache_->IsIdentifierStart(c)) {
|
||||
return Token::ILLEGAL;
|
||||
}
|
||||
AddLiteralChar(c);
|
||||
return ScanIdentifierSuffix(&literal);
|
||||
}
|
||||
@ -966,7 +975,11 @@ Token::Value JavaScriptScanner::ScanIdentifierSuffix(LiteralScope* literal) {
|
||||
if (c0_ == '\\') {
|
||||
uc32 c = ScanIdentifierUnicodeEscape();
|
||||
// Only allow legal identifier part characters.
|
||||
if (!unicode_cache_->IsIdentifierPart(c)) return Token::ILLEGAL;
|
||||
if (c < 0 ||
|
||||
c == '\\' ||
|
||||
!unicode_cache_->IsIdentifierPart(c)) {
|
||||
return Token::ILLEGAL;
|
||||
}
|
||||
AddLiteralChar(c);
|
||||
} else {
|
||||
AddLiteralChar(c0_);
|
||||
@ -992,8 +1005,9 @@ bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) {
|
||||
// the scanner should pass uninterpreted bodies to the RegExp
|
||||
// constructor.
|
||||
LiteralScope literal(this);
|
||||
if (seen_equal)
|
||||
if (seen_equal) {
|
||||
AddLiteralChar('=');
|
||||
}
|
||||
|
||||
while (c0_ != '/' || in_character_class) {
|
||||
if (unicode_cache_->IsLineTerminator(c0_) || c0_ < 0) return false;
|
||||
@ -1025,20 +1039,47 @@ bool JavaScriptScanner::ScanRegExpPattern(bool seen_equal) {
|
||||
}
|
||||
|
||||
|
||||
bool JavaScriptScanner::ScanLiteralUnicodeEscape() {
|
||||
ASSERT(c0_ == '\\');
|
||||
uc32 chars_read[6] = {'\\', 'u', 0, 0, 0, 0};
|
||||
Advance();
|
||||
int i = 1;
|
||||
if (c0_ == 'u') {
|
||||
i++;
|
||||
while (i < 6) {
|
||||
Advance();
|
||||
if (!IsHexDigit(c0_)) break;
|
||||
chars_read[i] = c0_;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (i < 6) {
|
||||
// Incomplete escape. Undo all advances and return false.
|
||||
while (i > 0) {
|
||||
i--;
|
||||
PushBack(chars_read[i]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// Complete escape. Add all chars to current literal buffer.
|
||||
for (int i = 0; i < 6; i++) {
|
||||
AddLiteralChar(chars_read[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool JavaScriptScanner::ScanRegExpFlags() {
|
||||
// Scan regular expression flags.
|
||||
LiteralScope literal(this);
|
||||
while (unicode_cache_->IsIdentifierPart(c0_)) {
|
||||
if (c0_ == '\\') {
|
||||
uc32 c = ScanIdentifierUnicodeEscape();
|
||||
if (c != static_cast<uc32>(unibrow::Utf8::kBadChar)) {
|
||||
// We allow any escaped character, unlike the restriction on
|
||||
// IdentifierPart when it is used to build an IdentifierName.
|
||||
AddLiteralChar(c);
|
||||
continue;
|
||||
if (c0_ != '\\') {
|
||||
AddLiteralCharAdvance();
|
||||
} else {
|
||||
if (!ScanLiteralUnicodeEscape()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
AddLiteralCharAdvance();
|
||||
}
|
||||
literal.Complete();
|
||||
|
||||
|
6
deps/v8/src/scanner-base.h
vendored
6
deps/v8/src/scanner-base.h
vendored
@ -419,7 +419,7 @@ class Scanner {
|
||||
}
|
||||
}
|
||||
|
||||
uc32 ScanHexEscape(uc32 c, int length);
|
||||
uc32 ScanHexNumber(int expected_length);
|
||||
|
||||
// Return the current source position.
|
||||
int source_pos() {
|
||||
@ -537,6 +537,10 @@ class JavaScriptScanner : public Scanner {
|
||||
// Decodes a unicode escape-sequence which is part of an identifier.
|
||||
// If the escape sequence cannot be decoded the result is kBadChar.
|
||||
uc32 ScanIdentifierUnicodeEscape();
|
||||
// Recognizes a uniocde escape-sequence and adds its characters,
|
||||
// uninterpreted, to the current literal. Used for parsing RegExp
|
||||
// flags.
|
||||
bool ScanLiteralUnicodeEscape();
|
||||
|
||||
// Start position of the octal literal last scanned.
|
||||
Location octal_pos_;
|
||||
|
1
deps/v8/src/spaces.h
vendored
1
deps/v8/src/spaces.h
vendored
@ -409,6 +409,7 @@ class Space : public Malloced {
|
||||
class CodeRange {
|
||||
public:
|
||||
explicit CodeRange(Isolate* isolate);
|
||||
~CodeRange() { TearDown(); }
|
||||
|
||||
// Reserves a range of virtual memory, but does not commit any of it.
|
||||
// Can only be called once, at heap initialization time.
|
||||
|
4
deps/v8/src/string.js
vendored
4
deps/v8/src/string.js
vendored
@ -170,7 +170,7 @@ function StringLocaleCompare(other) {
|
||||
["String.prototype.localeCompare"]);
|
||||
}
|
||||
if (%_ArgumentsLength() === 0) return 0;
|
||||
return %StringLocaleCompare(TO_STRING_INLINE(this),
|
||||
return %StringLocaleCompare(TO_STRING_INLINE(this),
|
||||
TO_STRING_INLINE(other));
|
||||
}
|
||||
|
||||
@ -914,6 +914,8 @@ function ReplaceResultBuilder(str) {
|
||||
this.special_string = str;
|
||||
}
|
||||
|
||||
ReplaceResultBuilder.prototype.__proto__ = null;
|
||||
|
||||
|
||||
ReplaceResultBuilder.prototype.add = function(str) {
|
||||
str = TO_STRING_INLINE(str);
|
||||
|
30
deps/v8/src/v8natives.js
vendored
30
deps/v8/src/v8natives.js
vendored
@ -462,6 +462,7 @@ function PropertyDescriptor() {
|
||||
}
|
||||
|
||||
PropertyDescriptor.prototype.__proto__ = null;
|
||||
|
||||
PropertyDescriptor.prototype.toString = function() {
|
||||
return "[object PropertyDescriptor]";
|
||||
};
|
||||
@ -1015,24 +1016,27 @@ function ObjectDefineProperty(obj, p, attributes) {
|
||||
}
|
||||
|
||||
|
||||
function GetOwnEnumerablePropertyNames(properties) {
|
||||
var names = new InternalArray();
|
||||
for (var key in properties) {
|
||||
if (%HasLocalProperty(properties, key)) {
|
||||
names.push(key);
|
||||
}
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
// ES5 section 15.2.3.7.
|
||||
function ObjectDefineProperties(obj, properties) {
|
||||
if (!IS_SPEC_OBJECT(obj))
|
||||
throw MakeTypeError("obj_ctor_property_non_object", ["defineProperties"]);
|
||||
var props = ToObject(properties);
|
||||
var key_values = [];
|
||||
for (var key in props) {
|
||||
if (%HasLocalProperty(props, key)) {
|
||||
key_values.push(key);
|
||||
var value = props[key];
|
||||
var desc = ToPropertyDescriptor(value);
|
||||
key_values.push(desc);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < key_values.length; i += 2) {
|
||||
var key = key_values[i];
|
||||
var desc = key_values[i + 1];
|
||||
DefineOwnProperty(obj, key, desc, true);
|
||||
var names = GetOwnEnumerablePropertyNames(props);
|
||||
for (var i = 0; i < names.length; i++) {
|
||||
var name = names[i];
|
||||
var desc = ToPropertyDescriptor(props[name]);
|
||||
DefineOwnProperty(obj, name, desc, true);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
4
deps/v8/src/v8threads.cc
vendored
4
deps/v8/src/v8threads.cc
vendored
@ -305,7 +305,9 @@ ThreadManager::ThreadManager()
|
||||
|
||||
|
||||
ThreadManager::~ThreadManager() {
|
||||
// TODO(isolates): Destroy mutexes.
|
||||
delete mutex_;
|
||||
delete free_anchor_;
|
||||
delete in_use_anchor_;
|
||||
}
|
||||
|
||||
|
||||
|
2
deps/v8/src/version.cc
vendored
2
deps/v8/src/version.cc
vendored
@ -34,7 +34,7 @@
|
||||
// cannot be changed without changing the SCons build script.
|
||||
#define MAJOR_VERSION 3
|
||||
#define MINOR_VERSION 5
|
||||
#define BUILD_NUMBER 6
|
||||
#define BUILD_NUMBER 7
|
||||
#define PATCH_LEVEL 0
|
||||
// Use 1 for candidates and 0 otherwise.
|
||||
// (Boolean macro values are not supported by all preprocessors.)
|
||||
|
12
deps/v8/src/x64/full-codegen-x64.cc
vendored
12
deps/v8/src/x64/full-codegen-x64.cc
vendored
@ -842,7 +842,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
__ bind(&next_test);
|
||||
__ Drop(1); // Switch value is no longer needed.
|
||||
if (default_clause == NULL) {
|
||||
__ jmp(nested_statement.break_target());
|
||||
__ jmp(nested_statement.break_label());
|
||||
} else {
|
||||
__ jmp(default_clause->body_target());
|
||||
}
|
||||
@ -856,7 +856,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
|
||||
VisitStatements(clause->statements());
|
||||
}
|
||||
|
||||
__ bind(nested_statement.break_target());
|
||||
__ bind(nested_statement.break_label());
|
||||
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
|
||||
}
|
||||
|
||||
@ -982,7 +982,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ bind(&loop);
|
||||
__ movq(rax, Operand(rsp, 0 * kPointerSize)); // Get the current index.
|
||||
__ cmpq(rax, Operand(rsp, 1 * kPointerSize)); // Compare to the array length.
|
||||
__ j(above_equal, loop_statement.break_target());
|
||||
__ j(above_equal, loop_statement.break_label());
|
||||
|
||||
// Get the current entry of the array into register rbx.
|
||||
__ movq(rbx, Operand(rsp, 2 * kPointerSize));
|
||||
@ -1010,7 +1010,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
__ push(rbx); // Current entry.
|
||||
__ InvokeBuiltin(Builtins::FILTER_KEY, CALL_FUNCTION);
|
||||
__ Cmp(rax, Smi::FromInt(0));
|
||||
__ j(equal, loop_statement.continue_target());
|
||||
__ j(equal, loop_statement.continue_label());
|
||||
__ movq(rbx, rax);
|
||||
|
||||
// Update the 'each' property or variable from the possibly filtered
|
||||
@ -1027,14 +1027,14 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
|
||||
|
||||
// Generate code for going to the next element by incrementing the
|
||||
// index (smi) stored on top of the stack.
|
||||
__ bind(loop_statement.continue_target());
|
||||
__ bind(loop_statement.continue_label());
|
||||
__ SmiAddConstant(Operand(rsp, 0 * kPointerSize), Smi::FromInt(1));
|
||||
|
||||
EmitStackCheck(stmt);
|
||||
__ jmp(&loop);
|
||||
|
||||
// Remove the pointers stored on the stack.
|
||||
__ bind(loop_statement.break_target());
|
||||
__ bind(loop_statement.break_label());
|
||||
__ addq(rsp, Immediate(5 * kPointerSize));
|
||||
|
||||
// Exit and decrement the loop depth.
|
||||
|
46
deps/v8/test/cctest/test-api.cc
vendored
46
deps/v8/test/cctest/test-api.cc
vendored
@ -3617,6 +3617,52 @@ THREADED_TEST(IndexedInterceptorUnboxedDoubleWithIndexedAccessor) {
|
||||
}
|
||||
|
||||
|
||||
Handle<v8::Array> NonStrictArgsIndexedPropertyEnumerator(
|
||||
const AccessorInfo& info) {
|
||||
// Force the list of returned keys to be stored in a Arguments object.
|
||||
Local<Script> indexed_property_names_script = Script::Compile(v8_str(
|
||||
"function f(w,x) {"
|
||||
" return arguments;"
|
||||
"}"
|
||||
"keys = f(0, 1, 2, 3);"
|
||||
"keys;"));
|
||||
Local<Value> result = indexed_property_names_script->Run();
|
||||
return Local<v8::Array>(static_cast<v8::Array*>(::v8::Object::Cast(*result)));
|
||||
}
|
||||
|
||||
|
||||
static v8::Handle<Value> NonStrictIndexedPropertyGetter(
|
||||
uint32_t index,
|
||||
const AccessorInfo& info) {
|
||||
ApiTestFuzzer::Fuzz();
|
||||
if (index < 4) {
|
||||
return v8::Handle<Value>(v8_num(index));
|
||||
}
|
||||
return v8::Handle<Value>();
|
||||
}
|
||||
|
||||
|
||||
// Make sure that the the interceptor code in the runtime properly handles
|
||||
// merging property name lists for non-string arguments arrays.
|
||||
THREADED_TEST(IndexedInterceptorNonStrictArgsWithIndexedAccessor) {
|
||||
v8::HandleScope scope;
|
||||
Local<ObjectTemplate> templ = ObjectTemplate::New();
|
||||
templ->SetIndexedPropertyHandler(NonStrictIndexedPropertyGetter,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NonStrictArgsIndexedPropertyEnumerator);
|
||||
LocalContext context;
|
||||
context->Global()->Set(v8_str("obj"), templ->NewInstance());
|
||||
Local<Script> create_args_script =
|
||||
Script::Compile(v8_str(
|
||||
"var key_count = 0;"
|
||||
"for (x in obj) {key_count++;} key_count;"));
|
||||
Local<Value> result = create_args_script->Run();
|
||||
CHECK_EQ(v8_num(4), result);
|
||||
}
|
||||
|
||||
|
||||
static v8::Handle<Value> IdentityIndexedPropertyGetter(
|
||||
uint32_t index,
|
||||
const AccessorInfo& info) {
|
||||
|
54
deps/v8/test/mjsunit/regress/regress-1620.js
vendored
Normal file
54
deps/v8/test/mjsunit/regress/regress-1620.js
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Don't allow malformed unicode escape sequences in identifiers.
|
||||
// In strings and regexps we currently allow malformed unicode escape
|
||||
// sequences without throwing a SyntaxError. Instead "\u22gk" would
|
||||
// treat the "\u" as an identity escape, and evaluate to "u22gk".
|
||||
// Due to code sharing, we did the same in identifiers. This should
|
||||
// no longer be the case.
|
||||
// See: http://code.google.com/p/v8/issues/detail?id=1620
|
||||
|
||||
assertThrows("var \\u\\u\\u = 42;");
|
||||
assertThrows("var \\u41 = 42;");
|
||||
assertThrows("var \\u123 = 42;");
|
||||
eval("var \\u1234 = 42;");
|
||||
assertEquals(42, eval("\u1234"));
|
||||
assertThrows("var uuu = 42; var x = \\u\\u\\u");
|
||||
|
||||
// Regressions introduced and fixed again while fixing the above.
|
||||
|
||||
// Handle 0xFFFD correctly (it's a valid value, and shouldn't be used
|
||||
// to mark an error).
|
||||
assertEquals(0xFFFD, "\uFFFD".charCodeAt(0));
|
||||
|
||||
// Handle unicode escapes in regexp flags correctly.
|
||||
assertThrows("/x/g\\uim", SyntaxError);
|
||||
assertThrows("/x/g\\u2im", SyntaxError);
|
||||
assertThrows("/x/g\\u22im", SyntaxError);
|
||||
assertThrows("/x/g\\u222im", SyntaxError);
|
||||
assertThrows("/x/g\\\\u2222im", SyntaxError);
|
36
deps/v8/test/mjsunit/regress/regress-1625.js
vendored
Normal file
36
deps/v8/test/mjsunit/regress/regress-1625.js
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2011 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Test that overwriting Array.prototype.push does not make
|
||||
// Object.defineProperties misbehave.
|
||||
|
||||
Array.prototype.push = 1;
|
||||
var desc = {foo: {value: 10}, bar: {get: function() {return 42; }}};
|
||||
var obj = {};
|
||||
var x = Object.defineProperties(obj, desc);
|
||||
assertEquals(x.foo, 10);
|
||||
assertEquals(x.bar, 42);
|
128
deps/v8/test/mjsunit/regress/regress-219.js
vendored
128
deps/v8/test/mjsunit/regress/regress-219.js
vendored
@ -30,6 +30,10 @@
|
||||
// We should now allow duplicates of flags.
|
||||
// (See http://code.google.com/p/v8/issues/detail?id=219)
|
||||
|
||||
// This has been reversed by issue 1628, since other browsers have also
|
||||
// tightened their syntax.
|
||||
// (See http://code.google.com/p/v8/issues/detail?id=1628)
|
||||
|
||||
// Base tests: we recognize the basic flags
|
||||
|
||||
function assertFlags(re, global, multiline, ignoreCase) {
|
||||
@ -53,124 +57,92 @@ assertFlags(re, true, true, true)
|
||||
|
||||
// Double i's
|
||||
|
||||
re = /a/ii;
|
||||
assertFlags(re, false, false, true)
|
||||
assertThrows("/a/ii");
|
||||
|
||||
re = /a/gii;
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows("/a/gii");
|
||||
|
||||
re = /a/igi;
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows("/a/igi");
|
||||
|
||||
re = /a/iig;
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows("/a/iig");
|
||||
|
||||
re = /a/gimi;
|
||||
assertFlags(re, true, true, true)
|
||||
assertThrows("/a/gimi");
|
||||
|
||||
re = /a/giim;
|
||||
assertFlags(re, true, true, true)
|
||||
assertThrows("/a/giim");
|
||||
|
||||
re = /a/igim;
|
||||
assertFlags(re, true, true, true)
|
||||
assertThrows("/a/igim");
|
||||
|
||||
assertThrows(function(){ return RegExp("a", "ii"); })
|
||||
|
||||
re = RegExp("a", "ii");
|
||||
assertFlags(re, false, false, true)
|
||||
assertThrows(function(){ return RegExp("a", "gii"); })
|
||||
|
||||
re = RegExp("a", "gii");
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows(function(){ return RegExp("a", "igi"); })
|
||||
|
||||
re = RegExp("a", "igi");
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows(function(){ return RegExp("a", "iig"); })
|
||||
|
||||
re = RegExp("a", "iig");
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows(function(){ return RegExp("a", "gimi"); })
|
||||
|
||||
re = RegExp("a", "gimi");
|
||||
assertFlags(re, true, true, true)
|
||||
assertThrows(function(){ return RegExp("a", "giim"); })
|
||||
|
||||
re = RegExp("a", "giim");
|
||||
assertFlags(re, true, true, true)
|
||||
|
||||
re = RegExp("a", "igim");
|
||||
assertFlags(re, true, true, true)
|
||||
assertThrows(function(){ return RegExp("a", "igim"); })
|
||||
|
||||
// Tripple i's
|
||||
|
||||
re = /a/iii;
|
||||
assertFlags(re, false, false, true)
|
||||
assertThrows("/a/iii");
|
||||
|
||||
re = /a/giii;
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows("/a/giii");
|
||||
|
||||
re = /a/igii;
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows("/a/igii");
|
||||
|
||||
re = /a/iigi;
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows("/a/iigi");
|
||||
|
||||
re = /a/iiig;
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows("/a/iiig");
|
||||
|
||||
re = /a/miiig;
|
||||
assertFlags(re, true, true, true)
|
||||
assertThrows("/a/miiig");
|
||||
|
||||
assertThrows(function(){ return RegExp("a", "iii"); })
|
||||
|
||||
re = RegExp("a", "iii");
|
||||
assertFlags(re, false, false, true)
|
||||
assertThrows(function(){ return RegExp("a", "giii"); })
|
||||
|
||||
re = RegExp("a", "giii");
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows(function(){ return RegExp("a", "igii"); })
|
||||
|
||||
re = RegExp("a", "igii");
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows(function(){ return RegExp("a", "iigi"); })
|
||||
|
||||
re = RegExp("a", "iigi");
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows(function(){ return RegExp("a", "iiig"); })
|
||||
|
||||
re = RegExp("a", "iiig");
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows(function(){ return RegExp("a", "miiig"); })
|
||||
|
||||
re = RegExp("a", "miiig");
|
||||
assertFlags(re, true, true, true)
|
||||
// Illegal flags - valid flags late in string.
|
||||
|
||||
// Illegal flags - flags late in string.
|
||||
assertThrows("/a/arglebargleglopglyf");
|
||||
|
||||
re = /a/arglebargleglopglyf;
|
||||
assertFlags(re, true, false, false)
|
||||
assertThrows("/a/arglebargleglopglif");
|
||||
|
||||
re = /a/arglebargleglopglif;
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows("/a/arglebargleglopglym");
|
||||
|
||||
re = /a/arglebargleglopglym;
|
||||
assertFlags(re, true, true, false)
|
||||
|
||||
re = /a/arglebargleglopglim;
|
||||
assertFlags(re, true, true, true)
|
||||
assertThrows("/a/arglebargleglopglim");
|
||||
|
||||
// Case of flags still matters.
|
||||
|
||||
re = /a/gmi;
|
||||
var re = /a/gmi;
|
||||
assertFlags(re, true, true, true)
|
||||
|
||||
re = /a/Gmi;
|
||||
assertFlags(re, false, true, true)
|
||||
assertThrows("/a/Gmi");
|
||||
|
||||
re = /a/gMi;
|
||||
assertFlags(re, true, false, true)
|
||||
assertThrows("/a/gMi");
|
||||
|
||||
re = /a/gmI;
|
||||
assertFlags(re, true, true, false)
|
||||
assertThrows("/a/gmI");
|
||||
|
||||
re = /a/GMi;
|
||||
assertFlags(re, false, false, true)
|
||||
assertThrows("/a/GMi");
|
||||
|
||||
re = /a/GmI;
|
||||
assertFlags(re, false, true, false)
|
||||
assertThrows("/a/GmI");
|
||||
|
||||
re = /a/gMI;
|
||||
assertFlags(re, true, false, false)
|
||||
assertThrows("/a/gMI");
|
||||
|
||||
re = /a/GMI;
|
||||
assertFlags(re, false, false, false)
|
||||
assertThrows("/a/GMI");
|
||||
|
||||
// Unicode escape sequences are not interpreted.
|
||||
|
||||
assertThrows("/a/\\u0067");
|
||||
assertThrows("/a/\\u0069");
|
||||
assertThrows("/a/\\u006d");
|
||||
assertThrows("/a/\\u006D");
|
||||
|
47
deps/v8/test/mjsunit/regress/regress-87.js
vendored
47
deps/v8/test/mjsunit/regress/regress-87.js
vendored
@ -25,34 +25,29 @@
|
||||
// (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 testFlags(flagstring, global, ignoreCase, multiline) {
|
||||
var text = "/x/"+flagstring;
|
||||
var re = eval(text);
|
||||
assertEquals(global, re.global, text + ".global");
|
||||
assertEquals(ignoreCase, re.ignoreCase, text + ".ignoreCase");
|
||||
assertEquals(multiline, re.multiline, text + ".multiline");
|
||||
}
|
||||
// In Issue 87, we allowed unicode escape sequences in RegExp flags.
|
||||
// However, according to ES5, they should not be interpreted, but passed
|
||||
// verbatim to the RegExp constructor.
|
||||
// (On top of that, the original test was bugged and never tested anything).
|
||||
// The behavior was changed in r8969 to not interpret escapes, but this
|
||||
// test didn't test that, and only failed when making invalid flag characters
|
||||
// an error too.
|
||||
|
||||
testFlags("", false, false, false);
|
||||
assertThrows("/x/\\u0067");
|
||||
assertThrows("/x/\\u0069");
|
||||
assertThrows("/x/\\u006d");
|
||||
|
||||
testFlags("\u0067", true, false, false);
|
||||
assertThrows("/x/\\u0067i");
|
||||
assertThrows("/x/\\u0069m");
|
||||
assertThrows("/x/\\u006dg");
|
||||
|
||||
testFlags("\u0069", false, true, false)
|
||||
assertThrows("/x/m\\u0067");
|
||||
assertThrows("/x/g\\u0069");
|
||||
assertThrows("/x/i\\u006d");
|
||||
|
||||
testFlags("\u006d", false, false, true);
|
||||
|
||||
testFlags("\u0068", false, false, false);
|
||||
|
||||
testFlags("\u0020", false, false, false);
|
||||
|
||||
|
||||
testFlags("\u0067g", true, false, false);
|
||||
|
||||
testFlags("g\u0067", true, false, false);
|
||||
|
||||
testFlags("abc\u0067efg", true, false, false);
|
||||
|
||||
testFlags("i\u0067", true, true, false);
|
||||
|
||||
testFlags("\u0067i", true, true, false);
|
||||
assertThrows("/x/m\\u0067i");
|
||||
assertThrows("/x/g\\u0069m");
|
||||
assertThrows("/x/i\\u006dg");
|
||||
|
||||
assertThrows("/x/\\u0068");
|
||||
assertThrows("/x/\\u0020");
|
||||
|
5
deps/v8/test/mozilla/mozilla.status
vendored
5
deps/v8/test/mozilla/mozilla.status
vendored
@ -246,9 +246,8 @@ ecma_3/Number/15.7.4.7-1: FAIL_OK
|
||||
ecma_3/Number/15.7.4.6-1: FAIL_OK
|
||||
|
||||
#:=== RegExp:===
|
||||
# To be compatible with JSC we silently ignore flags that do not make
|
||||
# sense. These tests expects us to throw exceptions.
|
||||
ecma_3/RegExp/regress-57631: FAIL_OK
|
||||
# We don't match the syntax error message of Mozilla for invalid
|
||||
# RegExp flags.
|
||||
ecma_3/RegExp/15.10.4.1-6: FAIL_OK
|
||||
|
||||
# PCRE doesn't allow subpattern nesting deeper than 200, this tests
|
||||
|
16
deps/v8/test/sputnik/sputnik.status
vendored
16
deps/v8/test/sputnik/sputnik.status
vendored
@ -56,15 +56,6 @@ S15.10.6.3_A1_T16: FAIL_OK
|
||||
# errors, for compatibility.
|
||||
S15.10.2.11_A1_T2: FAIL
|
||||
S15.10.2.11_A1_T3: FAIL
|
||||
S15.10.4.1_A5_T1: FAIL
|
||||
S15.10.4.1_A5_T2: FAIL
|
||||
S15.10.4.1_A5_T3: FAIL
|
||||
S15.10.4.1_A5_T4: FAIL
|
||||
S15.10.4.1_A5_T5: FAIL
|
||||
S15.10.4.1_A5_T6: FAIL
|
||||
S15.10.4.1_A5_T7: FAIL
|
||||
S15.10.4.1_A5_T8: FAIL
|
||||
S15.10.4.1_A5_T9: FAIL
|
||||
|
||||
# We are more lenient in which string character escapes we allow than
|
||||
# the spec (7.8.4 p. 19) wants us to be. This is for compatibility.
|
||||
@ -99,6 +90,13 @@ S7.8.4_A7.4_T1: FAIL_OK
|
||||
S7.8.4_A4.3_T5: FAIL_OK
|
||||
S7.8.4_A7.2_T5: FAIL_OK
|
||||
|
||||
# Sputnik expects unicode escape sequences in RegExp flags to be interpreted.
|
||||
# The specification requires them to be passed uninterpreted to the RegExp
|
||||
# constructor. We now implement that.
|
||||
S7.8.5_A3.1_T7: FAIL_OK
|
||||
S7.8.5_A3.1_T8: FAIL_OK
|
||||
S7.8.5_A3.1_T9: FAIL_OK
|
||||
|
||||
# We allow some keywords to be used as identifiers.
|
||||
S7.5.3_A1.15: FAIL_OK
|
||||
S7.5.3_A1.18: FAIL_OK
|
||||
|
6
deps/v8/tools/gyp/v8.gyp
vendored
6
deps/v8/tools/gyp/v8.gyp
vendored
@ -144,7 +144,6 @@
|
||||
'Debug': {
|
||||
'defines': [
|
||||
'DEBUG',
|
||||
'_DEBUG',
|
||||
'ENABLE_DISASSEMBLER',
|
||||
'V8_ENABLE_CHECKS',
|
||||
'OBJECT_PRINT',
|
||||
@ -372,7 +371,10 @@
|
||||
'<(INTERMEDIATE_DIR)/snapshot.cc',
|
||||
],
|
||||
'variables': {
|
||||
'mksnapshot_flags': [],
|
||||
'mksnapshot_flags': [
|
||||
'--log-snapshot-positions',
|
||||
'--logfile', '<(INTERMEDIATE_DIR)/snapshot.log',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
['v8_target_arch=="arm"', {
|
||||
|
Loading…
x
Reference in New Issue
Block a user