Changed shell sample to take flags directly from the command-line. Added api call that implements this.
Added better test support. Added load, quit and version functions to the shell sample so it's easier to run benchmarks and tests. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c42f5829a1
commit
05bbf90b3a
169
SConstruct
169
SConstruct
@ -28,6 +28,7 @@
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
import os
|
||||
from os.path import join, dirname, abspath
|
||||
root_dir = dirname(File('SConstruct').rfile().abspath)
|
||||
sys.path.append(join(root_dir, 'tools'))
|
||||
@ -41,7 +42,8 @@ LIBRARY_FLAGS = {
|
||||
'gcc': {
|
||||
'all': {
|
||||
'DIALECTFLAGS': ['-ansi'],
|
||||
'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
|
||||
'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS',
|
||||
'-fno-strict-aliasing'],
|
||||
'CXXFLAGS': ['$CCFLAGS', '-fno-rtti', '-fno-exceptions'],
|
||||
'LIBS': ['pthread']
|
||||
},
|
||||
@ -52,6 +54,9 @@ LIBRARY_FLAGS = {
|
||||
'mode:release': {
|
||||
'CCFLAGS': ['-O2']
|
||||
},
|
||||
'wordsize:64': {
|
||||
'CCFLAGS': ['-m32']
|
||||
},
|
||||
},
|
||||
'msvc': {
|
||||
'all': {
|
||||
@ -83,10 +88,13 @@ LIBRARY_FLAGS = {
|
||||
V8_EXTRA_FLAGS = {
|
||||
'gcc': {
|
||||
'all': {
|
||||
'CXXFLAGS': ['-fvisibility=hidden'],
|
||||
'CXXFLAGS': [], #['-fvisibility=hidden'],
|
||||
'WARNINGFLAGS': ['-pedantic', '-Wall', '-Werror', '-W',
|
||||
'-Wno-unused-parameter']
|
||||
},
|
||||
'arch:arm': {
|
||||
'CPPDEFINES': ['ARM']
|
||||
},
|
||||
},
|
||||
'msvc': {
|
||||
'all': {
|
||||
@ -95,6 +103,9 @@ V8_EXTRA_FLAGS = {
|
||||
'library:shared': {
|
||||
'CPPDEFINES': ['BUILDING_V8_SHARED']
|
||||
},
|
||||
'arch:arm': {
|
||||
'CPPDEFINES': ['ARM']
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,6 +154,9 @@ CCTEST_EXTRA_FLAGS = {
|
||||
}
|
||||
},
|
||||
'msvc': {
|
||||
'all': {
|
||||
'CPPDEFINES': ['_HAS_EXCEPTIONS=0']
|
||||
},
|
||||
'library:shared': {
|
||||
'CPPDEFINES': ['USING_V8_SHARED']
|
||||
}
|
||||
@ -198,17 +212,24 @@ def GuessOS():
|
||||
elif id == 'Windows':
|
||||
return 'win32'
|
||||
else:
|
||||
return '<none>'
|
||||
return None
|
||||
|
||||
|
||||
def GuessProcessor():
|
||||
def GuessArchitecture():
|
||||
id = platform.machine()
|
||||
if id.startswith('arm'):
|
||||
return 'arm'
|
||||
elif (not id) or (not re.match('(x|i[3-6])86', id) is None):
|
||||
return 'ia32'
|
||||
else:
|
||||
return '<none>'
|
||||
return None
|
||||
|
||||
|
||||
def GuessWordsize():
|
||||
if '64' in platform.machine():
|
||||
return '64'
|
||||
else:
|
||||
return '32'
|
||||
|
||||
|
||||
def GuessToolchain(os):
|
||||
@ -218,21 +239,61 @@ def GuessToolchain(os):
|
||||
elif 'msvc' in tools:
|
||||
return 'msvc'
|
||||
else:
|
||||
return '<none>'
|
||||
return None
|
||||
|
||||
|
||||
OS_GUESS = GuessOS()
|
||||
TOOLCHAIN_GUESS = GuessToolchain(OS_GUESS)
|
||||
ARCH_GUESS = GuessArchitecture()
|
||||
WORDSIZE_GUESS = GuessWordsize()
|
||||
|
||||
|
||||
SIMPLE_OPTIONS = {
|
||||
'toolchain': {
|
||||
'values': ['gcc', 'msvc'],
|
||||
'default': TOOLCHAIN_GUESS,
|
||||
'help': 'the toolchain to use'
|
||||
},
|
||||
'os': {
|
||||
'values': ['linux', 'macos', 'win32'],
|
||||
'default': OS_GUESS,
|
||||
'help': 'the os to build for'
|
||||
},
|
||||
'arch': {
|
||||
'values':['arm', 'ia32'],
|
||||
'default': ARCH_GUESS,
|
||||
'help': 'the architecture to build for'
|
||||
},
|
||||
'snapshot': {
|
||||
'values': ['on', 'off'],
|
||||
'default': 'off',
|
||||
'help': 'build using snapshots for faster start-up'
|
||||
},
|
||||
'library': {
|
||||
'values': ['static', 'shared', 'default'],
|
||||
'default': 'default',
|
||||
'help': 'the type of library to produce'
|
||||
},
|
||||
'wordsize': {
|
||||
'values': ['64', '32'],
|
||||
'default': WORDSIZE_GUESS,
|
||||
'help': 'the word size'
|
||||
},
|
||||
'simulator': {
|
||||
'values': ['arm', 'none'],
|
||||
'default': 'none',
|
||||
'help': 'build with simulator'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def GetOptions():
|
||||
result = Options()
|
||||
os_guess = GuessOS()
|
||||
toolchain_guess = GuessToolchain(os_guess)
|
||||
processor_guess = GuessProcessor()
|
||||
result.Add('mode', 'compilation mode (debug, release)', 'release')
|
||||
result.Add('toolchain', 'the toolchain to use (gcc, msvc)', toolchain_guess)
|
||||
result.Add('os', 'the os to build for (linux, macos, win32)', os_guess)
|
||||
result.Add('processor', 'the processor to build for (arm, ia32)', processor_guess)
|
||||
result.Add('snapshot', 'build using snapshots for faster start-up (on, off)', 'off')
|
||||
result.Add('library', 'which type of library to produce (static, shared, default)', 'default')
|
||||
result.Add('sample', 'build sample (shell, process)', '')
|
||||
for (name, option) in SIMPLE_OPTIONS.items():
|
||||
help = '%s (%s)' % (name, ", ".join(option['values']))
|
||||
result.Add(name, help, option.get('default'))
|
||||
return result
|
||||
|
||||
|
||||
@ -252,51 +313,46 @@ def IsLegal(env, option, values):
|
||||
def VerifyOptions(env):
|
||||
if not IsLegal(env, 'mode', ['debug', 'release']):
|
||||
return False
|
||||
if not env['toolchain'] in ['gcc', 'msvc']:
|
||||
Abort("Unknown toolchain '%s'." % env['toolchain'])
|
||||
if not env['os'] in ['linux', 'macos', 'win32']:
|
||||
Abort("Unknown os '%s'." % env['os'])
|
||||
if not env['processor'] in ['arm', 'ia32']:
|
||||
Abort("Unknown processor '%s'." % env['processor'])
|
||||
if not env['snapshot'] in ['on', 'off']:
|
||||
Abort("Illegal value for option snapshot: '%s'." % env['snapshot'])
|
||||
if not env['library'] in ['static', 'shared', 'default']:
|
||||
Abort("Illegal value for option library: '%s'." % env['library'])
|
||||
if not IsLegal(env, 'sample', ["shell", "process"]):
|
||||
return False
|
||||
for (name, option) in SIMPLE_OPTIONS.items():
|
||||
if (not option.get('default')) and (name not in ARGUMENTS):
|
||||
message = ("A value for option %s must be specified (%s)." %
|
||||
(name, ", ".join(option['values'])))
|
||||
Abort(message)
|
||||
if not env[name] in option['values']:
|
||||
message = ("Unknown %s value '%s'. Possible values are (%s)." %
|
||||
(name, env[name], ", ".join(option['values'])))
|
||||
Abort(message)
|
||||
|
||||
|
||||
class BuildContext(object):
|
||||
|
||||
def __init__(self, os, arch, toolchain, snapshot, library, samples, mode):
|
||||
def __init__(self, options, samples):
|
||||
self.library_targets = []
|
||||
self.cctest_targets = []
|
||||
self.sample_targets = []
|
||||
self.os = os
|
||||
self.arch = arch
|
||||
self.toolchain = toolchain
|
||||
self.snapshot = snapshot
|
||||
self.library = library
|
||||
self.options = options
|
||||
self.samples = samples
|
||||
self.mode = mode
|
||||
self.use_snapshot = (snapshot == 'on')
|
||||
self.use_snapshot = (options['snapshot'] == 'on')
|
||||
self.flags = None
|
||||
|
||||
def AddRelevantFlags(self, initial, flags):
|
||||
result = initial.copy()
|
||||
self.AppendFlags(result, flags.get('all'))
|
||||
self.AppendFlags(result, flags[self.toolchain].get('all'))
|
||||
self.AppendFlags(result, flags[self.toolchain].get('mode:' + self.mode))
|
||||
self.AppendFlags(result, flags[self.toolchain].get('library:' + self.library))
|
||||
toolchain = self.options['toolchain']
|
||||
self.AppendFlags(result, flags[toolchain].get('all'))
|
||||
for option in sorted(self.options.keys()):
|
||||
value = self.options[option]
|
||||
self.AppendFlags(result, flags[toolchain].get(option + ':' + value))
|
||||
return result
|
||||
|
||||
def GetRelevantSources(self, source):
|
||||
result = []
|
||||
result += source.get('all', [])
|
||||
result += source.get('arch:' + self.arch, [])
|
||||
result += source.get('os:' + self.os, [])
|
||||
result += source.get('mode:' + self.mode, [])
|
||||
return result
|
||||
for (name, value) in self.options.items():
|
||||
result += source.get(name + ':' + value, [])
|
||||
return sorted(result)
|
||||
|
||||
def AppendFlags(self, options, added):
|
||||
if not added:
|
||||
@ -306,28 +362,39 @@ class BuildContext(object):
|
||||
options[key] = value
|
||||
else:
|
||||
options[key] = options[key] + value
|
||||
|
||||
|
||||
def ConfigureObject(self, env, input, **kw):
|
||||
if self.library == 'static':
|
||||
if self.options['library'] == 'static':
|
||||
return env.StaticObject(input, **kw)
|
||||
elif self.library == 'shared':
|
||||
elif self.options['library'] == 'shared':
|
||||
return env.SharedObject(input, **kw)
|
||||
else:
|
||||
return env.Object(input, **kw)
|
||||
|
||||
|
||||
def BuildSpecific(env, mode):
|
||||
context = BuildContext(os=env['os'], arch=env['processor'],
|
||||
toolchain=env['toolchain'], snapshot=env['snapshot'],
|
||||
library=env['library'], samples=SplitList(env['sample']),
|
||||
mode=mode)
|
||||
def PostprocessOptions(options):
|
||||
# Adjust architecture if the simulator option has been set
|
||||
if (options['simulator'] != 'none') and (options['arch'] != options['simulator']):
|
||||
if 'arch' in ARGUMENTS:
|
||||
# Print a warning if arch has explicitly been set
|
||||
print "Warning: forcing architecture to match simulator (%s)" % options['simulator']
|
||||
options['arch'] = options['simulator']
|
||||
|
||||
library_flags = context.AddRelevantFlags({}, LIBRARY_FLAGS)
|
||||
|
||||
def BuildSpecific(env, mode):
|
||||
options = {'mode': mode}
|
||||
for option in SIMPLE_OPTIONS:
|
||||
options[option] = env[option]
|
||||
PostprocessOptions(options)
|
||||
|
||||
context = BuildContext(options, samples=SplitList(env['sample']))
|
||||
|
||||
library_flags = context.AddRelevantFlags(os.environ, LIBRARY_FLAGS)
|
||||
v8_flags = context.AddRelevantFlags(library_flags, V8_EXTRA_FLAGS)
|
||||
jscre_flags = context.AddRelevantFlags(library_flags, JSCRE_EXTRA_FLAGS)
|
||||
dtoa_flags = context.AddRelevantFlags(library_flags, DTOA_EXTRA_FLAGS)
|
||||
cctest_flags = context.AddRelevantFlags(v8_flags, CCTEST_EXTRA_FLAGS)
|
||||
sample_flags = context.AddRelevantFlags({}, SAMPLE_FLAGS)
|
||||
sample_flags = context.AddRelevantFlags(os.environ, SAMPLE_FLAGS)
|
||||
|
||||
context.flags = {
|
||||
'v8': v8_flags,
|
||||
@ -351,9 +418,9 @@ def BuildSpecific(env, mode):
|
||||
)
|
||||
|
||||
# Link the object files into a library.
|
||||
if context.library == 'static':
|
||||
if context.options['library'] == 'static':
|
||||
library = env.StaticLibrary(library_name, object_files)
|
||||
elif context.library == 'shared':
|
||||
elif context.options['library'] == 'shared':
|
||||
# There seems to be a glitch in the way scons decides where to put
|
||||
# PDB files when compiling using MSVC so we specify it manually.
|
||||
# This should not affect any other platforms.
|
||||
|
@ -1673,6 +1673,14 @@ class EXPORT V8 {
|
||||
*/
|
||||
static void SetFlagsFromString(const char* str, int length);
|
||||
|
||||
/**
|
||||
* Sets v8 flags from command line.
|
||||
* TODO(758124): Describe flags?
|
||||
*/
|
||||
static void SetFlagsFromCommandLine(int* argc,
|
||||
char** argv,
|
||||
bool remove_flags);
|
||||
|
||||
/** Get the version string. */
|
||||
static const char* GetVersion();
|
||||
|
||||
|
@ -62,7 +62,7 @@ class HttpRequestProcessor {
|
||||
// Initialize this processor. The map contains options that control
|
||||
// how requests should be processed.
|
||||
virtual bool Initialize(map<string, string>* options,
|
||||
map<string, string>* output) = 0;
|
||||
map<string, string>* output) = 0;
|
||||
|
||||
// Process a single request.
|
||||
virtual bool Process(HttpRequest* req) = 0;
|
||||
@ -78,17 +78,17 @@ class JsHttpRequestProcessor : public HttpRequestProcessor {
|
||||
|
||||
// Creates a new processor that processes requests by invoking the
|
||||
// Process function of the JavaScript script given as an argument.
|
||||
JsHttpRequestProcessor(Handle<String> script) : script_(script) { }
|
||||
explicit JsHttpRequestProcessor(Handle<String> script) : script_(script) { }
|
||||
virtual ~JsHttpRequestProcessor();
|
||||
|
||||
virtual bool Initialize(map<string, string>* opts,
|
||||
map<string, string>* output);
|
||||
map<string, string>* output);
|
||||
virtual bool Process(HttpRequest* req);
|
||||
|
||||
private:
|
||||
|
||||
// Execute the script associated with this processor and extract the
|
||||
// Process function. Returns true if this succeeded, otherwise false.
|
||||
// Execute the script associated with this processor and extract the
|
||||
// Process function. Returns true if this succeeded, otherwise false.
|
||||
bool ExecuteScript(Handle<String> script);
|
||||
|
||||
// Wrap the options and output map in a JavaScript objects and
|
||||
@ -108,8 +108,9 @@ class JsHttpRequestProcessor : public HttpRequestProcessor {
|
||||
|
||||
// Callbacks that access maps
|
||||
static Handle<Value> MapGet(Local<String> name, const AccessorInfo& info);
|
||||
static Handle<Value> MapSet(Local<String> name, Local<Value> value,
|
||||
const AccessorInfo& info);
|
||||
static Handle<Value> MapSet(Local<String> name,
|
||||
Local<Value> value,
|
||||
const AccessorInfo& info);
|
||||
|
||||
// Utility methods for wrapping C++ objects as JavaScript objects,
|
||||
// and going back again.
|
||||
@ -142,7 +143,7 @@ static Handle<Value> LogCallback(const Arguments& args) {
|
||||
|
||||
// Execute the script and fetch the Process method.
|
||||
bool JsHttpRequestProcessor::Initialize(map<string, string>* opts,
|
||||
map<string, string>* output) {
|
||||
map<string, string>* output) {
|
||||
// Create a handle scope to hold the temporary references.
|
||||
HandleScope handle_scope;
|
||||
|
||||
@ -223,7 +224,7 @@ bool JsHttpRequestProcessor::ExecuteScript(Handle<String> script) {
|
||||
|
||||
|
||||
bool JsHttpRequestProcessor::InstallMaps(map<string, string>* opts,
|
||||
map<string, string>* output) {
|
||||
map<string, string>* output) {
|
||||
HandleScope handle_scope;
|
||||
|
||||
// Wrap the map object in a JavaScript wrapper
|
||||
@ -335,7 +336,7 @@ string ObjectToString(Local<Value> value) {
|
||||
|
||||
|
||||
Handle<Value> JsHttpRequestProcessor::MapGet(Local<String> name,
|
||||
const AccessorInfo& info) {
|
||||
const AccessorInfo& info) {
|
||||
// Fetch the map wrapped by this object.
|
||||
map<string, string>* obj = UnwrapMap(info.Holder());
|
||||
|
||||
@ -355,7 +356,8 @@ Handle<Value> JsHttpRequestProcessor::MapGet(Local<String> name,
|
||||
|
||||
|
||||
Handle<Value> JsHttpRequestProcessor::MapSet(Local<String> name,
|
||||
Local<Value> value_obj, const AccessorInfo& info) {
|
||||
Local<Value> value_obj,
|
||||
const AccessorInfo& info) {
|
||||
// Fetch the map wrapped by this object.
|
||||
map<string, string>* obj = UnwrapMap(info.Holder());
|
||||
|
||||
@ -433,7 +435,7 @@ HttpRequest* JsHttpRequestProcessor::UnwrapRequest(Handle<Object> obj) {
|
||||
|
||||
|
||||
Handle<Value> JsHttpRequestProcessor::GetPath(Local<String> name,
|
||||
const AccessorInfo& info) {
|
||||
const AccessorInfo& info) {
|
||||
// Extract the C++ request object from the JavaScript wrapper.
|
||||
HttpRequest* request = UnwrapRequest(info.Holder());
|
||||
|
||||
@ -446,7 +448,7 @@ Handle<Value> JsHttpRequestProcessor::GetPath(Local<String> name,
|
||||
|
||||
|
||||
Handle<Value> JsHttpRequestProcessor::GetReferrer(Local<String> name,
|
||||
const AccessorInfo& info) {
|
||||
const AccessorInfo& info) {
|
||||
HttpRequest* request = UnwrapRequest(info.Holder());
|
||||
const string& path = request->Referrer();
|
||||
return String::New(path.c_str(), path.length());
|
||||
@ -454,7 +456,7 @@ Handle<Value> JsHttpRequestProcessor::GetReferrer(Local<String> name,
|
||||
|
||||
|
||||
Handle<Value> JsHttpRequestProcessor::GetHost(Local<String> name,
|
||||
const AccessorInfo& info) {
|
||||
const AccessorInfo& info) {
|
||||
HttpRequest* request = UnwrapRequest(info.Holder());
|
||||
const string& path = request->Host();
|
||||
return String::New(path.c_str(), path.length());
|
||||
@ -462,7 +464,7 @@ Handle<Value> JsHttpRequestProcessor::GetHost(Local<String> name,
|
||||
|
||||
|
||||
Handle<Value> JsHttpRequestProcessor::GetUserAgent(Local<String> name,
|
||||
const AccessorInfo& info) {
|
||||
const AccessorInfo& info) {
|
||||
HttpRequest* request = UnwrapRequest(info.Holder());
|
||||
const string& path = request->UserAgent();
|
||||
return String::New(path.c_str(), path.length());
|
||||
@ -499,8 +501,10 @@ void HttpRequestProcessor::Log(const char* event) {
|
||||
*/
|
||||
class StringHttpRequest : public HttpRequest {
|
||||
public:
|
||||
StringHttpRequest(const string& path, const string& referrer,
|
||||
const string& host, const string& user_agent);
|
||||
StringHttpRequest(const string& path,
|
||||
const string& referrer,
|
||||
const string& host,
|
||||
const string& user_agent);
|
||||
virtual const string& Path() { return path_; }
|
||||
virtual const string& Referrer() { return referrer_; }
|
||||
virtual const string& Host() { return host_; }
|
||||
@ -514,15 +518,19 @@ class StringHttpRequest : public HttpRequest {
|
||||
|
||||
|
||||
StringHttpRequest::StringHttpRequest(const string& path,
|
||||
const string& referrer, const string& host, const string& user_agent)
|
||||
const string& referrer,
|
||||
const string& host,
|
||||
const string& user_agent)
|
||||
: path_(path),
|
||||
referrer_(referrer),
|
||||
host_(host),
|
||||
user_agent_(user_agent) { }
|
||||
|
||||
|
||||
void ParseOptions(int argc, char* argv[], map<string, string>& options,
|
||||
string* file) {
|
||||
void ParseOptions(int argc,
|
||||
char* argv[],
|
||||
map<string, string>& options,
|
||||
string* file) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
string arg = argv[i];
|
||||
int index = arg.find('=', 0);
|
||||
@ -571,7 +579,7 @@ StringHttpRequest kSampleRequests[kSampleSize] = {
|
||||
|
||||
|
||||
bool ProcessEntries(HttpRequestProcessor* processor, int count,
|
||||
StringHttpRequest* reqs) {
|
||||
StringHttpRequest* reqs) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!processor->Process(&reqs[i]))
|
||||
return false;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <v8.h>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
void RunShell(v8::Handle<v8::Context> context);
|
||||
@ -35,18 +36,28 @@ bool ExecuteString(v8::Handle<v8::String> source,
|
||||
v8::Handle<v8::Value> name,
|
||||
bool print_result);
|
||||
v8::Handle<v8::Value> Print(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::String> ReadFile(const char* name);
|
||||
void ProcessRuntimeFlags(int argc, char* argv[]);
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
ProcessRuntimeFlags(argc, argv);
|
||||
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
|
||||
v8::HandleScope handle_scope;
|
||||
// Create a template for the global object.
|
||||
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
|
||||
// Bind the global 'print' function to the C++ Print callback.
|
||||
global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print));
|
||||
// Create a new execution environment containing the 'print' function.
|
||||
// Bind the global 'load' function to the C++ Load callback.
|
||||
global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load));
|
||||
// Bind the 'quit' function
|
||||
global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit));
|
||||
// Bind the 'version' function
|
||||
global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version));
|
||||
// Create a new execution environment containing the built-in
|
||||
// functions
|
||||
v8::Handle<v8::Context> context = v8::Context::New(NULL, global);
|
||||
// Enter the newly created execution environment.
|
||||
v8::Context::Scope context_scope(context);
|
||||
@ -55,9 +66,8 @@ int main(int argc, char* argv[]) {
|
||||
const char* str = argv[i];
|
||||
if (strcmp(str, "--shell") == 0) {
|
||||
run_shell = true;
|
||||
} else if (strcmp(str, "--runtime-flags") == 0) {
|
||||
// Skip the --runtime-flags flag since it was processed earlier.
|
||||
i++;
|
||||
} else if (strncmp(str, "--", 2) == 0) {
|
||||
printf("Warning: unknown flag %s.\n", str);
|
||||
} else {
|
||||
// Use all other arguments as names of files to load and run.
|
||||
v8::HandleScope handle_scope;
|
||||
@ -93,6 +103,39 @@ v8::Handle<v8::Value> Print(const v8::Arguments& args) {
|
||||
}
|
||||
|
||||
|
||||
// The callback that is invoked by v8 whenever the JavaScript 'load'
|
||||
// function is called. Loads, compiles and executes its argument
|
||||
// JavaScript file.
|
||||
v8::Handle<v8::Value> Load(const v8::Arguments& args) {
|
||||
for (int i = 0; i < args.Length(); i++) {
|
||||
v8::HandleScope handle_scope;
|
||||
v8::String::AsciiValue file(args[i]);
|
||||
v8::Handle<v8::String> source = ReadFile(*file);
|
||||
if (source.IsEmpty()) {
|
||||
return v8::ThrowException(v8::String::New("Error loading file"));
|
||||
}
|
||||
ExecuteString(source, v8::String::New(*file), false);
|
||||
}
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
|
||||
// The callback that is invoked by v8 whenever the JavaScript 'quit'
|
||||
// function is called. Quits.
|
||||
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();
|
||||
exit(exit_code);
|
||||
return v8::Undefined();
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<v8::Value> Version(const v8::Arguments& args) {
|
||||
return v8::String::New(v8::V8::GetVersion());
|
||||
}
|
||||
|
||||
|
||||
// Reads a file into a v8 string.
|
||||
v8::Handle<v8::String> ReadFile(const char* name) {
|
||||
FILE* file = fopen(name, "rb");
|
||||
@ -161,14 +204,3 @@ bool ExecuteString(v8::Handle<v8::String> source,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Set the vm flags before using the vm.
|
||||
void ProcessRuntimeFlags(int argc, char* argv[]) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--runtime-flags") == 0 && i + 1 < argc) {
|
||||
i++;
|
||||
v8::V8::SetFlagsFromString(argv[i], strlen(argv[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,10 +50,11 @@ SOURCES = {
|
||||
],
|
||||
'arch:arm': ['assembler-arm.cc', 'builtins-arm.cc', 'codegen-arm.cc',
|
||||
'cpu-arm.cc', 'disasm-arm.cc', 'frames-arm.cc', 'ic-arm.cc',
|
||||
'macro-assembler-arm.cc', 'simulator-arm.cc', 'stub-cache-arm.cc'],
|
||||
'macro-assembler-arm.cc', 'stub-cache-arm.cc'],
|
||||
'arch:ia32': ['assembler-ia32.cc', 'builtins-ia32.cc', 'codegen-ia32.cc',
|
||||
'cpu-ia32.cc', 'disasm-ia32.cc', 'frames-ia32.cc', 'ic-ia32.cc',
|
||||
'macro-assembler-ia32.cc', 'simulator-ia32.cc', 'stub-cache-ia32.cc'],
|
||||
'macro-assembler-ia32.cc', 'stub-cache-ia32.cc'],
|
||||
'simulator:arm': ['simulator-arm.cc'],
|
||||
'os:linux': ['platform-linux.cc'],
|
||||
'os:macos': ['platform-macos.cc'],
|
||||
'os:nullos': ['platform-nullos.cc'],
|
||||
|
@ -223,6 +223,11 @@ void V8::SetFlagsFromString(const char* str, int length) {
|
||||
}
|
||||
|
||||
|
||||
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
|
||||
i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
|
||||
if (IsDeadCheck("v8::ThrowException()")) return v8::Handle<Value>();
|
||||
i::Top::ScheduleThrow(*Utils::OpenHandle(*value));
|
||||
|
@ -1,29 +1,38 @@
|
||||
// Copyright 2007-2008 Google Inc. All Rights Reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// Copyright (c) 1994-2006 Sun Microsystems Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// * 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.
|
||||
// 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.
|
||||
//
|
||||
// - Redistribution 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 Sun Microsystems or the names of 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.
|
||||
// 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.
|
||||
|
||||
// The original source code covered by the above license above has been modified
|
||||
// significantly by Google Inc.
|
||||
// Copyright 2006-2008 Google Inc. All Rights Reserved.
|
||||
|
||||
#ifndef V8_ASSEMBLER_ARM_INL_H_
|
||||
#define V8_ASSEMBLER_ARM_INL_H_
|
||||
|
@ -1,29 +1,38 @@
|
||||
// Copyright 2006-2008 Google Inc. All Rights Reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// Copyright (c) 1994-2006 Sun Microsystems Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// * 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.
|
||||
// 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.
|
||||
//
|
||||
// - Redistribution 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 Sun Microsystems or the names of 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.
|
||||
// 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.
|
||||
|
||||
// The original source code covered by the above license above has been modified
|
||||
// significantly by Google Inc.
|
||||
// Copyright 2006-2008 Google Inc. All Rights Reserved.
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
|
@ -1,29 +1,38 @@
|
||||
// Copyright 2007-2008 Google Inc. All Rights Reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
// Copyright (c) 1994-2006 Sun Microsystems Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// * 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.
|
||||
// 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.
|
||||
//
|
||||
// - Redistribution 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 Sun Microsystems or the names of 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.
|
||||
// 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.
|
||||
|
||||
// The original source code covered by the above license above has been modified
|
||||
// significantly by Google Inc.
|
||||
// Copyright 2006-2008 Google Inc. All Rights Reserved.
|
||||
|
||||
// A light-weight ARM Assembler
|
||||
// Generates user mode instructions for the ARM architecture up to version 5
|
||||
|
@ -379,9 +379,9 @@ Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
|
||||
|
||||
// Add prototype.
|
||||
PropertyAttributes attributes = static_cast<PropertyAttributes>(
|
||||
(make_prototype_enumerable ? 0 : DONT_ENUM)
|
||||
| DONT_DELETE
|
||||
| (make_prototype_read_only ? READ_ONLY : 0));
|
||||
(make_prototype_enumerable ? 0 : DONT_ENUM)
|
||||
| DONT_DELETE
|
||||
| (make_prototype_read_only ? READ_ONLY : 0));
|
||||
result =
|
||||
Factory::CopyAppendProxyDescriptor(
|
||||
result,
|
||||
@ -481,8 +481,8 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
|
||||
|
||||
global_context()->set_initial_object_prototype(*prototype);
|
||||
SetPrototype(object_fun, prototype);
|
||||
object_function_map->set_instance_descriptors(
|
||||
DescriptorArray::cast(Heap::empty_fixed_array()));
|
||||
object_function_map->
|
||||
set_instance_descriptors(Heap::empty_descriptor_array());
|
||||
}
|
||||
|
||||
// Allocate the empty function as the prototype for function ECMAScript
|
||||
@ -1192,7 +1192,8 @@ void Genesis::TransferNamedProperties(Handle<JSObject> from,
|
||||
}
|
||||
case MAP_TRANSITION:
|
||||
case CONSTANT_TRANSITION:
|
||||
// Ignore map transitions.
|
||||
case NULL_DESCRIPTOR:
|
||||
// Ignore non-properties.
|
||||
break;
|
||||
case NORMAL:
|
||||
// Do not occur since the from object has fast properties.
|
||||
|
@ -352,7 +352,7 @@ BUILTIN_0(HandleApiCall) {
|
||||
HandleScope scope;
|
||||
|
||||
// TODO(1238487): This is not nice. We need to get rid of this
|
||||
// retarded behavior and start handling API calls in a more direct
|
||||
// kludgy behavior and start handling API calls in a more direct
|
||||
// way - maybe compile specialized stubs lazily?.
|
||||
#ifdef USE_OLD_CALLING_CONVENTIONS
|
||||
Handle<JSFunction> function =
|
||||
|
@ -1084,6 +1084,12 @@ class GenericBinaryOpStub : public CodeStub {
|
||||
case Token::SUB: return "GenericBinaryOpStub_SUB";
|
||||
case Token::MUL: return "GenericBinaryOpStub_MUL";
|
||||
case Token::DIV: return "GenericBinaryOpStub_DIV";
|
||||
case Token::BIT_OR: return "GenericBinaryOpStub_BIT_OR";
|
||||
case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND";
|
||||
case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR";
|
||||
case Token::SAR: return "GenericBinaryOpStub_SAR";
|
||||
case Token::SHL: return "GenericBinaryOpStub_SHL";
|
||||
case Token::SHR: return "GenericBinaryOpStub_SHR";
|
||||
default: return "GenericBinaryOpStub";
|
||||
}
|
||||
}
|
||||
@ -1175,75 +1181,104 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
|
||||
__ bind(&exit);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::BIT_OR:
|
||||
case Token::BIT_AND:
|
||||
case Token::BIT_XOR: {
|
||||
Label slow, exit;
|
||||
// tag check
|
||||
__ orr(r2, r1, Operand(r0)); // r2 = x | y;
|
||||
ASSERT(kSmiTag == 0); // adjust code below
|
||||
__ tst(r2, Operand(kSmiTagMask));
|
||||
__ b(ne, &slow);
|
||||
switch (op_) {
|
||||
case Token::BIT_OR: __ orr(r0, r0, Operand(r1)); break;
|
||||
case Token::BIT_AND: __ and_(r0, r0, Operand(r1)); break;
|
||||
case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
__ b(&exit);
|
||||
__ bind(&slow);
|
||||
__ push(r1); // restore stack
|
||||
__ push(r0);
|
||||
__ mov(r0, Operand(1)); // 1 argument (not counting receiver).
|
||||
switch (op_) {
|
||||
case Token::BIT_OR: __ InvokeBuiltin("BIT_OR", 1, JUMP_JS); break;
|
||||
case Token::BIT_AND: __ InvokeBuiltin("BIT_AND", 1, JUMP_JS); break;
|
||||
case Token::BIT_XOR: __ InvokeBuiltin("BIT_XOR", 1, JUMP_JS); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
__ bind(&exit);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::SHL:
|
||||
case Token::SHR:
|
||||
case Token::SAR: {
|
||||
Label slow, exit;
|
||||
// tag check
|
||||
__ orr(r2, r1, Operand(r0)); // r2 = x | y;
|
||||
ASSERT(kSmiTag == 0); // adjust code below
|
||||
__ tst(r2, Operand(kSmiTagMask));
|
||||
__ b(ne, &slow);
|
||||
// remove tags from operands (but keep sign)
|
||||
__ mov(r3, Operand(r1, ASR, kSmiTagSize)); // x
|
||||
__ mov(r2, Operand(r0, ASR, kSmiTagSize)); // y
|
||||
// use only the 5 least significant bits of the shift count
|
||||
__ and_(r2, r2, Operand(0x1f));
|
||||
// perform operation
|
||||
switch (op_) {
|
||||
case Token::SAR:
|
||||
__ mov(r3, Operand(r3, ASR, r2));
|
||||
// no checks of result necessary
|
||||
break;
|
||||
|
||||
case Token::SHR:
|
||||
__ mov(r3, Operand(r3, LSR, r2));
|
||||
// check that the *unsigned* result fits in a smi
|
||||
// neither of the two high-order bits can be set:
|
||||
// - 0x80000000: high bit would be lost when smi tagging
|
||||
// - 0x40000000: this number would convert to negative when
|
||||
// smi tagging these two cases can only happen with shifts
|
||||
// by 0 or 1 when handed a valid smi
|
||||
__ and_(r2, r3, Operand(0xc0000000), SetCC);
|
||||
__ b(ne, &slow);
|
||||
break;
|
||||
|
||||
case Token::SHL:
|
||||
__ mov(r3, Operand(r3, LSL, r2));
|
||||
// check that the *signed* result fits in a smi
|
||||
__ add(r2, r3, Operand(0x40000000), SetCC);
|
||||
__ b(mi, &slow);
|
||||
break;
|
||||
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
// tag result and store it in r0
|
||||
ASSERT(kSmiTag == 0); // adjust code below
|
||||
__ mov(r0, Operand(r3, LSL, kSmiTagSize));
|
||||
__ b(&exit);
|
||||
// slow case
|
||||
__ bind(&slow);
|
||||
__ push(r1); // restore stack
|
||||
__ push(r0);
|
||||
__ mov(r0, Operand(1)); // 1 argument (not counting receiver).
|
||||
switch (op_) {
|
||||
case Token::SAR: __ InvokeBuiltin("SAR", 1, JUMP_JS); break;
|
||||
case Token::SHR: __ InvokeBuiltin("SHR", 1, JUMP_JS); break;
|
||||
case Token::SHL: __ InvokeBuiltin("SHL", 1, JUMP_JS); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
__ bind(&exit);
|
||||
break;
|
||||
}
|
||||
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
|
||||
class SmiOpStub : public CodeStub {
|
||||
public:
|
||||
SmiOpStub(Token::Value op, bool reversed)
|
||||
: op_(op), reversed_(reversed) {}
|
||||
|
||||
private:
|
||||
Token::Value op_;
|
||||
bool reversed_;
|
||||
|
||||
Major MajorKey() { return SmiOp; }
|
||||
int MinorKey() {
|
||||
return (op_ == Token::ADD ? 2 : 0) | (reversed_ ? 1 : 0);
|
||||
}
|
||||
void Generate(MacroAssembler* masm);
|
||||
void GenerateShared(MacroAssembler* masm);
|
||||
|
||||
const char* GetName() { return "SmiOpStub"; }
|
||||
|
||||
#ifdef DEBUG
|
||||
void Print() {
|
||||
PrintF("SmiOpStub (token %s), (reversed %s)\n",
|
||||
Token::String(op_), reversed_ ? "true" : "false");
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
void SmiOpStub::Generate(MacroAssembler* masm) {
|
||||
switch (op_) {
|
||||
case Token::ADD: {
|
||||
if (!reversed_) {
|
||||
__ sub(r0, r0, Operand(r1)); // revert optimistic add
|
||||
__ push(r0);
|
||||
__ push(r1);
|
||||
__ mov(r0, Operand(1)); // set number of arguments
|
||||
__ InvokeBuiltin("ADD", 1, JUMP_JS);
|
||||
} else {
|
||||
__ sub(r0, r0, Operand(r1)); // revert optimistic add
|
||||
__ push(r1); // reversed
|
||||
__ push(r0);
|
||||
__ mov(r0, Operand(1)); // set number of arguments
|
||||
__ InvokeBuiltin("ADD", 1, JUMP_JS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Token::SUB: {
|
||||
if (!reversed_) {
|
||||
__ push(r0);
|
||||
__ push(r1);
|
||||
__ mov(r0, Operand(1)); // set number of arguments
|
||||
__ InvokeBuiltin("SUB", 1, JUMP_JS);
|
||||
} else {
|
||||
__ push(r1);
|
||||
__ push(r0);
|
||||
__ mov(r0, Operand(1)); // set number of arguments
|
||||
__ InvokeBuiltin("SUB", 1, JUMP_JS);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void StackCheckStub::Generate(MacroAssembler* masm) {
|
||||
Label within_limit;
|
||||
__ mov(ip, Operand(ExternalReference::address_of_stack_guard_limit()));
|
||||
@ -1866,7 +1901,13 @@ void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
|
||||
switch (op) {
|
||||
case Token::ADD: // fall through.
|
||||
case Token::SUB: // fall through.
|
||||
case Token::MUL: {
|
||||
case Token::MUL:
|
||||
case Token::BIT_OR:
|
||||
case Token::BIT_AND:
|
||||
case Token::BIT_XOR:
|
||||
case Token::SHL:
|
||||
case Token::SHR:
|
||||
case Token::SAR: {
|
||||
__ pop(r0); // r0 : y
|
||||
__ pop(r1); // r1 : x
|
||||
GenericBinaryOpStub stub(op);
|
||||
@ -1886,101 +1927,6 @@ void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::BIT_OR:
|
||||
case Token::BIT_AND:
|
||||
case Token::BIT_XOR: {
|
||||
Label slow, exit;
|
||||
__ pop(r0); // get y
|
||||
__ pop(r1); // get x
|
||||
// tag check
|
||||
__ orr(r2, r1, Operand(r0)); // r2 = x | y;
|
||||
ASSERT(kSmiTag == 0); // adjust code below
|
||||
__ tst(r2, Operand(kSmiTagMask));
|
||||
__ b(ne, &slow);
|
||||
switch (op) {
|
||||
case Token::BIT_OR: __ orr(r0, r0, Operand(r1)); break;
|
||||
case Token::BIT_AND: __ and_(r0, r0, Operand(r1)); break;
|
||||
case Token::BIT_XOR: __ eor(r0, r0, Operand(r1)); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
__ b(&exit);
|
||||
__ bind(&slow);
|
||||
__ push(r1); // restore stack
|
||||
__ push(r0);
|
||||
__ mov(r0, Operand(1)); // 1 argument (not counting receiver).
|
||||
switch (op) {
|
||||
case Token::BIT_OR: __ InvokeBuiltin("BIT_OR", 1, CALL_JS); break;
|
||||
case Token::BIT_AND: __ InvokeBuiltin("BIT_AND", 1, CALL_JS); break;
|
||||
case Token::BIT_XOR: __ InvokeBuiltin("BIT_XOR", 1, CALL_JS); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
__ bind(&exit);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::SHL:
|
||||
case Token::SHR:
|
||||
case Token::SAR: {
|
||||
Label slow, exit;
|
||||
__ pop(r0); // get y
|
||||
__ pop(r1); // get x
|
||||
// tag check
|
||||
__ orr(r2, r1, Operand(r0)); // r2 = x | y;
|
||||
ASSERT(kSmiTag == 0); // adjust code below
|
||||
__ tst(r2, Operand(kSmiTagMask));
|
||||
__ b(ne, &slow);
|
||||
// remove tags from operands (but keep sign)
|
||||
__ mov(r3, Operand(r1, ASR, kSmiTagSize));
|
||||
__ mov(r2, Operand(r0, ASR, kSmiTagSize));
|
||||
// use only the 5 least significant bits of the shift count
|
||||
__ and_(r2, r2, Operand(0x1f));
|
||||
// perform operation
|
||||
switch (op) {
|
||||
case Token::SAR:
|
||||
__ mov(r3, Operand(r3, ASR, r2));
|
||||
// no checks of result necessary
|
||||
break;
|
||||
|
||||
case Token::SHR:
|
||||
__ mov(r3, Operand(r3, LSR, r2));
|
||||
// check that the *unsigned* result fits in a smi
|
||||
// neither of the two high-order bits can be set:
|
||||
// - 0x80000000: high bit would be lost when smi tagging
|
||||
// - 0x40000000: this number would convert to negative when
|
||||
// smi tagging these two cases can only happen with shifts
|
||||
// by 0 or 1 when handed a valid smi
|
||||
__ and_(r2, r3, Operand(0xc0000000), SetCC);
|
||||
__ b(ne, &slow);
|
||||
break;
|
||||
|
||||
case Token::SHL:
|
||||
__ mov(r3, Operand(r3, LSL, r2));
|
||||
// check that the *signed* result fits in a smi
|
||||
__ add(r2, r3, Operand(0x40000000), SetCC);
|
||||
__ b(mi, &slow);
|
||||
break;
|
||||
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
// tag result and store it in r0
|
||||
ASSERT(kSmiTag == 0); // adjust code below
|
||||
__ mov(r0, Operand(r3, LSL, kSmiTagSize));
|
||||
__ b(&exit);
|
||||
// slow case
|
||||
__ bind(&slow);
|
||||
__ push(r1); // restore stack
|
||||
__ push(r0);
|
||||
__ mov(r0, Operand(1)); // 1 argument (not counting receiver).
|
||||
switch (op) {
|
||||
case Token::SAR: __ InvokeBuiltin("SAR", 1, CALL_JS); break;
|
||||
case Token::SHR: __ InvokeBuiltin("SHR", 1, CALL_JS); break;
|
||||
case Token::SHL: __ InvokeBuiltin("SHL", 1, CALL_JS); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
__ bind(&exit);
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::COMMA:
|
||||
__ pop(r0);
|
||||
// simply discard left value
|
||||
@ -1995,6 +1941,82 @@ void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
|
||||
}
|
||||
|
||||
|
||||
class DeferredInlinedSmiOperation: public DeferredCode {
|
||||
public:
|
||||
DeferredInlinedSmiOperation(CodeGenerator* generator, Token::Value op,
|
||||
int value, bool reversed) :
|
||||
DeferredCode(generator), op_(op), value_(value), reversed_(reversed) {
|
||||
set_comment("[ DeferredInlinedSmiOperation");
|
||||
}
|
||||
|
||||
virtual void Generate() {
|
||||
switch (op_) {
|
||||
case Token::ADD: {
|
||||
if (reversed_) {
|
||||
// revert optimistic add
|
||||
__ sub(r0, r0, Operand(Smi::FromInt(value_)));
|
||||
__ mov(r1, Operand(Smi::FromInt(value_))); // x
|
||||
} else {
|
||||
// revert optimistic add
|
||||
__ sub(r1, r0, Operand(Smi::FromInt(value_)));
|
||||
__ mov(r0, Operand(Smi::FromInt(value_)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::SUB: {
|
||||
if (reversed_) {
|
||||
// revert optimistic sub
|
||||
__ rsb(r0, r0, Operand(Smi::FromInt(value_)));
|
||||
__ mov(r1, Operand(Smi::FromInt(value_)));
|
||||
} else {
|
||||
__ add(r1, r0, Operand(Smi::FromInt(value_)));
|
||||
__ mov(r0, Operand(Smi::FromInt(value_)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::BIT_OR:
|
||||
case Token::BIT_XOR:
|
||||
case Token::BIT_AND: {
|
||||
if (reversed_) {
|
||||
__ mov(r1, Operand(Smi::FromInt(value_)));
|
||||
} else {
|
||||
__ mov(r1, Operand(r0));
|
||||
__ mov(r0, Operand(Smi::FromInt(value_)));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::SHL:
|
||||
case Token::SHR:
|
||||
case Token::SAR: {
|
||||
if (!reversed_) {
|
||||
__ mov(r1, Operand(r0));
|
||||
__ mov(r0, Operand(Smi::FromInt(value_)));
|
||||
} else {
|
||||
UNREACHABLE(); // should have been handled in SmiOperation
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// other cases should have been handled before this point.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
GenericBinaryOpStub igostub(op_);
|
||||
__ CallStub(&igostub);
|
||||
}
|
||||
|
||||
private:
|
||||
Token::Value op_;
|
||||
int value_;
|
||||
bool reversed_;
|
||||
};
|
||||
|
||||
|
||||
void ArmCodeGenerator::SmiOperation(Token::Value op,
|
||||
Handle<Object> value,
|
||||
bool reversed) {
|
||||
@ -2007,45 +2029,108 @@ void ArmCodeGenerator::SmiOperation(Token::Value op,
|
||||
|
||||
// sp[0] : operand
|
||||
|
||||
ASSERT(value->IsSmi());
|
||||
int int_value = Smi::cast(*value)->value();
|
||||
|
||||
Label exit;
|
||||
__ pop(r0);
|
||||
|
||||
switch (op) {
|
||||
case Token::ADD: {
|
||||
Label slow;
|
||||
DeferredCode* deferred =
|
||||
new DeferredInlinedSmiOperation(this, op, int_value, reversed);
|
||||
|
||||
__ mov(r1, Operand(value));
|
||||
__ add(r0, r0, Operand(r1), SetCC);
|
||||
__ b(vs, &slow);
|
||||
__ add(r0, r0, Operand(value), SetCC);
|
||||
__ b(vs, deferred->enter());
|
||||
__ tst(r0, Operand(kSmiTagMask));
|
||||
__ b(eq, &exit);
|
||||
__ bind(&slow);
|
||||
|
||||
SmiOpStub stub(Token::ADD, reversed);
|
||||
__ CallStub(&stub);
|
||||
__ b(ne, deferred->enter());
|
||||
__ bind(deferred->exit());
|
||||
break;
|
||||
}
|
||||
|
||||
case Token::SUB: {
|
||||
Label slow;
|
||||
DeferredCode* deferred =
|
||||
new DeferredInlinedSmiOperation(this, op, int_value, reversed);
|
||||
|
||||
__ mov(r1, Operand(value));
|
||||
if (!reversed) {
|
||||
__ sub(r2, r0, Operand(r1), SetCC);
|
||||
__ sub(r0, r0, Operand(value), SetCC);
|
||||
} else {
|
||||
__ rsb(r2, r0, Operand(r1), SetCC);
|
||||
__ rsb(r0, r0, Operand(value), SetCC);
|
||||
}
|
||||
__ b(vs, &slow);
|
||||
__ tst(r2, Operand(kSmiTagMask));
|
||||
__ mov(r0, Operand(r2), LeaveCC, eq); // conditionally set r0 to result
|
||||
__ b(eq, &exit);
|
||||
__ b(vs, deferred->enter());
|
||||
__ tst(r0, Operand(kSmiTagMask));
|
||||
__ b(ne, deferred->enter());
|
||||
__ bind(deferred->exit());
|
||||
break;
|
||||
}
|
||||
|
||||
__ bind(&slow);
|
||||
case Token::BIT_OR:
|
||||
case Token::BIT_XOR:
|
||||
case Token::BIT_AND: {
|
||||
DeferredCode* deferred =
|
||||
new DeferredInlinedSmiOperation(this, op, int_value, reversed);
|
||||
__ tst(r0, Operand(kSmiTagMask));
|
||||
__ b(ne, deferred->enter());
|
||||
switch (op) {
|
||||
case Token::BIT_OR: __ orr(r0, r0, Operand(value)); break;
|
||||
case Token::BIT_XOR: __ eor(r0, r0, Operand(value)); break;
|
||||
case Token::BIT_AND: __ and_(r0, r0, Operand(value)); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
__ bind(deferred->exit());
|
||||
break;
|
||||
}
|
||||
|
||||
SmiOpStub stub(Token::SUB, reversed);
|
||||
__ CallStub(&stub);
|
||||
case Token::SHL:
|
||||
case Token::SHR:
|
||||
case Token::SAR: {
|
||||
if (reversed) {
|
||||
__ mov(ip, Operand(value));
|
||||
__ push(ip);
|
||||
__ push(r0);
|
||||
GenericBinaryOperation(op);
|
||||
|
||||
} else {
|
||||
int shift_value = int_value & 0x1f; // least significant 5 bits
|
||||
DeferredCode* deferred =
|
||||
new DeferredInlinedSmiOperation(this, op, shift_value, false);
|
||||
__ tst(r0, Operand(kSmiTagMask));
|
||||
__ b(ne, deferred->enter());
|
||||
__ mov(r2, Operand(r0, ASR, kSmiTagSize)); // remove tags
|
||||
switch (op) {
|
||||
case Token::SHL: {
|
||||
__ mov(r2, Operand(r2, LSL, shift_value));
|
||||
// check that the *unsigned* result fits in a smi
|
||||
__ add(r3, r2, Operand(0x40000000), SetCC);
|
||||
__ b(mi, deferred->enter());
|
||||
break;
|
||||
}
|
||||
case Token::SHR: {
|
||||
// LSR by immediate 0 means shifting 32 bits.
|
||||
if (shift_value != 0) {
|
||||
__ mov(r2, Operand(r2, LSR, shift_value));
|
||||
}
|
||||
// check that the *unsigned* result fits in a smi
|
||||
// neither of the two high-order bits can be set:
|
||||
// - 0x80000000: high bit would be lost when smi tagging
|
||||
// - 0x40000000: this number would convert to negative when
|
||||
// smi tagging these two cases can only happen with shifts
|
||||
// by 0 or 1 when handed a valid smi
|
||||
__ and_(r3, r2, Operand(0xc0000000), SetCC);
|
||||
__ b(ne, deferred->enter());
|
||||
break;
|
||||
}
|
||||
case Token::SAR: {
|
||||
if (shift_value != 0) {
|
||||
// ASR by immediate 0 means shifting 32 bits.
|
||||
__ mov(r2, Operand(r2, ASR, shift_value));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
__ mov(r0, Operand(r2, LSL, kSmiTagSize));
|
||||
__ bind(deferred->exit());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -555,8 +555,7 @@ Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor,
|
||||
Handle<JSObject> Factory::NewObjectLiteral(int expected_number_of_properties) {
|
||||
Handle<Map> map = Handle<Map>(Top::object_function()->initial_map());
|
||||
map = Factory::CopyMap(map);
|
||||
map->set_instance_descriptors(
|
||||
DescriptorArray::cast(Heap::empty_fixed_array()));
|
||||
map->set_instance_descriptors(Heap::empty_descriptor_array());
|
||||
map->set_unused_property_fields(expected_number_of_properties);
|
||||
CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, TENURED),
|
||||
JSObject);
|
||||
@ -704,7 +703,7 @@ Handle<JSFunction> Factory::CreateApiFunction(
|
||||
if (parent->IsUndefined()) break;
|
||||
obj = Handle<FunctionTemplateInfo>::cast(parent);
|
||||
}
|
||||
if (array->length() > 0) {
|
||||
if (!array->IsEmpty()) {
|
||||
map->set_instance_descriptors(*array);
|
||||
}
|
||||
|
||||
|
@ -281,10 +281,6 @@ class Factory : public AllStatic {
|
||||
SYMBOL_LIST(SYMBOL_ACCESSOR)
|
||||
#undef SYMBOL_ACCESSOR
|
||||
|
||||
static Handle<DescriptorArray> empty_descriptor_array() {
|
||||
return Handle<DescriptorArray>::cast(empty_fixed_array());
|
||||
}
|
||||
|
||||
static Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);
|
||||
|
||||
static Handle<Dictionary> DictionaryAtNumberPut(Handle<Dictionary>,
|
||||
|
12
src/flags.cc
12
src/flags.cc
@ -301,8 +301,16 @@ int FlagList::SetFlagsFromCommandLine(int* argc,
|
||||
// lookup the flag
|
||||
Flag* flag = Lookup(name);
|
||||
if (flag == NULL) {
|
||||
fprintf(stderr, "Error: unrecognized flag %s\n", arg);
|
||||
return j;
|
||||
if (remove_flags) {
|
||||
// We don't recognize this flag but since we're removing
|
||||
// the flags we recognize we assume that the remaining flags
|
||||
// will be processed somewhere else so this flag might make
|
||||
// sense there.
|
||||
continue;
|
||||
} else {
|
||||
fprintf(stderr, "Error: unrecognized flag %s\n", arg);
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
||||
// if we still need a flag value, use the next argument if available
|
||||
|
@ -304,7 +304,8 @@ enum PropertyType {
|
||||
FIELD = 3, // only in fast mode
|
||||
CALLBACKS = 4,
|
||||
CONSTANT_TRANSITION = 5, // only in fast mode
|
||||
INTERCEPTOR = 6
|
||||
INTERCEPTOR = 6,
|
||||
NULL_DESCRIPTOR = 7 // only in fast mode
|
||||
};
|
||||
|
||||
|
||||
|
@ -160,14 +160,6 @@ void Heap::RecordWrite(Address address, int offset) {
|
||||
}
|
||||
|
||||
|
||||
Object* Heap::AllocatePropertyStorageForMap(Map* map) {
|
||||
if (map->unused_property_fields() > 0) {
|
||||
return AllocateFixedArray(map->unused_property_fields());
|
||||
}
|
||||
return Heap::empty_fixed_array();
|
||||
}
|
||||
|
||||
|
||||
AllocationSpace Heap::TargetSpace(HeapObject* object) {
|
||||
// Heap numbers and sequential strings are promoted to code space, all
|
||||
// other object types are promoted to old space. We do not use
|
||||
|
22
src/heap.cc
22
src/heap.cc
@ -861,7 +861,7 @@ Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) {
|
||||
map->set_prototype(null_value());
|
||||
map->set_constructor(null_value());
|
||||
map->set_instance_size(instance_size);
|
||||
map->set_instance_descriptors(DescriptorArray::cast(empty_fixed_array()));
|
||||
map->set_instance_descriptors(empty_descriptor_array());
|
||||
map->set_code_cache(empty_fixed_array());
|
||||
map->set_unused_property_fields(0);
|
||||
map->set_bit_field(0);
|
||||
@ -894,17 +894,20 @@ bool Heap::CreateInitialMaps() {
|
||||
if (obj->IsFailure()) return false;
|
||||
null_value_ = obj;
|
||||
|
||||
// Fix the instance_descriptors for the existing maps.
|
||||
DescriptorArray* empty_descriptors =
|
||||
DescriptorArray::cast(empty_fixed_array());
|
||||
// Allocate the empty descriptor array. AllocateMap can now be used.
|
||||
obj = AllocateEmptyFixedArray();
|
||||
if (obj->IsFailure()) return false;
|
||||
// There is a check against empty_descriptor_array() in cast().
|
||||
empty_descriptor_array_ = reinterpret_cast<DescriptorArray*>(obj);
|
||||
|
||||
meta_map()->set_instance_descriptors(empty_descriptors);
|
||||
// Fix the instance_descriptors for the existing maps.
|
||||
meta_map()->set_instance_descriptors(empty_descriptor_array());
|
||||
meta_map()->set_code_cache(empty_fixed_array());
|
||||
|
||||
fixed_array_map()->set_instance_descriptors(empty_descriptors);
|
||||
fixed_array_map()->set_instance_descriptors(empty_descriptor_array());
|
||||
fixed_array_map()->set_code_cache(empty_fixed_array());
|
||||
|
||||
oddball_map()->set_instance_descriptors(empty_descriptors);
|
||||
oddball_map()->set_instance_descriptors(empty_descriptor_array());
|
||||
oddball_map()->set_code_cache(empty_fixed_array());
|
||||
|
||||
// Fix prototype object for existing maps.
|
||||
@ -1004,6 +1007,7 @@ bool Heap::CreateInitialMaps() {
|
||||
if (obj->IsFailure()) return false;
|
||||
shared_function_info_map_ = Map::cast(obj);
|
||||
|
||||
ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1701,7 +1705,7 @@ Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) {
|
||||
ASSERT(map->instance_type() != JS_FUNCTION_TYPE);
|
||||
|
||||
// Allocate the backing storage for the properties.
|
||||
Object* properties = AllocatePropertyStorageForMap(map);
|
||||
Object* properties = AllocateFixedArray(map->unused_property_fields());
|
||||
if (properties->IsFailure()) return properties;
|
||||
|
||||
// Allocate the JSObject.
|
||||
@ -1749,7 +1753,7 @@ Object* Heap::ReinitializeJSGlobalObject(JSFunction* constructor,
|
||||
ASSERT(map->instance_size() == object->map()->instance_size());
|
||||
|
||||
// Allocate the backing storage for the properties.
|
||||
Object* properties = AllocatePropertyStorageForMap(map);
|
||||
Object* properties = AllocateFixedArray(map->unused_property_fields());
|
||||
if (properties->IsFailure()) return properties;
|
||||
|
||||
// Reset the map for the object.
|
||||
|
@ -112,6 +112,7 @@ namespace v8 { namespace internal {
|
||||
V(Object, false_value) \
|
||||
V(String, empty_string) \
|
||||
V(FixedArray, empty_fixed_array) \
|
||||
V(DescriptorArray, empty_descriptor_array) \
|
||||
V(Object, the_hole_value) \
|
||||
V(Map, neander_map) \
|
||||
V(JSObject, message_listeners) \
|
||||
@ -811,10 +812,6 @@ class Heap : public AllStatic {
|
||||
// inlined).
|
||||
static inline Object* AllocateRawMap(int size_in_bytes);
|
||||
|
||||
// Allocate storage for JSObject properties.
|
||||
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
||||
// failed.
|
||||
static inline Object* AllocatePropertyStorageForMap(Map* map);
|
||||
|
||||
// Initializes a JSObject based on its map.
|
||||
static void InitializeJSObjectFromMap(JSObject* obj,
|
||||
|
@ -133,6 +133,7 @@ void HeapObject::HeapObjectPrint() {
|
||||
JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint();
|
||||
break;
|
||||
case JS_VALUE_TYPE:
|
||||
PrintF("Value wrapper around:");
|
||||
JSValue::cast(this)->value()->Print();
|
||||
break;
|
||||
case CODE_TYPE:
|
||||
|
@ -979,6 +979,13 @@ void FixedArray::set_the_hole(int index) {
|
||||
}
|
||||
|
||||
|
||||
bool DescriptorArray::IsEmpty() {
|
||||
ASSERT(this == Heap::empty_descriptor_array() ||
|
||||
this->length() > 2);
|
||||
return this == Heap::empty_descriptor_array();
|
||||
}
|
||||
|
||||
|
||||
void DescriptorArray::fast_swap(FixedArray* array, int first, int second) {
|
||||
Object* tmp = array->get(first);
|
||||
fast_set(array, first, array->get(second));
|
||||
|
126
src/objects.cc
126
src/objects.cc
@ -1030,8 +1030,7 @@ Object* JSObject::AddFastProperty(String* name,
|
||||
} else {
|
||||
ASSERT(map()->unused_property_fields() == 0);
|
||||
|
||||
static const int kFastNofProperties = 8;
|
||||
if (properties()->length() > kFastNofProperties) {
|
||||
if (properties()->length() > kMaxFastProperties) {
|
||||
Object* obj = NormalizeProperties();
|
||||
if (obj->IsFailure()) return obj;
|
||||
return AddSlowProperty(name, value, attributes);
|
||||
@ -1553,6 +1552,8 @@ Object* JSObject::SetProperty(LookupResult* result,
|
||||
// if the value is a function.
|
||||
// AddProperty has been extended to do this, in this case.
|
||||
return AddFastProperty(name, value, attributes);
|
||||
case NULL_DESCRIPTOR:
|
||||
UNREACHABLE();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
@ -1612,6 +1613,8 @@ Object* JSObject::IgnoreAttributesAndSetLocalProperty(String* name,
|
||||
case INTERCEPTOR:
|
||||
return SetPropertyWithInterceptor(name, value, NONE);
|
||||
case CONSTANT_TRANSITION:
|
||||
case NULL_DESCRIPTOR:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1727,7 +1730,12 @@ PropertyAttributes JSObject::GetPropertyAttribute(JSObject* receiver,
|
||||
case INTERCEPTOR:
|
||||
return result->holder()->
|
||||
GetPropertyAttributeWithInterceptor(receiver, name, continue_search);
|
||||
case MAP_TRANSITION:
|
||||
case CONSTANT_TRANSITION:
|
||||
case NULL_DESCRIPTOR:
|
||||
return ABSENT;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1790,8 +1798,14 @@ Object* JSObject::NormalizeProperties() {
|
||||
dictionary = Dictionary::cast(result);
|
||||
break;
|
||||
}
|
||||
case MAP_TRANSITION:
|
||||
case CONSTANT_TRANSITION:
|
||||
case NULL_DESCRIPTOR:
|
||||
case INTERCEPTOR:
|
||||
break;
|
||||
default:
|
||||
ASSERT(details.IsTransition());
|
||||
case NORMAL:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1800,17 +1814,15 @@ Object* JSObject::NormalizeProperties() {
|
||||
int index = map()->instance_descriptors()->NextEnumerationIndex();
|
||||
dictionary->SetNextEnumerationIndex(index);
|
||||
|
||||
// Descriptors with type MAP_TRANSITION is ignored.
|
||||
|
||||
// Allocate new map.
|
||||
obj = map()->Copy();
|
||||
if (obj->IsFailure()) return obj;
|
||||
|
||||
// We have now sucessfully allocated all the necessary objects.
|
||||
// Changes can now be made with the guarantee that all of them take effect.
|
||||
set_map(Map::cast(obj));
|
||||
map()->
|
||||
set_instance_descriptors(DescriptorArray::cast(Heap::empty_fixed_array()));
|
||||
map()->set_instance_descriptors(Heap::empty_descriptor_array());
|
||||
|
||||
// We have now allocate all the necessary object and change can be applied.
|
||||
map()->set_unused_property_fields(0);
|
||||
set_properties(dictionary);
|
||||
|
||||
@ -2569,20 +2581,33 @@ void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
bool FixedArray::IsEqualTo(FixedArray* other) {
|
||||
if (length() != other->length()) return false;
|
||||
for (int i = 0 ; i < length(); ++i) {
|
||||
if (get(i) != other->get(i)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Object* DescriptorArray::Allocate(int number_of_descriptors) {
|
||||
// Allocate the descriptor array.
|
||||
if (number_of_descriptors == 0) {
|
||||
return Heap::empty_descriptor_array();
|
||||
}
|
||||
// Allocate the array of keys.
|
||||
Object* array = Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors));
|
||||
if (array->IsFailure()) return array;
|
||||
DescriptorArray* result = DescriptorArray::cast(array);
|
||||
// Do not use DescriptorArray::cast on incomplete object.
|
||||
FixedArray* result = FixedArray::cast(array);
|
||||
|
||||
// Allocate the content array and set it in the descriptor array.
|
||||
array = Heap::AllocateFixedArray(number_of_descriptors << 1);
|
||||
if (array->IsFailure()) return array;
|
||||
result->set(kContentArrayIndex, array);
|
||||
|
||||
// Initialize the next enumeration index.
|
||||
result->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
|
||||
|
||||
result->set(kEnumerationIndexIndex,
|
||||
Smi::FromInt(PropertyDetails::kInitialIndex));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -2594,7 +2619,7 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
|
||||
FixedArray::cast(get(kEnumerationIndexIndex))->
|
||||
set(kEnumCacheBridgeCacheIndex, new_cache);
|
||||
} else {
|
||||
if (length() == 0) return; // Do nothing for empty descriptor array.
|
||||
if (IsEmpty()) return; // Do nothing for empty descriptor array.
|
||||
FixedArray::cast(bridge_storage)->
|
||||
set(kEnumCacheBridgeCacheIndex, new_cache);
|
||||
fast_set(FixedArray::cast(bridge_storage),
|
||||
@ -2706,7 +2731,6 @@ Object* DescriptorArray::CopyRemove(String* name) {
|
||||
// Set the enumeration index in the descriptors and set the enumeration index
|
||||
// in the result.
|
||||
new_descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
|
||||
|
||||
// Write the old content and the descriptor information
|
||||
DescriptorWriter w(new_descriptors);
|
||||
DescriptorReader r(this);
|
||||
@ -2801,6 +2825,19 @@ int DescriptorArray::BinarySearch(String* name, int low, int high) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
|
||||
if (IsEmpty()) return other->IsEmpty();
|
||||
if (other->IsEmpty()) return false;
|
||||
if (length() != other->length()) return false;
|
||||
for (int i = 0; i < length(); ++i) {
|
||||
if (get(i) != other->get(i) && i != kContentArrayIndex) return false;
|
||||
}
|
||||
return GetContentArray()->IsEqualTo(other->GetContentArray());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static StaticResource<StringInputBuffer> string_input_buffer;
|
||||
|
||||
|
||||
@ -3775,7 +3812,8 @@ Object* JSFunction::SetPrototype(Object* value) {
|
||||
|
||||
map()->set_constructor(value);
|
||||
map()->set_non_instance_prototype(true);
|
||||
construct_prototype = *Top::initial_object_prototype();
|
||||
construct_prototype =
|
||||
Top::context()->global_context()->initial_object_prototype();
|
||||
} else {
|
||||
map()->set_non_instance_prototype(false);
|
||||
}
|
||||
@ -4210,8 +4248,8 @@ Object* JSObject::SetElementsLength(Object* len) {
|
||||
}
|
||||
int min = NewElementsCapacity(old_capacity);
|
||||
int new_capacity = value > min ? value : min;
|
||||
if (KeepInFastCase(new_capacity) ||
|
||||
new_capacity <= kMaxFastElementsLength) {
|
||||
if (new_capacity <= kMaxFastElementsLength ||
|
||||
!ShouldConvertToSlowElements(new_capacity)) {
|
||||
Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
|
||||
if (obj->IsFailure()) return obj;
|
||||
if (IsJSArray()) JSArray::cast(this)->set_length(smi_length);
|
||||
@ -4463,8 +4501,8 @@ Object* JSObject::SetFastElement(uint32_t index, Object* value) {
|
||||
if ((index - elms_length) < kMaxGap) {
|
||||
// Try allocating extra space.
|
||||
int new_capacity = NewElementsCapacity(index+1);
|
||||
if (KeepInFastCase(new_capacity) ||
|
||||
new_capacity <= kMaxFastElementsLength) {
|
||||
if (new_capacity <= kMaxFastElementsLength ||
|
||||
!ShouldConvertToSlowElements(new_capacity)) {
|
||||
ASSERT(static_cast<uint32_t>(new_capacity) > index);
|
||||
Object* obj = Heap::AllocateFixedArrayWithHoles(new_capacity);
|
||||
if (obj->IsFailure()) return obj;
|
||||
@ -4519,7 +4557,7 @@ Object* JSObject::SetElement(uint32_t index, Object* value) {
|
||||
}
|
||||
|
||||
// Attempt to put this object back in fast case.
|
||||
if (ShouldHaveFastElements()) {
|
||||
if (ShouldConvertToFastElements()) {
|
||||
uint32_t new_length = 0;
|
||||
if (IsJSArray()) {
|
||||
CHECK(Array::IndexFromObject(JSArray::cast(this)->length(), &new_length));
|
||||
@ -4671,17 +4709,17 @@ bool JSObject::HasDenseElements() {
|
||||
}
|
||||
|
||||
|
||||
bool JSObject::KeepInFastCase(int new_capacity) {
|
||||
bool JSObject::ShouldConvertToSlowElements(int new_capacity) {
|
||||
ASSERT(HasFastElements());
|
||||
// Keep the array in fast case if the current backing storage is
|
||||
// almost filled and if the new capacity is no more than twice the
|
||||
// old capacity.
|
||||
int elements_length = FixedArray::cast(elements())->length();
|
||||
return HasDenseElements() && ((new_capacity / 2) <= elements_length);
|
||||
return !HasDenseElements() || ((new_capacity / 2) > elements_length);
|
||||
}
|
||||
|
||||
|
||||
bool JSObject::ShouldHaveFastElements() {
|
||||
bool JSObject::ShouldConvertToFastElements() {
|
||||
ASSERT(!HasFastElements());
|
||||
Dictionary* dictionary = Dictionary::cast(elements());
|
||||
// If the elements are sparse, we should not go back to fast case.
|
||||
@ -4864,8 +4902,15 @@ bool JSObject::HasRealNamedProperty(String* key) {
|
||||
case NORMAL: // fall through.
|
||||
case FIELD: // fall through.
|
||||
case CALLBACKS: // fall through.
|
||||
case CONSTANT_FUNCTION: return true;
|
||||
default: return false;
|
||||
case CONSTANT_FUNCTION:
|
||||
return true;
|
||||
case INTERCEPTOR:
|
||||
case MAP_TRANSITION:
|
||||
case CONSTANT_TRANSITION:
|
||||
case NULL_DESCRIPTOR:
|
||||
return false;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@ -5099,8 +5144,9 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
|
||||
}
|
||||
ASSERT(!storage || storage->length() >= counter);
|
||||
} else {
|
||||
if (storage)
|
||||
if (storage) {
|
||||
element_dictionary()->CopyKeysTo(storage, filter);
|
||||
}
|
||||
counter = element_dictionary()->NumberOfElementsFilterAttributes(filter);
|
||||
}
|
||||
|
||||
@ -5506,7 +5552,7 @@ Object* Dictionary::GenerateNewEnumerationIndices() {
|
||||
|
||||
|
||||
Object* Dictionary::EnsureCapacity(int n, Key* key) {
|
||||
// Check whether there is enough enumeration indices for adding n elements.
|
||||
// Check whether there are enough enumeration indices to add n elements.
|
||||
if (key->IsStringKey() &&
|
||||
!PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) {
|
||||
// If not, we generate new indices for the properties.
|
||||
@ -5793,9 +5839,10 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
|
||||
}
|
||||
|
||||
// Allocate the instance descriptor.
|
||||
Object* instance_descriptors =
|
||||
Object* descriptors_unchecked =
|
||||
DescriptorArray::Allocate(instance_descriptor_length);
|
||||
if (instance_descriptors->IsFailure()) return instance_descriptors;
|
||||
if (descriptors_unchecked->IsFailure()) return descriptors_unchecked;
|
||||
DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked);
|
||||
|
||||
int number_of_allocated_fields = number_of_fields + unused_property_fields;
|
||||
|
||||
@ -5804,7 +5851,7 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
|
||||
if (fields->IsFailure()) return fields;
|
||||
|
||||
// Fill in the instance descriptor and the fields.
|
||||
DescriptorWriter w(DescriptorArray::cast(instance_descriptors));
|
||||
DescriptorWriter w(descriptors);
|
||||
int current_offset = 0;
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object* k = KeyAt(i);
|
||||
@ -5841,25 +5888,20 @@ Object* Dictionary::TransformPropertiesToFastFor(JSObject* obj,
|
||||
}
|
||||
ASSERT(current_offset == number_of_fields);
|
||||
|
||||
// Sort the instance descriptors.
|
||||
DescriptorArray::cast(instance_descriptors)->Sort();
|
||||
|
||||
descriptors->Sort();
|
||||
// Allocate new map.
|
||||
Object* new_map = obj->map()->Copy();
|
||||
if (new_map->IsFailure()) return new_map;
|
||||
|
||||
// Transform the object.
|
||||
Map::cast(new_map)->
|
||||
set_instance_descriptors(DescriptorArray::cast(instance_descriptors));
|
||||
Map::cast(new_map)->set_unused_property_fields(unused_property_fields);
|
||||
obj->set_map(Map::cast(new_map));
|
||||
obj->map()->set_instance_descriptors(descriptors);
|
||||
obj->map()->set_unused_property_fields(unused_property_fields);
|
||||
|
||||
obj->set_properties(FixedArray::cast(fields));
|
||||
ASSERT(obj->IsJSObject());
|
||||
|
||||
// Transfer next enumeration index from dictionary to instance descriptors.
|
||||
DescriptorArray::cast(instance_descriptors)->
|
||||
SetNextEnumerationIndex(NextEnumerationIndex());
|
||||
|
||||
descriptors->SetNextEnumerationIndex(NextEnumerationIndex());
|
||||
// Check it really works.
|
||||
ASSERT(obj->HasFastProperties());
|
||||
return obj;
|
||||
|
@ -52,6 +52,7 @@
|
||||
// - Array
|
||||
// - ByteArray
|
||||
// - FixedArray
|
||||
// - DescriptorArray
|
||||
// - HashTable
|
||||
// - Dictionary
|
||||
// - SymbolTable
|
||||
@ -135,8 +136,7 @@ class PropertyDetails BASE_EMBEDDED {
|
||||
bool IsTransition() {
|
||||
PropertyType t = type();
|
||||
ASSERT(t != INTERCEPTOR);
|
||||
if (t == MAP_TRANSITION || t == CONSTANT_TRANSITION) return true;
|
||||
return false;
|
||||
return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
|
||||
}
|
||||
|
||||
PropertyAttributes attributes() { return AttributesField::decode(value_); }
|
||||
@ -1095,23 +1095,20 @@ class HeapNumber: public HeapObject {
|
||||
class JSObject: public HeapObject {
|
||||
public:
|
||||
// [properties]: Backing storage for properties.
|
||||
DECL_ACCESSORS(properties, FixedArray)
|
||||
// properties is a FixedArray in the fast case, and a Dictionary in the
|
||||
// slow case.
|
||||
DECL_ACCESSORS(properties, FixedArray) // Get and set fast properties.
|
||||
inline void initialize_properties();
|
||||
|
||||
// [elements]: The elements in the fast case.
|
||||
DECL_ACCESSORS(elements, HeapObject)
|
||||
inline void initialize_elements();
|
||||
|
||||
// Accessors for properties.
|
||||
inline bool HasFastProperties();
|
||||
inline Dictionary* property_dictionary(); // Gets slow properties.
|
||||
|
||||
// Do we want to keep the elements in fast case when increasing the
|
||||
// capacity?
|
||||
bool KeepInFastCase(int new_capacity);
|
||||
|
||||
// Accessors for slow properties
|
||||
inline Dictionary* property_dictionary(); // asserts !HasFastProperties
|
||||
inline Dictionary* element_dictionary(); // asserts !HasFastElements
|
||||
// [elements]: The elements (properties with names that are integers).
|
||||
// elements is a FixedArray in the fast case, and a Dictionary in the slow
|
||||
// case.
|
||||
DECL_ACCESSORS(elements, HeapObject) // Get and set fast elements.
|
||||
inline void initialize_elements();
|
||||
inline bool HasFastElements();
|
||||
inline Dictionary* element_dictionary(); // Gets slow elements.
|
||||
|
||||
Object* SetProperty(String* key,
|
||||
Object* value,
|
||||
@ -1188,14 +1185,14 @@ class JSObject: public HeapObject {
|
||||
// Tests for the fast common case for property enumeration.
|
||||
bool IsSimpleEnum();
|
||||
|
||||
// Tells whether the backing storage for elements is fast (FixedArray).
|
||||
inline bool HasFastElements();
|
||||
|
||||
// Do we want to keep the elements in fast case when increasing the
|
||||
// capacity?
|
||||
bool ShouldConvertToSlowElements(int new_capacity);
|
||||
// Returns true if the backing storage for the slow-case elements of
|
||||
// this object takes up nearly as much space as a fast-case backing
|
||||
// storage would. In that case the JSObject should have fast
|
||||
// elements.
|
||||
bool ShouldHaveFastElements();
|
||||
bool ShouldConvertToFastElements();
|
||||
|
||||
// Return the object's prototype (might be Heap::null_value()).
|
||||
inline Object* GetPrototype();
|
||||
@ -1370,6 +1367,7 @@ class JSObject: public HeapObject {
|
||||
|
||||
static const uint32_t kMaxGap = 1024;
|
||||
static const int kMaxFastElementsLength = 5000;
|
||||
static const int kMaxFastProperties = 8;
|
||||
|
||||
// Layout description.
|
||||
static const int kPropertiesOffset = HeapObject::kSize;
|
||||
@ -1477,6 +1475,8 @@ class FixedArray: public Array {
|
||||
#ifdef DEBUG
|
||||
void FixedArrayPrint();
|
||||
void FixedArrayVerify();
|
||||
// Checks if two FixedArrays have identical contents.
|
||||
bool IsEqualTo(FixedArray* other);
|
||||
#endif
|
||||
|
||||
// Swap two elements.
|
||||
@ -1505,14 +1505,15 @@ class FixedArray: public Array {
|
||||
//
|
||||
class DescriptorArray: public FixedArray {
|
||||
public:
|
||||
// Is this the singleton empty_descriptor_array?
|
||||
inline bool IsEmpty();
|
||||
// Returns the number of descriptors in the array.
|
||||
int number_of_descriptors() {
|
||||
int len = length();
|
||||
return len == 0 ? 0 : len - kFirstIndex;
|
||||
return IsEmpty() ? 0 : length() - kFirstIndex;
|
||||
}
|
||||
|
||||
int NextEnumerationIndex() {
|
||||
if (length() == 0) return PropertyDetails::kInitialIndex;
|
||||
if (IsEmpty()) return PropertyDetails::kInitialIndex;
|
||||
Object* obj = get(kEnumerationIndexIndex);
|
||||
if (obj->IsSmi()) {
|
||||
return Smi::cast(obj)->value();
|
||||
@ -1524,11 +1525,12 @@ class DescriptorArray: public FixedArray {
|
||||
|
||||
// Set next enumeration index and flush any enum cache.
|
||||
void SetNextEnumerationIndex(int value) {
|
||||
fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value));
|
||||
if (!IsEmpty()) {
|
||||
fast_set(this, kEnumerationIndexIndex, Smi::FromInt(value));
|
||||
}
|
||||
}
|
||||
|
||||
bool HasEnumCache() {
|
||||
return length() > 0 && !get(kEnumerationIndexIndex)->IsSmi();
|
||||
return !IsEmpty() && !get(kEnumerationIndexIndex)->IsSmi();
|
||||
}
|
||||
|
||||
Object* GetEnumCache() {
|
||||
@ -1579,6 +1581,9 @@ class DescriptorArray: public FixedArray {
|
||||
// with low=0 and high=2.
|
||||
int BinarySearch(String* name, int low, int high);
|
||||
|
||||
|
||||
// Allocates a DescriptorArray, but returns the singleton
|
||||
// empty descriptor array object if number_of_descriptors is 0.
|
||||
static Object* Allocate(int number_of_descriptors);
|
||||
|
||||
// Casting.
|
||||
@ -1612,6 +1617,9 @@ class DescriptorArray: public FixedArray {
|
||||
|
||||
// Is the descriptor array sorted and without duplicates?
|
||||
bool IsSortedNoDuplicates();
|
||||
|
||||
// Are two DescriptorArrays equal?
|
||||
bool IsEqualTo(DescriptorArray* other);
|
||||
#endif
|
||||
|
||||
// The maximum number of descriptors we want in a descriptor array (should
|
||||
|
@ -2726,9 +2726,8 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
||||
int literal_index = temp_scope_->NextMaterializedLiteralIndex();
|
||||
if (is_pre_parsing_) return NULL;
|
||||
|
||||
Handle<FixedArray> constant_properties = (number_of_constant_properties == 0)
|
||||
? Factory::empty_fixed_array()
|
||||
: Factory::NewFixedArray(number_of_constant_properties*2, TENURED);
|
||||
Handle<FixedArray> constant_properties =
|
||||
Factory::NewFixedArray(number_of_constant_properties * 2, TENURED);
|
||||
int position = 0;
|
||||
for (int i = 0; i < properties.length(); i++) {
|
||||
ObjectLiteral::Property* property = properties.at(i);
|
||||
|
@ -87,6 +87,9 @@ void LookupResult::Print() {
|
||||
case CONSTANT_TRANSITION:
|
||||
PrintF(" -type = constant property transition\n");
|
||||
break;
|
||||
case NULL_DESCRIPTOR:
|
||||
PrintF(" =type = null descriptor\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,8 +348,11 @@ class DescriptorReader: public DescriptorStream {
|
||||
bool IsTransition() {
|
||||
PropertyType t = type();
|
||||
ASSERT(t != INTERCEPTOR);
|
||||
if (t == MAP_TRANSITION || t == CONSTANT_TRANSITION) return true;
|
||||
return false;
|
||||
return t == MAP_TRANSITION || t == CONSTANT_TRANSITION;
|
||||
}
|
||||
|
||||
bool IsNullDescriptor() {
|
||||
return type() == NULL_DESCRIPTOR;
|
||||
}
|
||||
|
||||
JSFunction* GetConstantFunction() { return JSFunction::cast(GetValue()); }
|
||||
|
@ -247,8 +247,7 @@ static Object* Runtime_CreateApiFunction(Arguments args) {
|
||||
static Object* Runtime_IsTemplate(Arguments args) {
|
||||
ASSERT(args.length() == 1);
|
||||
Object* arg = args[0];
|
||||
bool result = arg->IsObjectTemplateInfo()
|
||||
|| arg->IsFunctionTemplateInfo();
|
||||
bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
|
||||
return Heap::ToBoolean(result);
|
||||
}
|
||||
|
||||
@ -794,11 +793,12 @@ static Object* Runtime_FunctionSetLength(Arguments args) {
|
||||
|
||||
|
||||
static Object* Runtime_FunctionSetPrototype(Arguments args) {
|
||||
HandleScope scope;
|
||||
NoHandleAllocation ha;
|
||||
ASSERT(args.length() == 2);
|
||||
|
||||
CONVERT_CHECKED(JSFunction, fun, args[0]);
|
||||
Accessors::FunctionSetPrototype(fun, args[1], NULL);
|
||||
Object* obj = Accessors::FunctionSetPrototype(fun, args[1], NULL);
|
||||
if (obj->IsFailure()) return obj;
|
||||
return args[0]; // return TOS
|
||||
}
|
||||
|
||||
@ -858,14 +858,12 @@ static Object* Runtime_SetCode(Arguments args) {
|
||||
|
||||
static Object* CharCodeAt(String* subject, Object* index) {
|
||||
uint32_t i = 0;
|
||||
if (!Array::IndexFromObject(index, &i))
|
||||
return Heap::nan_value();
|
||||
if (!Array::IndexFromObject(index, &i)) return Heap::nan_value();
|
||||
// Flatten the string. If someone wants to get a char at an index
|
||||
// in a cons string, it is likely that more indices will be
|
||||
// accessed.
|
||||
subject->TryFlatten();
|
||||
if (i >= static_cast<uint32_t>(subject->length()))
|
||||
return Heap::nan_value();
|
||||
if (i >= static_cast<uint32_t>(subject->length())) return Heap::nan_value();
|
||||
return Smi::FromInt(subject->Get(i));
|
||||
}
|
||||
|
||||
@ -1315,12 +1313,13 @@ Object* Runtime::SetObjectProperty(Handle<Object> object,
|
||||
return *value;
|
||||
}
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
// Handlify object and value before calling into JavaScript again.
|
||||
Handle<JSObject> object_handle = Handle<JSObject>::cast(object);
|
||||
Handle<Object> value_handle = value;
|
||||
|
||||
// Call-back into JavaScript to convert the key to a string.
|
||||
HandleScope scope;
|
||||
bool has_pending_exception = false;
|
||||
Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
|
||||
if (has_pending_exception) return Failure::Exception();
|
||||
@ -1562,8 +1561,7 @@ static Object* Runtime_Typeof(Arguments args) {
|
||||
HeapObject* heap_obj = HeapObject::cast(obj);
|
||||
|
||||
// typeof an undetectable object is 'undefined'
|
||||
if (heap_obj->map()->is_undetectable())
|
||||
return Heap::undefined_symbol();
|
||||
if (heap_obj->map()->is_undetectable()) return Heap::undefined_symbol();
|
||||
|
||||
InstanceType instance_type = heap_obj->map()->instance_type();
|
||||
if (instance_type < FIRST_NONSTRING_TYPE) {
|
||||
@ -1888,7 +1886,7 @@ static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
|
||||
|
||||
template <class Converter>
|
||||
static Object* ConvertCase(Arguments args,
|
||||
unibrow::Mapping<Converter, 128> *mapping) {
|
||||
unibrow::Mapping<Converter, 128>* mapping) {
|
||||
NoHandleAllocation ha;
|
||||
|
||||
CONVERT_CHECKED(String, s, args[0]);
|
||||
@ -1916,12 +1914,10 @@ static Object* ConvertCase(Arguments args,
|
||||
Object* o = s->IsAscii()
|
||||
? Heap::AllocateRawAsciiString(length)
|
||||
: Heap::AllocateRawTwoByteString(length);
|
||||
if (o->IsFailure())
|
||||
return o;
|
||||
if (o->IsFailure()) return o;
|
||||
String* result = String::cast(o);
|
||||
bool has_changed_character = false;
|
||||
|
||||
|
||||
// Convert all characters to upper case, assuming that they will fit
|
||||
// in the buffer
|
||||
Access<StringInputBuffer> buffer(&string_input_buffer);
|
||||
@ -2047,10 +2043,7 @@ static Object* Runtime_NumberToInteger(Arguments args) {
|
||||
ASSERT(args.length() == 1);
|
||||
|
||||
Object* obj = args[0];
|
||||
|
||||
if (obj->IsSmi())
|
||||
return obj;
|
||||
|
||||
if (obj->IsSmi()) return obj;
|
||||
CONVERT_DOUBLE_CHECKED(number, obj);
|
||||
return Heap::NumberFromDouble(DoubleToInteger(number));
|
||||
}
|
||||
@ -2184,8 +2177,9 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
|
||||
return Top::Throw(Heap::illegal_argument_symbol());
|
||||
}
|
||||
FixedArray* fixed_array = FixedArray::cast(array->elements());
|
||||
if (fixed_array->length() < array_length)
|
||||
if (fixed_array->length() < array_length) {
|
||||
array_length = fixed_array->length();
|
||||
}
|
||||
|
||||
if (array_length == 0) {
|
||||
return Heap::empty_string();
|
||||
@ -2214,8 +2208,9 @@ static Object* Runtime_StringBuilderConcat(Arguments args) {
|
||||
return Failure::OutOfMemoryException();
|
||||
}
|
||||
position += element_length;
|
||||
if (ascii && !element->IsAscii())
|
||||
if (ascii && !element->IsAscii()) {
|
||||
ascii = false;
|
||||
}
|
||||
} else {
|
||||
return Top::Throw(Heap::illegal_argument_symbol());
|
||||
}
|
||||
@ -2408,17 +2403,15 @@ static Object* Runtime_StringCompare(Arguments args) {
|
||||
// A few fast case tests before we flatten.
|
||||
if (x == y) return Smi::FromInt(EQUAL);
|
||||
if (y->length() == 0) {
|
||||
if (x->length() == 0)
|
||||
return Smi::FromInt(EQUAL);
|
||||
if (x->length() == 0) return Smi::FromInt(EQUAL);
|
||||
return Smi::FromInt(GREATER);
|
||||
} else if (x->length() == 0) {
|
||||
return Smi::FromInt(LESS);
|
||||
}
|
||||
{
|
||||
int d = x->Get(0) - y->Get(0);
|
||||
if (d < 0) return Smi::FromInt(LESS);
|
||||
else if (d > 0) return Smi::FromInt(GREATER);
|
||||
}
|
||||
|
||||
int d = x->Get(0) - y->Get(0);
|
||||
if (d < 0) return Smi::FromInt(LESS);
|
||||
else if (d > 0) return Smi::FromInt(GREATER);
|
||||
|
||||
x->TryFlatten();
|
||||
y->TryFlatten();
|
||||
@ -2821,8 +2814,6 @@ static Object* Runtime_LookupContext(Arguments args) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// A mechanism to return pairs of Object*'s. This is somewhat
|
||||
// compiler-dependent as it assumes that a 64-bit value (a long long)
|
||||
// is returned via two registers (edx:eax on ia32). Both the ia32 and
|
||||
@ -2888,7 +2879,7 @@ static ObjPair LoadContextSlotHelper(Arguments args, bool throw_error) {
|
||||
if (throw_error) {
|
||||
// The property doesn't exist - throw exception.
|
||||
Handle<Object> reference_error =
|
||||
Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
|
||||
Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
|
||||
return MakePair(Top::Throw(*reference_error), NULL);
|
||||
} else {
|
||||
// The property doesn't exist - return undefined
|
||||
@ -2913,7 +2904,7 @@ static Object* Runtime_StoreContextSlot(Arguments args) {
|
||||
|
||||
Handle<Object> value(args[0]);
|
||||
CONVERT_ARG_CHECKED(Context, context, 1);
|
||||
Handle<String> name(String::cast(args[2]));
|
||||
CONVERT_ARG_CHECKED(String, name, 2);
|
||||
|
||||
int index;
|
||||
PropertyAttributes attributes;
|
||||
@ -3473,8 +3464,7 @@ static Object* Runtime_GetArrayKeys(Arguments args) {
|
||||
CONVERT_CHECKED(JSArray, raw_array, args[0]);
|
||||
Handle<JSArray> array(raw_array);
|
||||
CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
|
||||
HeapObject* elements = array->elements();
|
||||
if (elements->IsDictionary()) {
|
||||
if (array->elements()->IsDictionary()) {
|
||||
// Create an array and get all the keys into it, then remove all the
|
||||
// keys that are not integers in the range 0 to length-1.
|
||||
Handle<FixedArray> keys = GetKeysInFixedArrayFor(array);
|
||||
@ -3606,14 +3596,15 @@ static Object* DebugLookupResultValue(LookupResult* result) {
|
||||
case CONSTANT_FUNCTION:
|
||||
return result->GetConstantFunction();
|
||||
case CALLBACKS:
|
||||
return Heap::undefined_value();
|
||||
case MAP_TRANSITION:
|
||||
return Heap::undefined_value();
|
||||
case INTERCEPTOR:
|
||||
case MAP_TRANSITION:
|
||||
case CONSTANT_TRANSITION:
|
||||
case NULL_DESCRIPTOR:
|
||||
return Heap::undefined_value();
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
UNREACHABLE();
|
||||
return Heap::undefined_value();
|
||||
}
|
||||
|
||||
@ -3788,8 +3779,7 @@ static Object* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) {
|
||||
CONVERT_ARG_CHECKED(String, name, 1);
|
||||
|
||||
PropertyAttributes attributes;
|
||||
Object* result = obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
|
||||
return result;
|
||||
return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
|
||||
}
|
||||
|
||||
|
||||
@ -3803,8 +3793,7 @@ static Object* Runtime_DebugIndexedInterceptorElementValue(Arguments args) {
|
||||
RUNTIME_ASSERT(obj->HasIndexedInterceptor());
|
||||
CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
|
||||
|
||||
Object* result = obj->GetElementWithInterceptor(*obj, index);
|
||||
return result;
|
||||
return obj->GetElementWithInterceptor(*obj, index);
|
||||
}
|
||||
|
||||
|
||||
@ -3868,8 +3857,8 @@ static Object* Runtime_GetFrameDetails(Arguments args) {
|
||||
ASSERT(args.length() == 2);
|
||||
|
||||
// Check arguments.
|
||||
Object* result = Runtime_CheckExecutionState(args);
|
||||
if (result->IsFailure()) return result;
|
||||
Object* check = Runtime_CheckExecutionState(args);
|
||||
if (check->IsFailure()) return check;
|
||||
CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
|
||||
|
||||
// Find the relevant frame with the requested index.
|
||||
@ -4258,8 +4247,8 @@ static Object* Runtime_PrepareStep(Arguments args) {
|
||||
HandleScope scope;
|
||||
ASSERT(args.length() == 3);
|
||||
// Check arguments.
|
||||
Object* check_result = Runtime_CheckExecutionState(args);
|
||||
if (check_result->IsFailure()) return check_result;
|
||||
Object* check = Runtime_CheckExecutionState(args);
|
||||
if (check->IsFailure()) return check;
|
||||
if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
|
||||
return Top::Throw(Heap::illegal_argument_symbol());
|
||||
}
|
||||
|
@ -212,7 +212,8 @@ $Object.prototype.constructor = $Object;
|
||||
%AddProperty(global, "execScript", function(expr, lang) {
|
||||
// NOTE: We don't care about the character casing.
|
||||
if (!lang || /javascript/i.test(lang)) {
|
||||
%CompileString(ToString(expr), false)();
|
||||
var f = %CompileString(ToString(expr), false);
|
||||
f.call(global);
|
||||
}
|
||||
return null;
|
||||
}, DONT_ENUM);
|
||||
|
@ -25,17 +25,18 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <v8.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include "cctest.h"
|
||||
|
||||
|
||||
CcTest* CcTest::first_ = NULL;
|
||||
CcTest* CcTest::last_ = NULL;
|
||||
|
||||
|
||||
CcTest::CcTest(TestFunction* callback, const char* file, const char* name)
|
||||
: callback_(callback), name_(name), prev_(first_) {
|
||||
: callback_(callback), name_(name), prev_(last_) {
|
||||
// Find the base name of this test (const_cast required on Windows).
|
||||
char *basename = strrchr(const_cast<char *>(file), '/');
|
||||
if (!basename) {
|
||||
@ -51,15 +52,67 @@ CcTest::CcTest(TestFunction* callback, const char* file, const char* name)
|
||||
if (extension) *extension = 0;
|
||||
// Install this test in the list of tests
|
||||
file_ = basename;
|
||||
prev_ = first_;
|
||||
first_ = this;
|
||||
prev_ = last_;
|
||||
last_ = this;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CcTest* current = CcTest::first();
|
||||
while (current != NULL) {
|
||||
printf("%s/%s\n", current->file(), current->name());
|
||||
current = current->prev();
|
||||
static void PrintTestList(CcTest* current) {
|
||||
if (current == NULL) return;
|
||||
PrintTestList(current->prev());
|
||||
printf("%s/%s\n", current->file(), current->name());
|
||||
}
|
||||
|
||||
|
||||
static int RunMatchingTests(CcTest* current, char* file_or_name) {
|
||||
if (current == NULL) return 0;
|
||||
int run_count = 0;
|
||||
if (strcmp(current->file(), file_or_name) == 0
|
||||
|| strcmp(current->name(), file_or_name) == 0) {
|
||||
current->Run();
|
||||
run_count++;
|
||||
}
|
||||
return run_count + RunMatchingTests(current->prev(), file_or_name);
|
||||
}
|
||||
|
||||
|
||||
static int RunMatchingTests(CcTest* current, char* file, char* name) {
|
||||
if (current == NULL) return 0;
|
||||
int run_count = 0;
|
||||
if (strcmp(current->file(), file) == 0
|
||||
&& strcmp(current->name(), name) == 0) {
|
||||
current->Run();
|
||||
run_count++;
|
||||
}
|
||||
return run_count + RunMatchingTests(current->prev(), file, name);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
v8::internal::FlagList::SetFlagsFromCommandLine(&argc, argv, true);
|
||||
int tests_run = 0;
|
||||
bool print_run_count = true;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
char* arg = argv[i];
|
||||
if (strcmp(arg, "--list") == 0) {
|
||||
PrintTestList(CcTest::last());
|
||||
print_run_count = false;
|
||||
} else {
|
||||
char* arg_copy = strdup(arg);
|
||||
char* testname = strchr(arg_copy, '/');
|
||||
if (testname) {
|
||||
// Split the string in two by nulling the slash and then run
|
||||
// exact matches.
|
||||
*testname = 0;
|
||||
tests_run += RunMatchingTests(CcTest::last(), arg_copy, testname + 1);
|
||||
} else {
|
||||
// Run all tests with the specified file or test name.
|
||||
tests_run += RunMatchingTests(CcTest::last(), arg_copy);
|
||||
}
|
||||
free(arg_copy);
|
||||
}
|
||||
}
|
||||
if (print_run_count && tests_run != 1)
|
||||
printf("Ran %i tests.\n", tests_run);
|
||||
return 0;
|
||||
}
|
||||
|
@ -40,17 +40,17 @@ class CcTest {
|
||||
public:
|
||||
typedef void (TestFunction)();
|
||||
CcTest(TestFunction* callback, const char* file, const char* name);
|
||||
void Run() { callback_(); }
|
||||
static int test_count();
|
||||
static CcTest* first() { return first_; }
|
||||
static CcTest* last() { return last_; }
|
||||
CcTest* prev() { return prev_; }
|
||||
const char* file() { return file_; }
|
||||
const char* name() { return name_; }
|
||||
|
||||
private:
|
||||
TestFunction* callback_;
|
||||
const char* file_;
|
||||
const char* name_;
|
||||
static CcTest* first_;
|
||||
static CcTest* last_;
|
||||
CcTest* prev_;
|
||||
};
|
||||
|
||||
|
@ -121,9 +121,9 @@ static inline void CheckNonEqualsHelper(const char* file, int line,
|
||||
|
||||
|
||||
// Helper class for creating a V8 enviromnent for running tests
|
||||
class LocalContext {
|
||||
class DebugLocalContext {
|
||||
public:
|
||||
inline LocalContext(
|
||||
inline DebugLocalContext(
|
||||
v8::ExtensionConfiguration* extensions = 0,
|
||||
v8::Handle<v8::ObjectTemplate> global_template =
|
||||
v8::Handle<v8::ObjectTemplate>(),
|
||||
@ -131,7 +131,7 @@ class LocalContext {
|
||||
: context_(v8::Context::New(extensions, global_template, global_object)) {
|
||||
context_->Enter();
|
||||
}
|
||||
inline ~LocalContext() {
|
||||
inline ~DebugLocalContext() {
|
||||
context_->Exit();
|
||||
context_.Dispose();
|
||||
}
|
||||
@ -159,7 +159,7 @@ class LocalContext {
|
||||
|
||||
|
||||
// Compile and run the supplied source and return the fequested function.
|
||||
static v8::Local<v8::Function> CompileFunction(LocalContext* env,
|
||||
static v8::Local<v8::Function> CompileFunction(DebugLocalContext* env,
|
||||
const char* source,
|
||||
const char* function_name) {
|
||||
v8::Script::Compile(v8::String::New(source))->Run();
|
||||
@ -377,7 +377,7 @@ class TestBreakLocationIterator: public v8::internal::BreakLocationIterator {
|
||||
|
||||
// Compile a function, set a break point and check that the call at the break
|
||||
// location in the code is the expected debug_break function.
|
||||
void CheckDebugBreakFunction(LocalContext* env,
|
||||
void CheckDebugBreakFunction(DebugLocalContext* env,
|
||||
const char* source, const char* name,
|
||||
int position, v8::internal::RelocMode mode,
|
||||
Code* debug_break) {
|
||||
@ -668,7 +668,7 @@ static void MessageCallbackCount(v8::Handle<v8::Message> message,
|
||||
TEST(DebugStub) {
|
||||
using ::v8::internal::Builtins;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// TODO(1240753): Make the test architecture independent or split
|
||||
// parts of the debugger into architecture dependent files. This
|
||||
@ -740,7 +740,7 @@ TEST(DebugStub) {
|
||||
// debugged.
|
||||
TEST(DebugInfo) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
// Create a couple of functions for the test.
|
||||
v8::Local<v8::Function> foo =
|
||||
CompileFunction(&env, "function foo(){}", "foo");
|
||||
@ -777,7 +777,7 @@ TEST(DebugInfo) {
|
||||
TEST(BreakPointICStore) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
v8::Undefined());
|
||||
v8::Script::Compile(v8::String::New("function foo(){bar=0;}"))->Run();
|
||||
@ -808,7 +808,7 @@ TEST(BreakPointICStore) {
|
||||
TEST(BreakPointICLoad) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
v8::Undefined());
|
||||
v8::Script::Compile(v8::String::New("bar=1"))->Run();
|
||||
@ -840,7 +840,7 @@ TEST(BreakPointICLoad) {
|
||||
TEST(BreakPointICCall) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
v8::Undefined());
|
||||
v8::Script::Compile(v8::String::New("function bar(){}"))->Run();
|
||||
@ -872,7 +872,7 @@ TEST(BreakPointICCall) {
|
||||
TEST(BreakPointReturn) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
v8::Undefined());
|
||||
v8::Script::Compile(v8::String::New("function foo(){}"))->Run();
|
||||
@ -914,7 +914,7 @@ static void CallWithBreakPoints(v8::Local<v8::Object> recv,
|
||||
TEST(GCDuringBreakPointProcessing) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointCollectGarbage,
|
||||
v8::Undefined());
|
||||
@ -971,7 +971,7 @@ static void CallAndGC(v8::Local<v8::Object> recv, v8::Local<v8::Function> f) {
|
||||
TEST(BreakPointSurviveGC) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
v8::Undefined());
|
||||
@ -1005,7 +1005,7 @@ TEST(BreakPointSurviveGC) {
|
||||
TEST(BreakPointThroughJavaScript) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
@ -1059,7 +1059,7 @@ TEST(BreakPointThroughJavaScript) {
|
||||
TEST(ScriptBreakPointThroughJavaScript) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
@ -1178,7 +1178,7 @@ TEST(ScriptBreakPointThroughJavaScript) {
|
||||
TEST(EnableDisableScriptBreakPoint) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
@ -1234,7 +1234,7 @@ TEST(EnableDisableScriptBreakPoint) {
|
||||
TEST(ConditionalScriptBreakPoint) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
@ -1295,7 +1295,7 @@ TEST(ConditionalScriptBreakPoint) {
|
||||
TEST(ScriptBreakPointIgnoreCount) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
@ -1349,7 +1349,7 @@ TEST(ScriptBreakPointIgnoreCount) {
|
||||
TEST(ScriptBreakPointReload) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
@ -1407,7 +1407,7 @@ TEST(ScriptBreakPointReload) {
|
||||
TEST(ScriptBreakPointMultiple) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
@ -1472,7 +1472,7 @@ TEST(ScriptBreakPointMultiple) {
|
||||
TEST(ScriptBreakPointLineOffset) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
@ -1526,7 +1526,7 @@ TEST(ScriptBreakPointLineOffset) {
|
||||
// Test script break points set on lines.
|
||||
TEST(ScriptBreakPointLine) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
// Create a function for checking the function when hitting a break point.
|
||||
@ -1632,7 +1632,7 @@ TEST(ScriptBreakPointLine) {
|
||||
// inside the break handling of that break point.
|
||||
TEST(RemoveBreakPointInBreak) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
v8::Local<v8::Function> foo =
|
||||
CompileFunction(&env, "function foo(){a=1;}", "foo");
|
||||
@ -1657,7 +1657,7 @@ TEST(RemoveBreakPointInBreak) {
|
||||
TEST(DebuggerStatement) {
|
||||
break_point_hit_count = 0;
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
v8::Debug::AddDebugEventListener(DebugEventBreakPointHitCount,
|
||||
v8::Undefined());
|
||||
v8::Script::Compile(v8::String::New("function bar(){debugger}"))->Run();
|
||||
@ -1684,7 +1684,7 @@ TEST(DebuggerStatement) {
|
||||
// the correct results.
|
||||
TEST(DebugEvaluate) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
// Create a function for checking the evaluation when hitting a break point.
|
||||
@ -1797,7 +1797,7 @@ TEST(DebugEvaluate) {
|
||||
// Simple test of the stepping mechanism using only store ICs.
|
||||
TEST(DebugStepLinear) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Create a function for testing stepping.
|
||||
v8::Local<v8::Function> foo = CompileFunction(&env,
|
||||
@ -1833,7 +1833,7 @@ TEST(DebugStepLinear) {
|
||||
// Test the stepping mechanism with different ICs.
|
||||
TEST(DebugStepLinearMixedICs) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Create a function for testing stepping.
|
||||
v8::Local<v8::Function> foo = CompileFunction(&env,
|
||||
@ -1877,7 +1877,7 @@ TEST(DebugStepLinearMixedICs) {
|
||||
|
||||
TEST(DebugStepIf) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Register a debug event listener which steps and counts.
|
||||
v8::Debug::AddDebugEventListener(DebugEventStep);
|
||||
@ -1917,7 +1917,7 @@ TEST(DebugStepIf) {
|
||||
|
||||
TEST(DebugStepSwitch) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Register a debug event listener which steps and counts.
|
||||
v8::Debug::AddDebugEventListener(DebugEventStep);
|
||||
@ -1969,7 +1969,7 @@ TEST(DebugStepSwitch) {
|
||||
|
||||
TEST(DebugStepFor) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Register a debug event listener which steps and counts.
|
||||
v8::Debug::AddDebugEventListener(DebugEventStep);
|
||||
@ -2006,7 +2006,7 @@ TEST(DebugStepFor) {
|
||||
|
||||
TEST(StepInOutSimple) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Create a function for checking the function when hitting a break point.
|
||||
frame_function_name = CompileFunction(&env,
|
||||
@ -2051,7 +2051,7 @@ TEST(StepInOutSimple) {
|
||||
|
||||
TEST(StepInOutTree) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Create a function for checking the function when hitting a break point.
|
||||
frame_function_name = CompileFunction(&env,
|
||||
@ -2097,7 +2097,7 @@ TEST(StepInOutTree) {
|
||||
|
||||
TEST(StepInOutBranch) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Create a function for checking the function when hitting a break point.
|
||||
frame_function_name = CompileFunction(&env,
|
||||
@ -2129,7 +2129,7 @@ TEST(StepInOutBranch) {
|
||||
// Test that step in does not step into native functions.
|
||||
TEST(DebugStepNatives) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Create a function for testing stepping.
|
||||
v8::Local<v8::Function> foo = CompileFunction(
|
||||
@ -2170,7 +2170,7 @@ TEST(DebugStepNatives) {
|
||||
// for them.
|
||||
TEST(BreakOnException) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
v8::internal::Top::TraceException(false);
|
||||
@ -2311,7 +2311,7 @@ TEST(BreakOnException) {
|
||||
|
||||
TEST(StepWithException) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Create a function for checking the function when hitting a break point.
|
||||
frame_function_name = CompileFunction(&env,
|
||||
@ -2392,7 +2392,7 @@ TEST(StepWithException) {
|
||||
|
||||
TEST(DebugBreak) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// This test should be run with option --verify-heap. This is an ASSERT and
|
||||
// not a CHECK as --verify-heap is only available in debug mode.
|
||||
@ -2447,7 +2447,7 @@ TEST(DebugBreak) {
|
||||
// through the stack limit flag is set but breaks are disabled.
|
||||
TEST(DisableBreak) {
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
|
||||
// Register a debug event listener which sets the break flag and counts.
|
||||
v8::Debug::AddDebugEventListener(DebugEventCounter);
|
||||
@ -2522,7 +2522,7 @@ static v8::Handle<v8::Value> IndexedGetter(uint32_t index,
|
||||
TEST(InterceptorPropertyMirror) {
|
||||
// Create a V8 environment with debug access.
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
env.ExposeDebug();
|
||||
|
||||
// Create object with named interceptor.
|
||||
@ -2864,7 +2864,7 @@ MessageQueueDebuggerThread message_queue_debugger_thread;
|
||||
TEST(MessageQueues) {
|
||||
// Create a V8 environment
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
message_queue_barriers.Initialize();
|
||||
v8::Debug::SetMessageHandler(MessageHandler);
|
||||
message_queue_debugger_thread.Start();
|
||||
@ -2938,7 +2938,7 @@ void V8Thread::Run() {
|
||||
const char* source_2 = "foo();\n";
|
||||
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
v8::Debug::SetMessageHandler(&ThreadedMessageHandler);
|
||||
|
||||
CompileRun(source_1);
|
||||
@ -3047,7 +3047,7 @@ void BreakpointsV8Thread::Run() {
|
||||
"cat(19);\n";
|
||||
|
||||
v8::HandleScope scope;
|
||||
LocalContext env;
|
||||
DebugLocalContext env;
|
||||
v8::Debug::SetMessageHandler(&BreakpointsMessageHandler);
|
||||
|
||||
CompileRun(source_1);
|
||||
|
@ -124,10 +124,10 @@ TEST(Flags4) {
|
||||
SetFlagsToDefault();
|
||||
int argc = 3;
|
||||
const char* argv[] = { "Test4", "--bool_flag", "--foo" };
|
||||
CHECK_EQ(2, FlagList::SetFlagsFromCommandLine(&argc,
|
||||
CHECK_EQ(0, FlagList::SetFlagsFromCommandLine(&argc,
|
||||
const_cast<char **>(argv),
|
||||
true));
|
||||
CHECK_EQ(3, argc);
|
||||
CHECK_EQ(2, argc);
|
||||
}
|
||||
|
||||
|
||||
|
84
test/cctest/testcfg.py
Normal file
84
test/cctest/testcfg.py
Normal file
@ -0,0 +1,84 @@
|
||||
# Copyright 2008 Google Inc. 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.
|
||||
|
||||
import test
|
||||
import os
|
||||
from os.path import join, dirname
|
||||
import platform
|
||||
|
||||
|
||||
DEBUG_FLAGS = ['--enable-slow-asserts', '--debug-code', '--verify-heap']
|
||||
|
||||
|
||||
class CcTestCase(test.TestCase):
|
||||
|
||||
def __init__(self, path, executable, mode, raw_name, context):
|
||||
super(CcTestCase, self).__init__(context, path)
|
||||
self.executable = executable
|
||||
self.mode = mode
|
||||
self.raw_name = raw_name
|
||||
|
||||
def GetLabel(self):
|
||||
return "%s %s %s" % (self.mode, self.path[-2], self.path[-1])
|
||||
|
||||
def GetName(self):
|
||||
return self.path[-1]
|
||||
|
||||
def GetCommand(self):
|
||||
result = [ self.executable, self.raw_name ]
|
||||
if self.mode == 'debug':
|
||||
result += DEBUG_FLAGS
|
||||
return result
|
||||
|
||||
|
||||
class CcTestConfiguration(test.TestConfiguration):
|
||||
|
||||
def __init__(self, context, root):
|
||||
super(CcTestConfiguration, self).__init__(context, root)
|
||||
|
||||
def GetBuildRequirements(self):
|
||||
return ['cctests']
|
||||
|
||||
def ListTests(self, current_path, path, mode):
|
||||
executable = join('obj', 'test', mode, 'cctest')
|
||||
if (platform.system() == 'Windows'):
|
||||
executable += '.exe'
|
||||
output = test.Execute([executable, '--list'], self.context)
|
||||
if output.exit_code != 0:
|
||||
print output.stdout
|
||||
print output.stderr
|
||||
return []
|
||||
result = []
|
||||
for raw_test in output.stdout.strip().split():
|
||||
full_path = current_path + raw_test.split('/')
|
||||
if self.Contains(path, full_path):
|
||||
result.append(CcTestCase(full_path, executable, mode, raw_test, self.context))
|
||||
return result
|
||||
|
||||
|
||||
def GetConfiguration(context, root):
|
||||
return CcTestConfiguration(context, root)
|
@ -25,7 +25,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --expose-debug-as debug
|
||||
// Flags: --expose-debug-as debug --expose-gc
|
||||
// Get the Debug object exposed from the debug context global object.
|
||||
Debug = debug.Debug
|
||||
|
||||
@ -55,7 +55,7 @@ for (i = 0; i < scripts.length; i++) {
|
||||
|
||||
// This has to be updated if the number of native and extension scripts change.
|
||||
assertEquals(12, native_count);
|
||||
assertEquals(5, extension_count);
|
||||
assertEquals(1, extension_count);
|
||||
assertEquals(2, normal_count); // This script and mjsunit.js.
|
||||
|
||||
// Test a builtins script.
|
||||
@ -80,7 +80,7 @@ assertEquals(Debug.ScriptType.Extension, extension_gc_script.type);
|
||||
|
||||
// Test a normal script.
|
||||
var mjsunit_js_script = Debug.findScript(/mjsunit.js/);
|
||||
assertEquals('mjsunit.js', mjsunit_js_script.name);
|
||||
assertTrue(/mjsunit.js/.test(mjsunit_js_script.name));
|
||||
assertEquals(Debug.ScriptType.Normal, mjsunit_js_script.type);
|
||||
|
||||
// Check a nonexistent script.
|
||||
|
@ -47,5 +47,3 @@ function g() {
|
||||
assertEquals(Debug.scriptSource(f), Debug.scriptSource(g));
|
||||
f();
|
||||
g();
|
||||
|
||||
assertEquals("function print() { [native code] }", print);
|
||||
|
@ -48,7 +48,7 @@ function testObjectMirror(o, cls_name, ctor_name, hasSpecialProperties) {
|
||||
assertTrue(mirror.prototypeObject() instanceof debug.Mirror);
|
||||
assertFalse(mirror.hasNamedInterceptor(), "hasNamedInterceptor()");
|
||||
assertFalse(mirror.hasIndexedInterceptor(), "hasIndexedInterceptor()");
|
||||
|
||||
|
||||
var names = mirror.propertyNames();
|
||||
var properties = mirror.properties()
|
||||
assertEquals(names.length, properties.length);
|
||||
@ -77,10 +77,11 @@ function testObjectMirror(o, cls_name, ctor_name, hasSpecialProperties) {
|
||||
assertEquals('object', fromJSON.type);
|
||||
assertEquals(cls_name, fromJSON.className);
|
||||
assertEquals('function', fromJSON.constructorFunction.type);
|
||||
assertEquals(ctor_name, fromJSON.constructorFunction.name);
|
||||
if (ctor_name !== undefined)
|
||||
assertEquals(ctor_name, fromJSON.constructorFunction.name);
|
||||
assertEquals(void 0, fromJSON.namedInterceptor);
|
||||
assertEquals(void 0, fromJSON.indexedInterceptor);
|
||||
|
||||
|
||||
// For array the index properties are seperate from named properties.
|
||||
if (!cls_name == 'Array') {
|
||||
assertEquals(names.length, fromJSON.properties.length, 'Some properties missing in JSON');
|
||||
@ -134,7 +135,7 @@ testObjectMirror({}, 'Object', 'Object');
|
||||
testObjectMirror({'a':1,'b':2}, 'Object', 'Object');
|
||||
testObjectMirror({'1':void 0,'2':null,'f':function pow(x,y){return Math.pow(x,y);}}, 'Object', 'Object');
|
||||
testObjectMirror(new Point(-1.2,2.003), 'Object', 'Point');
|
||||
testObjectMirror(this, 'global', 'Object', true); // Global object has special properties
|
||||
testObjectMirror(this, 'global', undefined, true); // Global object has special properties
|
||||
testObjectMirror([], 'Array', 'Array');
|
||||
testObjectMirror([1,2], 'Array', 'Array');
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --trace-calls --preallocated-stack-trace-memory 1000000
|
||||
// Flags: --trace-calls --preallocate-message-memory
|
||||
|
||||
/**
|
||||
* @fileoverview Check that various regexp constructs work as intended.
|
||||
|
33
test/mjsunit/regress/regress-1341167.js
Normal file
33
test/mjsunit/regress/regress-1341167.js
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright 2008 Google Inc. 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.
|
||||
|
||||
// Make sure that 'this' is bound to the global object when using
|
||||
// execScript.
|
||||
|
||||
var result;
|
||||
execScript("result = this");
|
||||
assertTrue(result === this);
|
@ -36,21 +36,24 @@ FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
|
||||
|
||||
class MjsunitTestCase(test.TestCase):
|
||||
|
||||
def __init__(self, path, file, config):
|
||||
super(MjsunitTestCase, self).__init__(path)
|
||||
def __init__(self, path, file, mode, context, config):
|
||||
super(MjsunitTestCase, self).__init__(context, path)
|
||||
self.file = file
|
||||
self.config = config
|
||||
self.mode = mode
|
||||
|
||||
def GetLabel(self):
|
||||
return "%s %s" % (self.mode, self.GetName())
|
||||
|
||||
def GetName(self):
|
||||
return self.path[-1]
|
||||
|
||||
|
||||
def GetCommand(self):
|
||||
result = [self.config.context.vm]
|
||||
result = [self.config.context.GetVm(self.mode)]
|
||||
source = open(self.file).read()
|
||||
flags_match = FLAGS_PATTERN.search(source)
|
||||
if flags_match:
|
||||
runtime_flags = flags_match.group(1).strip().split()
|
||||
result += ["--runtime-flags", " ".join(runtime_flags)]
|
||||
result += flags_match.group(1).strip().split()
|
||||
framework = join(dirname(self.config.root), 'mjsunit', 'mjsunit.js')
|
||||
result += [framework, self.file]
|
||||
return result
|
||||
@ -65,29 +68,21 @@ class MjsunitTestConfiguration(test.TestConfiguration):
|
||||
def SelectTest(name):
|
||||
return name.endswith('.js') and name != 'mjsunit.js'
|
||||
return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
|
||||
|
||||
def Contains(self, path, file):
|
||||
if len(path) > len(file):
|
||||
return False
|
||||
for i in xrange(len(path)):
|
||||
if path[i] != file[i]:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def ListTests(self, current_path, path, mode):
|
||||
mjsunit = [[t] for t in self.Ls(self.root)]
|
||||
regress = [['regress', t] for t in self.Ls(join(self.root, 'regress'))]
|
||||
mjsunit = [current_path + [t] for t in self.Ls(self.root)]
|
||||
regress = [current_path + ['regress', t] for t in self.Ls(join(self.root, 'regress'))]
|
||||
all_tests = mjsunit + regress
|
||||
result = []
|
||||
for test in all_tests:
|
||||
if self.Contains(path, test):
|
||||
full_name = current_path + test
|
||||
file_path = join(self.root, reduce(join, test, "") + ".js")
|
||||
result.append(MjsunitTestCase(full_name, file_path, self))
|
||||
file_path = join(self.root, reduce(join, test[1:], "") + ".js")
|
||||
result.append(MjsunitTestCase(full_name, file_path, mode, self.context, self))
|
||||
return result
|
||||
|
||||
def GetBuildRequirements(self):
|
||||
return ['sample=shell']
|
||||
return ['sample', 'sample=shell']
|
||||
|
||||
|
||||
def GetConfiguration(context, root):
|
||||
|
762
test/mozilla/mozilla.status
Normal file
762
test/mozilla/mozilla.status
Normal file
@ -0,0 +1,762 @@
|
||||
# Copyright 2008 Google Inc. 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.
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# If you add a test case to this file, please try to provide
|
||||
# an explanation of why the test fails; this may ease future
|
||||
# debugging.
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
prefix mozilla_js_tests
|
||||
def FAIL_OK = FAIL, OKAY
|
||||
|
||||
|
||||
##################### SKIPPED TESTS #####################
|
||||
|
||||
# This test checks that we behave properly in an out-of-memory
|
||||
# situation. The test fails in V8 with an exception and takes a long
|
||||
# time to do so.
|
||||
js1_5/Regress/regress-271716-n: SKIP
|
||||
|
||||
|
||||
##################### SLOW TESTS #####################
|
||||
|
||||
# This takes a long time to run (~100 seconds). It should only be run
|
||||
# by the really patient.
|
||||
js1_5/GC/regress-324278: SLOW
|
||||
|
||||
# This takes a long time to run because our indexOf operation is
|
||||
# pretty slow - it causes a lot of GCs; see issue
|
||||
# #926379. We could consider marking this SKIP because it takes a
|
||||
# while to run to completion.
|
||||
js1_5/GC/regress-338653: SLOW
|
||||
|
||||
# This test is designed to run until it runs out of memory. This takes
|
||||
# a very long time because it builds strings character by character
|
||||
# and compiles a lot of regular expressions. We could consider marking
|
||||
# this SKIP because it takes a while to run to completion.
|
||||
js1_5/GC/regress-346794: SLOW
|
||||
|
||||
# Runs out of memory while trying to build huge string of 'x'
|
||||
# characters. This takes a long time to run (~32 seconds).
|
||||
js1_5/GC/regress-348532: SLOW
|
||||
|
||||
|
||||
##################### FLAKY TESTS #####################
|
||||
|
||||
# These tests time out in debug mode but pass in product mode
|
||||
js1_5/Regress/regress-280769-3: PASS || ($DEBUG && FAIL)
|
||||
js1_5/Regress/regress-203278-1: PASS || ($DEBUG && FAIL)
|
||||
js1_5/GC/regress-203278-2: PASS || ($DEBUG && FAIL)
|
||||
js1_5/Regress/regress-244470: PASS || ($DEBUG && FAIL)
|
||||
ecma_3/RegExp/regress-209067: PASS || ($DEBUG && FAIL)
|
||||
js1_5/GC/regress-278725: PASS || ($DEBUG && FAIL)
|
||||
js1_5/Regress/regress-360969-03: PASS || ($DEBUG && FAIL)
|
||||
js1_5/Regress/regress-360969-04: PASS || ($DEBUG && FAIL)
|
||||
js1_5/Regress/regress-360969-05: PASS || ($DEBUG && FAIL)
|
||||
js1_5/Regress/regress-360969-06: PASS || ($DEBUG && FAIL)
|
||||
js1_5/extensions/regress-365527: PASS || ($DEBUG && FAIL)
|
||||
# http://b/issue?id=1206983
|
||||
js1_5/Regress/regress-367561-03: PASS || ($DEBUG && FAIL)
|
||||
ecma/Date/15.9.5.10-2: PASS || ($DEBUG && FAIL)
|
||||
|
||||
# These tests create two Date objects just after each other and
|
||||
# expects them to match. Sometimes this happens on the border
|
||||
# between one second and the next.
|
||||
ecma/Date/15.9.2.1: PASS || FAIL
|
||||
ecma/Date/15.9.2.2-1: PASS || FAIL
|
||||
ecma/Date/15.9.2.2-2: PASS || FAIL
|
||||
ecma/Date/15.9.2.2-3: PASS || FAIL
|
||||
ecma/Date/15.9.2.2-4: PASS || FAIL
|
||||
ecma/Date/15.9.2.2-5: PASS || FAIL
|
||||
ecma/Date/15.9.2.2-6: PASS || FAIL
|
||||
|
||||
# 1026139: These date tests fail on arm
|
||||
ecma/Date/15.9.5.29-1: PASS || ($ARM && FAIL)
|
||||
ecma/Date/15.9.5.34-1: PASS || ($ARM && FAIL)
|
||||
ecma/Date/15.9.5.28-1: PASS || ($ARM && FAIL)
|
||||
|
||||
# 1050186: Arm vm is broken; probably unrelated to dates
|
||||
ecma/Array/15.4.4.5-3: PASS || ($ARM && FAIL)
|
||||
ecma/Date/15.9.5.22-2: PASS || ($ARM && FAIL)
|
||||
|
||||
# Severely brain-damaged test. Access to local variables must not
|
||||
# be more than 2.5 times faster than access to global variables? WTF?
|
||||
js1_5/Regress/regress-169559: PASS || FAIL
|
||||
|
||||
|
||||
# Test that rely on specific timezone (not working in Denmark).
|
||||
js1_5/Regress/regress-58116: PASS || FAIL
|
||||
|
||||
|
||||
# Flaky random() test. Tests the distribution of calls to Math.random().
|
||||
js1_5/Regress/regress-211590: PASS || FAIL
|
||||
|
||||
|
||||
# Flaky tests; expect BigO-order computations to yield 1, but the code
|
||||
# cannot handle outliers. See bug #925864.
|
||||
ecma_3/RegExp/regress-311414: PASS || FAIL
|
||||
ecma_3/RegExp/regress-289669: PASS || FAIL
|
||||
js1_5/String/regress-314890: PASS || FAIL
|
||||
js1_5/String/regress-56940-01: PASS || FAIL
|
||||
js1_5/String/regress-56940-02: PASS || FAIL
|
||||
js1_5/String/regress-157334-01: PASS || FAIL
|
||||
js1_5/String/regress-322772: PASS || FAIL
|
||||
js1_5/Array/regress-99120-01: PASS || FAIL
|
||||
js1_5/Array/regress-99120-02: PASS || FAIL
|
||||
js1_5/Regress/regress-347306-01: PASS || FAIL
|
||||
js1_5/Regress/regress-416628: PASS || FAIL
|
||||
|
||||
|
||||
# The following two tests assume that daylight savings time starts first Sunday
|
||||
# in April. This is not true when executing the tests outside California!
|
||||
# In Denmark the adjustment starts one week earlier!.
|
||||
# Tests based on shell that use dates in this gap are flaky.
|
||||
ecma/Date/15.9.5.10-1: PASS || FAIL
|
||||
ecma/Date/15.9.5.12-1: PASS || FAIL
|
||||
ecma/Date/15.9.5.14: PASS || FAIL
|
||||
ecma/Date/15.9.5.34-1: PASS || FAIL
|
||||
|
||||
|
||||
# These tests sometimes pass (in particular on Windows). They build up
|
||||
# a lot of stuff on the stack, which normally causes a stack overflow,
|
||||
# but sometimes it makes it through?
|
||||
js1_5/Regress/regress-290575: PASS || FAIL
|
||||
js1_5/Regress/regress-98901: PASS || FAIL
|
||||
|
||||
|
||||
# Tests that sorting arrays of ints is less than 3 times as fast
|
||||
# as sorting arrays of strings.
|
||||
js1_5/extensions/regress-371636: PASS || FAIL
|
||||
|
||||
|
||||
# Test depends on GC timings. Inherently flaky.
|
||||
js1_5/GC/regress-383269-01: PASS || FAIL
|
||||
|
||||
|
||||
##################### INCOMPATIBLE TESTS #####################
|
||||
|
||||
# This section is for tests that fail in both V8 and KJS. Thus they
|
||||
# have been determined to be incompatible between Mozilla and V8/KJS.
|
||||
|
||||
# Fail because of toLowerCase and toUpperCase conversion.
|
||||
ecma/String/15.5.4.11-2: FAIL_OK
|
||||
ecma/String/15.5.4.11-5: FAIL_OK
|
||||
ecma/String/15.5.4.12-1: FAIL_OK
|
||||
ecma/String/15.5.4.12-4: FAIL_OK
|
||||
|
||||
# This test uses an older version of the unicode standard that fails
|
||||
# us because we correctly convert the armenian small ligature ech-yiwn
|
||||
# to the two upper-case characters ECH and YIWN, whereas the older
|
||||
# unicode version converts it to itself.
|
||||
ecma/String/15.5.4.12-5: FAIL_OK
|
||||
|
||||
# Creates a linked list of arrays until we run out of memory.
|
||||
js1_5/Regress/regress-312588: FAIL_OK
|
||||
|
||||
|
||||
# Runs out of memory because it compiles huge functions.
|
||||
js1_5/Function/regress-338001: FAIL_OK
|
||||
js1_5/Function/regress-338121-01: FAIL_OK
|
||||
js1_5/Function/regress-338121-02: FAIL_OK
|
||||
js1_5/Function/regress-338121-03: FAIL_OK
|
||||
|
||||
|
||||
# Length of objects whose prototype chain includes a function
|
||||
ecma_3/Function/regress-313570: FAIL_OK
|
||||
|
||||
|
||||
#:=== RegExp:===
|
||||
# To be compatible with KJS we silently ignore flags that do not make
|
||||
# sense. This test expects us to throw exceptions.
|
||||
ecma_3/RegExp/regress-57631: FAIL_OK
|
||||
|
||||
# PCRE doesn't allow subpattern nesting deeper than 200, this tests
|
||||
# depth 500. KJS detects the case, and return null from the match,
|
||||
# and passes this test (the test doesn't check for a correct return
|
||||
# value).
|
||||
ecma_3/RegExp/regress-119909: FAIL_OK
|
||||
|
||||
|
||||
# Difference in the way capturing subpatterns work. In JS, when the
|
||||
# 'minimum repeat count' is reached, the empty string must not match.
|
||||
# In this case, we are similar but not identical to KJS. Hard to
|
||||
# support the JS behavior with PCRE, so maybe emulate KJS?
|
||||
#
|
||||
# Note: We do not support toSource currently so we cannot run this
|
||||
# test. We should make an isolated test case for the regexp issue.
|
||||
ecma_3/RegExp/regress-209919: FAIL_OK
|
||||
|
||||
|
||||
# PCRE's match limit is reached. SpiderMonkey hangs on the first one,
|
||||
# KJS returns true somehow. Maybe they up the match limit? There is
|
||||
# an open V8 bug 676063 about this.
|
||||
ecma_3/RegExp/regress-330684: FAIL_OK
|
||||
|
||||
|
||||
# We do not detect overflow in bounds for back references and {}
|
||||
# quantifiers. Might fix by parsing numbers differently?
|
||||
js1_5/Regress/regress-230216-2: FAIL_OK
|
||||
|
||||
|
||||
# According to ECMA-262, \b is a 'word' boundary, where words are only
|
||||
# ASCII characters. PCRE supports non-ASCII word characters.
|
||||
js1_5/Regress/regress-247179: FAIL_OK
|
||||
|
||||
|
||||
# Regexp too long for PCRE.
|
||||
js1_5/Regress/regress-280769: FAIL_OK
|
||||
js1_5/Regress/regress-280769-1: FAIL_OK
|
||||
js1_5/Regress/regress-280769-2: FAIL_OK
|
||||
js1_5/Regress/regress-280769-4: FAIL_OK
|
||||
js1_5/Regress/regress-280769-5: FAIL_OK
|
||||
|
||||
|
||||
# We do not support static RegExp.multiline - should we?.
|
||||
js1_2/regexp/RegExp_multiline: FAIL_OK
|
||||
js1_2/regexp/RegExp_multiline_as_array: FAIL_OK
|
||||
js1_2/regexp/beginLine: FAIL_OK
|
||||
js1_2/regexp/endLine: FAIL_OK
|
||||
|
||||
|
||||
# Date trouble?
|
||||
js1_5/Date/regress-301738-02: FAIL_OK
|
||||
|
||||
|
||||
# This test fails for all browsers on in the CET timezone.
|
||||
ecma/Date/15.9.5.35-1: PASS || FAIL_OK
|
||||
|
||||
|
||||
# Spidermonkey allows stuff in parenthesis directly after the minutes
|
||||
# in a date. KJS does not, so we don't either.
|
||||
js1_5/Date/regress-309925-02: FAIL_OK
|
||||
|
||||
|
||||
# Print string after deleting array element?
|
||||
js1_5/Expressions/regress-96526-delelem: FAIL_OK
|
||||
|
||||
|
||||
# Stack overflows should be InternalError: too much recursion?
|
||||
js1_5/Regress/regress-234389: FAIL_OK
|
||||
|
||||
|
||||
# This may very well be a bogus test. I'm not sure yet.
|
||||
js1_5/Regress/regress-320119: FAIL_OK
|
||||
|
||||
|
||||
# We do not support explicit global evals through <global>.eval(...).
|
||||
js1_5/Regress/regress-68498-003: FAIL_OK
|
||||
|
||||
|
||||
# No support for toSource().
|
||||
js1_5/Regress/regress-248444: FAIL_OK
|
||||
js1_5/Regress/regress-313967-01: FAIL_OK
|
||||
js1_5/Regress/regress-313967-02: FAIL_OK
|
||||
|
||||
# This fails because we don't have stack space for Function.prototype.apply
|
||||
# with very large numbers of arguments. The test uses 2^24 arguments.
|
||||
js1_5/Array/regress-350256-03: FAIL_OK
|
||||
|
||||
|
||||
# Extra arguments not handled properly in String.prototype.match
|
||||
js1_5/Regress/regress-179524: FAIL_OK
|
||||
|
||||
|
||||
# Uncategorized failures. Please help categorize (or fix) these failures.
|
||||
js1_5/Regress/regress-172699: FAIL_OK
|
||||
|
||||
|
||||
# Calls regexp objects with function call syntax; non-ECMA behavior.
|
||||
js1_2/Objects/toString-001: FAIL_OK
|
||||
|
||||
|
||||
# Assumes that the prototype of a function is enumerable. Non-ECMA,
|
||||
# see section 15.3.3.1, page 86.
|
||||
ecma/GlobalObject/15.1.2.2-1: FAIL_OK
|
||||
ecma/GlobalObject/15.1.2.3-1: FAIL_OK
|
||||
ecma/GlobalObject/15.1.2.4: FAIL_OK
|
||||
ecma/GlobalObject/15.1.2.5-1: FAIL_OK
|
||||
ecma/GlobalObject/15.1.2.6: FAIL_OK
|
||||
ecma/GlobalObject/15.1.2.7: FAIL_OK
|
||||
|
||||
|
||||
# Tests that rely on specific details of function decompilation or
|
||||
# print strings for errors. Non-ECMA behavior.
|
||||
js1_2/function/tostring-2: FAIL_OK
|
||||
js1_5/Exceptions/regress-332472: FAIL_OK
|
||||
js1_5/Regress/regress-173067: FAIL_OK
|
||||
js1_5/Regress/regress-355556: FAIL_OK
|
||||
js1_5/Regress/regress-328664: FAIL_OK
|
||||
js1_5/Regress/regress-252892: FAIL_OK
|
||||
js1_5/Regress/regress-352208: FAIL_OK
|
||||
ecma_3/Array/15.4.5.1-01: FAIL_OK
|
||||
ecma_3/Array/regress-387501: FAIL_OK
|
||||
ecma_3/LexicalConventions/7.9.1: FAIL_OK
|
||||
ecma_3/RegExp/regress-375711: FAIL_OK
|
||||
ecma_3/Unicode/regress-352044-01: FAIL_OK
|
||||
ecma_3/extensions/regress-274152: FAIL_OK
|
||||
js1_5/Regress/regress-372364: FAIL_OK
|
||||
js1_5/Regress/regress-420919: FAIL_OK
|
||||
js1_5/Regress/regress-422348: FAIL_OK
|
||||
ecma_3/RegExp/regress-375715-04: FAIL_OK
|
||||
|
||||
|
||||
# Uses Mozilla-specific QName, XML, XMLList and Iterator.
|
||||
js1_5/Regress/regress-407323: FAIL_OK
|
||||
js1_5/Regress/regress-407957: FAIL_OK
|
||||
|
||||
|
||||
# Relies on JavaScript 1.2 / 1.3 deprecated features.
|
||||
js1_2/function/String: FAIL_OK
|
||||
js1_2/operator/equality: FAIL_OK
|
||||
js1_2/version120/boolean-001: FAIL_OK
|
||||
js1_2/String/concat: FAIL_OK
|
||||
js1_2/function/Function_object: FAIL_OK
|
||||
js1_2/function/tostring-1: FAIL_OK
|
||||
js1_2/version120/regress-99663: FAIL_OK
|
||||
js1_2/regexp/RegExp_lastIndex: FAIL_OK
|
||||
js1_2/regexp/string_split: FAIL_OK
|
||||
|
||||
|
||||
# We do not check for bad surrogate pairs when quoting strings.
|
||||
js1_5/Regress/regress-315974: FAIL_OK
|
||||
|
||||
|
||||
# Use unsupported "watch".
|
||||
js1_5/Regress/regress-213482: FAIL_OK
|
||||
js1_5/Regress/regress-240577: FAIL_OK
|
||||
js1_5/Regress/regress-355344: FAIL_OK
|
||||
js1_5/Object/regress-362872-01: FAIL_OK
|
||||
js1_5/Object/regress-362872-02: FAIL_OK
|
||||
js1_5/Regress/regress-361467: FAIL_OK
|
||||
js1_5/Regress/regress-385393-06: FAIL_OK
|
||||
|
||||
|
||||
# Use special Mozilla getter/setter syntax
|
||||
js1_5/Regress/regress-354924: FAIL_OK
|
||||
js1_5/Regress/regress-355341: FAIL_OK
|
||||
js1_5/GC/regress-316885-01: FAIL_OK
|
||||
js1_5/GetSet/getset-002: FAIL_OK
|
||||
js1_5/GetSet/regress-353264: FAIL_OK
|
||||
js1_5/Regress/regress-361617: FAIL_OK
|
||||
js1_5/Regress/regress-362583: FAIL_OK
|
||||
|
||||
|
||||
# 'native' *is* a keyword in V8.
|
||||
js1_5/Regress/regress-240317: FAIL_OK
|
||||
|
||||
|
||||
# Requires Mozilla-specific strict mode or options() function.
|
||||
ecma_3/Object/8.6.1-01: FAIL_OK
|
||||
js1_5/Exceptions/regress-315147: FAIL_OK
|
||||
js1_5/Regress/regress-106244: FAIL_OK
|
||||
js1_5/Regress/regress-317533: FAIL_OK
|
||||
js1_5/Regress/regress-323314-1: FAIL_OK
|
||||
js1_5/Regress/regress-352197: FAIL_OK
|
||||
js1_5/Regress/regress-115436: FAIL_OK
|
||||
js1_5/Regress/regress-214761: FAIL_OK
|
||||
js1_5/Regress/regress-253150: FAIL_OK
|
||||
js1_5/Regress/regress-306727: FAIL_OK
|
||||
js1_5/Regress/regress-308566: FAIL_OK
|
||||
js1_5/Regress/regress-312260: FAIL_OK
|
||||
js1_5/Regress/regress-322430: FAIL_OK
|
||||
js1_5/Regress/regress-383674: FAIL_OK
|
||||
|
||||
|
||||
# Equivalent to assert(false).
|
||||
ecma_2/RegExp/exec-001: FAIL_OK
|
||||
ecma_2/String/replace-001: FAIL_OK
|
||||
|
||||
|
||||
# We do not strip unicode format control characters. This is really
|
||||
# required for working with non-latin character sets. We match KJS
|
||||
# and IE here. Firefox matches the spec (section 7.1).
|
||||
ecma_3/Unicode/uc-001: FAIL_OK
|
||||
|
||||
|
||||
# A non-breaking space doesn't match \s in a regular expression. This behaviour
|
||||
# matches KJS. All the VMs have different behaviours in which characters match
|
||||
# \s so we do the same as KJS until they change.
|
||||
ecma_3/Unicode/uc-002: FAIL_OK
|
||||
|
||||
|
||||
# String.prototype.split on empty strings always returns an array
|
||||
# with one element (as specified in ECMA-262).
|
||||
js1_2/Array/array_split_1: FAIL_OK
|
||||
|
||||
|
||||
# The concat() method is defined in Array.prototype; not Array.
|
||||
js1_5/Array/regress-313153: FAIL_OK
|
||||
|
||||
|
||||
# Properties stack, fileName, and lineNumber of Error instances are
|
||||
# not supported. Mozilla specific extension.
|
||||
js1_5/Exceptions/errstack-001: FAIL_OK
|
||||
js1_5/Exceptions/regress-257751: FAIL_OK
|
||||
js1_5/Regress/regress-119719: FAIL_OK
|
||||
js1_5/Regress/regress-139316: FAIL_OK
|
||||
js1_5/Regress/regress-167328: FAIL_OK
|
||||
js1_5/Regress/regress-243869: FAIL_OK
|
||||
|
||||
|
||||
# Unsupported import/export and <xml> literals. Mozilla extensions.
|
||||
js1_5/Regress/regress-249211: FAIL_OK
|
||||
js1_5/Regress/regress-309242: FAIL_OK
|
||||
js1_5/Regress/regress-350692: FAIL_OK
|
||||
|
||||
|
||||
# The length of Error functions is 1 not 3.
|
||||
js1_5/Exceptions/regress-123002: FAIL_OK
|
||||
|
||||
|
||||
# Reserved keywords as function names, etc is not supported.
|
||||
js1_5/LexicalConventions/regress-343675: FAIL_OK
|
||||
|
||||
|
||||
# Unsupported list comprehensions: [ ... for ... ] and for each.
|
||||
js1_5/Regress/regress-352009: FAIL_OK
|
||||
js1_5/Regress/regress-349648: FAIL_OK
|
||||
|
||||
|
||||
# Expects top level arguments (passed on command line?) to be
|
||||
# the empty string?
|
||||
js1_5/Regress/regress-336100: FAIL_OK
|
||||
|
||||
|
||||
# Regular expression test failures due to PCRE. We match KJS (ie, perl)
|
||||
# behavior and not the ECMA spec.
|
||||
ecma_3/RegExp/15.10.2-1: FAIL_OK
|
||||
ecma_3/RegExp/perlstress-001: FAIL_OK
|
||||
ecma_3/RegExp/regress-334158: FAIL_OK
|
||||
|
||||
|
||||
# This test requires a failure if we try to compile a function with more
|
||||
# than 65536 arguments. This seems to be a Mozilla restriction.
|
||||
js1_5/Regress/regress-290575: FAIL_OK
|
||||
|
||||
|
||||
# Fails because of the way function declarations are
|
||||
# handled in V8/KJS. V8 follows IE behavior and introduce
|
||||
# all nested function declarations when entering the
|
||||
# surrounding function, whereas Spidermonkey declares
|
||||
# them dynamically when the statement is executed.
|
||||
ecma_3/Function/scope-001: FAIL_OK
|
||||
ecma_3/FunExpr/fe-001: FAIL_OK
|
||||
js1_5/Scope/regress-184107: FAIL_OK
|
||||
|
||||
|
||||
# Function is deletable in V8 and KJS.
|
||||
js1_5/Regress/regress-352604: FAIL_OK
|
||||
|
||||
|
||||
# Cannot call strings as functions. Expects not to crash.
|
||||
js1_5/Regress/regress-417893: FAIL_OK
|
||||
|
||||
|
||||
|
||||
##################### FAILING TESTS #####################
|
||||
|
||||
# This section is for tests that fail in V8 and pass in KJS.
|
||||
# Tests that fail in both V8 and KJS belong in the FAIL_OK
|
||||
# category.
|
||||
|
||||
# This fails because we don't handle Function.prototype.apply with very large
|
||||
# numbers of arguments (depending on max stack size). 350256-02 needs more than
|
||||
# 4Mbytes of stack space.
|
||||
js1_5/Array/regress-350256-02: FAIL
|
||||
|
||||
|
||||
# This fails because 'delete arguments[i]' does not disconnect the
|
||||
# argument from the arguments array. See issue #900066.
|
||||
ecma_3/Function/regress-137181: FAIL
|
||||
|
||||
|
||||
# Calls regexp objects with function call syntax; non-ECMA behavior.
|
||||
ecma_2/RegExp/regress-001: FAIL
|
||||
js1_2/regexp/regress-6359: FAIL
|
||||
js1_2/regexp/regress-9141: FAIL
|
||||
js1_5/Regress/regress-224956: FAIL
|
||||
js1_5/Regress/regress-325925: FAIL
|
||||
js1_2/regexp/simple_form: FAIL
|
||||
|
||||
|
||||
# Tests that rely on specific details of function decompilation or
|
||||
# print strings for errors. Non-ECMA behavior.
|
||||
js1_4/Regress/function-003: FAIL
|
||||
|
||||
|
||||
# Relies on JavaScript 1.2 / 1.3 deprecated features.
|
||||
js1_2/function/regexparg-1: FAIL
|
||||
|
||||
|
||||
# 'export' and 'import' are not keywords in V8.
|
||||
ecma_2/Exceptions/lexical-010: FAIL
|
||||
ecma_2/Exceptions/lexical-022: FAIL
|
||||
|
||||
|
||||
# Requires Mozilla-specific strict mode.
|
||||
ecma_2/Exceptions/lexical-011: FAIL
|
||||
ecma_2/Exceptions/lexical-014: FAIL
|
||||
ecma_2/Exceptions/lexical-016: FAIL
|
||||
ecma_2/Exceptions/lexical-021: FAIL
|
||||
ecma_2/LexicalConventions/keywords-001: FAIL
|
||||
js1_5/Regress/regress-306633: FAIL
|
||||
|
||||
|
||||
# This test seems designed to fail (it produces a 700Mbyte string).
|
||||
# We fail on out of memory. The important thing is not to crash.
|
||||
js1_5/Regress/regress-303213: FAIL
|
||||
|
||||
|
||||
# Bug 1193440: Ignore Unicode BOM characters when scanning.
|
||||
ecma_3/extensions/regress-368516: FAIL
|
||||
|
||||
# Bug 1202592:New ecma_3/String/15.5.4.11 is failing.
|
||||
ecma_3/String/15.5.4.11: FAIL
|
||||
|
||||
# Bug 1202597: New js1_5/Expressions/regress-394673 is failing.
|
||||
# Marked as: Will not fix. V8 throws an acceptable RangeError.
|
||||
js1_5/Expressions/regress-394673: FAIL
|
||||
|
||||
# Bug 1202598: New mozilla test js1_5/Regress/regress-383682 fails.
|
||||
js1_5/Regress/regress-383682: FAIL
|
||||
|
||||
|
||||
##################### MOZILLA EXTENSION TESTS #####################
|
||||
|
||||
ecma/extensions/15.1.2.1-1: FAIL_OK
|
||||
ecma_3/extensions/regress-385393-03: FAIL_OK
|
||||
ecma_3/extensions/7.9.1: FAIL_OK
|
||||
js1_5/extensions/catchguard-001: FAIL_OK
|
||||
js1_5/extensions/catchguard-002: FAIL_OK
|
||||
js1_5/extensions/catchguard-003: FAIL_OK
|
||||
js1_5/extensions/getset-001: FAIL_OK
|
||||
js1_5/extensions/getset-003: FAIL_OK
|
||||
js1_5/extensions/no-such-method: FAIL_OK
|
||||
js1_5/extensions/regress-104077: FAIL_OK
|
||||
js1_5/extensions/regress-226078: FAIL_OK
|
||||
js1_5/extensions/regress-303277: FAIL_OK
|
||||
js1_5/extensions/regress-304897: FAIL_OK
|
||||
js1_5/extensions/regress-306738: FAIL_OK
|
||||
js1_5/extensions/regress-311161: FAIL_OK
|
||||
js1_5/extensions/regress-311583: FAIL_OK
|
||||
js1_5/extensions/regress-311792-01: FAIL_OK
|
||||
js1_5/extensions/regress-312278: FAIL_OK
|
||||
js1_5/extensions/regress-313630: FAIL_OK
|
||||
js1_5/extensions/regress-313763: FAIL_OK
|
||||
js1_5/extensions/regress-313803: FAIL_OK
|
||||
js1_5/extensions/regress-314874: FAIL_OK
|
||||
js1_5/extensions/regress-322957: FAIL_OK
|
||||
js1_5/extensions/regress-328556: FAIL_OK
|
||||
js1_5/extensions/regress-330569: FAIL_OK
|
||||
js1_5/extensions/regress-333541: FAIL_OK
|
||||
js1_5/extensions/regress-335700: FAIL_OK
|
||||
js1_5/extensions/regress-336409-1: FAIL_OK
|
||||
js1_5/extensions/regress-336409-2: FAIL_OK
|
||||
js1_5/extensions/regress-336410-1: FAIL_OK
|
||||
js1_5/extensions/regress-336410-2: FAIL_OK
|
||||
js1_5/extensions/regress-341956-01: FAIL_OK
|
||||
js1_5/extensions/regress-341956-02: FAIL_OK
|
||||
js1_5/extensions/regress-341956-03: FAIL_OK
|
||||
js1_5/extensions/regress-342960: FAIL_OK
|
||||
js1_5/extensions/regress-345967: FAIL_OK
|
||||
js1_5/extensions/regress-346494-01: FAIL_OK
|
||||
js1_5/extensions/regress-346494: FAIL_OK
|
||||
js1_5/extensions/regress-347306-02: FAIL_OK
|
||||
js1_5/extensions/regress-348986: FAIL_OK
|
||||
js1_5/extensions/regress-349616: FAIL_OK
|
||||
js1_5/extensions/regress-350312-02: FAIL_OK
|
||||
js1_5/extensions/regress-350312-03: FAIL_OK
|
||||
js1_5/extensions/regress-350531: FAIL_OK
|
||||
js1_5/extensions/regress-351102-01: FAIL_OK
|
||||
js1_5/extensions/regress-351102-02: FAIL_OK
|
||||
js1_5/extensions/regress-351102-06: FAIL_OK
|
||||
js1_5/extensions/regress-351448: FAIL_OK
|
||||
js1_5/extensions/regress-351973: FAIL_OK
|
||||
js1_5/extensions/regress-352060: FAIL_OK
|
||||
js1_5/extensions/regress-352094: FAIL_OK
|
||||
js1_5/extensions/regress-352261: FAIL_OK
|
||||
js1_5/extensions/regress-352281: FAIL_OK
|
||||
js1_5/extensions/regress-352372: FAIL_OK
|
||||
js1_5/extensions/regress-352455: FAIL_OK
|
||||
js1_5/extensions/regress-352604: FAIL_OK
|
||||
js1_5/extensions/regress-353214: FAIL_OK
|
||||
js1_5/extensions/regress-355339: FAIL_OK
|
||||
js1_5/extensions/regress-355497: FAIL_OK
|
||||
js1_5/extensions/regress-355622: FAIL_OK
|
||||
js1_5/extensions/regress-355736: FAIL_OK
|
||||
js1_5/extensions/regress-356085: FAIL_OK
|
||||
js1_5/extensions/regress-356106: FAIL_OK
|
||||
js1_5/extensions/regress-358594-01: FAIL_OK
|
||||
js1_5/extensions/regress-358594-02: FAIL_OK
|
||||
js1_5/extensions/regress-358594-03: FAIL_OK
|
||||
js1_5/extensions/regress-358594-04: FAIL_OK
|
||||
js1_5/extensions/regress-358594-05: FAIL_OK
|
||||
js1_5/extensions/regress-358594-06: FAIL_OK
|
||||
js1_5/extensions/regress-361346: FAIL_OK
|
||||
js1_5/extensions/regress-361360: FAIL_OK
|
||||
js1_5/extensions/regress-361558: FAIL_OK
|
||||
js1_5/extensions/regress-361571: FAIL_OK
|
||||
js1_5/extensions/regress-361856: FAIL_OK
|
||||
js1_5/extensions/regress-361964: FAIL_OK
|
||||
js1_5/extensions/regress-363988: FAIL_OK
|
||||
js1_5/extensions/regress-365869: FAIL_OK
|
||||
js1_5/extensions/regress-367630: FAIL_OK
|
||||
js1_5/extensions/regress-367923: FAIL_OK
|
||||
js1_5/extensions/regress-368859: FAIL_OK
|
||||
js1_5/extensions/regress-374589: FAIL_OK
|
||||
js1_5/extensions/regress-375801: FAIL_OK
|
||||
js1_5/extensions/regress-376052: FAIL_OK
|
||||
js1_5/extensions/regress-379523: FAIL_OK
|
||||
js1_5/extensions/regress-380581: FAIL_OK
|
||||
js1_5/extensions/regress-380831: FAIL_OK
|
||||
js1_5/extensions/regress-381205: FAIL_OK
|
||||
js1_5/extensions/regress-381211: FAIL_OK
|
||||
js1_5/extensions/regress-381304: FAIL_OK
|
||||
js1_5/extensions/regress-382509: FAIL_OK
|
||||
js1_5/extensions/regress-383965: FAIL_OK
|
||||
js1_5/extensions/regress-384680: FAIL_OK
|
||||
js1_5/extensions/regress-385393-09: FAIL_OK
|
||||
js1_5/extensions/regress-407501: FAIL_OK
|
||||
js1_5/extensions/regress-418730: FAIL_OK
|
||||
js1_5/extensions/regress-420612: FAIL_OK
|
||||
js1_5/extensions/regress-420869-01: FAIL_OK
|
||||
js1_5/extensions/regress-424257: FAIL_OK
|
||||
js1_5/extensions/regress-424683-01: FAIL_OK
|
||||
js1_5/extensions/regress-44009: FAIL_OK
|
||||
js1_5/extensions/regress-50447-1: FAIL_OK
|
||||
js1_5/extensions/regress-50447: FAIL_OK
|
||||
js1_5/extensions/regress-90596-001: FAIL_OK
|
||||
js1_5/extensions/regress-90596-002: FAIL_OK
|
||||
js1_5/extensions/regress-96284-001: FAIL_OK
|
||||
js1_5/extensions/regress-96284-002: FAIL_OK
|
||||
js1_5/extensions/scope-001: FAIL_OK
|
||||
js1_5/extensions/toLocaleFormat-01: FAIL_OK
|
||||
js1_5/extensions/toLocaleFormat-02: FAIL_OK
|
||||
|
||||
|
||||
##################### DECOMPILATION TESTS #####################
|
||||
|
||||
# We don't really about the outcome of running the
|
||||
# decompilation tests as long as they don't crash or
|
||||
# timeout.
|
||||
|
||||
js1_5/decompilation/regress-344120: PASS || FAIL
|
||||
js1_5/decompilation/regress-346892: PASS || FAIL
|
||||
js1_5/decompilation/regress-346902: PASS || FAIL
|
||||
js1_5/decompilation/regress-346904: PASS || FAIL
|
||||
js1_5/decompilation/regress-346915: PASS || FAIL
|
||||
js1_5/decompilation/regress-349484: PASS || FAIL
|
||||
js1_5/decompilation/regress-349489: PASS || FAIL
|
||||
js1_5/decompilation/regress-349491: PASS || FAIL
|
||||
js1_5/decompilation/regress-349596: PASS || FAIL
|
||||
js1_5/decompilation/regress-349650: PASS || FAIL
|
||||
js1_5/decompilation/regress-349663: PASS || FAIL
|
||||
js1_5/decompilation/regress-350242: PASS || FAIL
|
||||
js1_5/decompilation/regress-350263: PASS || FAIL
|
||||
js1_5/decompilation/regress-350271: PASS || FAIL
|
||||
js1_5/decompilation/regress-350666: PASS || FAIL
|
||||
js1_5/decompilation/regress-350670: PASS || FAIL
|
||||
js1_5/decompilation/regress-351104: PASS || FAIL
|
||||
js1_5/decompilation/regress-351219: PASS || FAIL
|
||||
js1_5/decompilation/regress-351336: PASS || FAIL
|
||||
js1_5/decompilation/regress-351597: PASS || FAIL
|
||||
js1_5/decompilation/regress-351625: PASS || FAIL
|
||||
js1_5/decompilation/regress-351626: PASS || FAIL
|
||||
js1_5/decompilation/regress-351693: PASS || FAIL
|
||||
js1_5/decompilation/regress-351705: PASS || FAIL
|
||||
js1_5/decompilation/regress-351793: PASS || FAIL
|
||||
js1_5/decompilation/regress-352013: PASS || FAIL
|
||||
js1_5/decompilation/regress-352022: PASS || FAIL
|
||||
js1_5/decompilation/regress-352073: PASS || FAIL
|
||||
js1_5/decompilation/regress-352202: PASS || FAIL
|
||||
js1_5/decompilation/regress-352312: PASS || FAIL
|
||||
js1_5/decompilation/regress-352360: PASS || FAIL
|
||||
js1_5/decompilation/regress-352375: PASS || FAIL
|
||||
js1_5/decompilation/regress-352453: PASS || FAIL
|
||||
js1_5/decompilation/regress-352649: PASS || FAIL
|
||||
js1_5/decompilation/regress-352873-01: PASS || FAIL
|
||||
js1_5/decompilation/regress-352873-02: PASS || FAIL
|
||||
js1_5/decompilation/regress-353000: PASS || FAIL
|
||||
js1_5/decompilation/regress-353120: PASS || FAIL
|
||||
js1_5/decompilation/regress-353146: PASS || FAIL
|
||||
js1_5/decompilation/regress-354878: PASS || FAIL
|
||||
js1_5/decompilation/regress-354910: PASS || FAIL
|
||||
js1_5/decompilation/regress-355992: PASS || FAIL
|
||||
js1_5/decompilation/regress-356083: PASS || FAIL
|
||||
js1_5/decompilation/regress-356248: PASS || FAIL
|
||||
js1_5/decompilation/regress-371692: PASS || FAIL
|
||||
js1_5/decompilation/regress-373678: PASS || FAIL
|
||||
js1_5/decompilation/regress-375639: PASS || FAIL
|
||||
js1_5/decompilation/regress-375882: PASS || FAIL
|
||||
js1_5/decompilation/regress-376564: PASS || FAIL
|
||||
js1_5/decompilation/regress-383721: PASS || FAIL
|
||||
js1_5/decompilation/regress-406555: PASS || FAIL
|
||||
|
||||
|
||||
[ $FAST == yes ]
|
||||
|
||||
# These tests take an unreasonable amount of time so we skip them
|
||||
# in fast mode.
|
||||
|
||||
js1_5/Regress/regress-312588: SKIP
|
||||
js1_5/Regress/regress-271716-n: SKIP
|
||||
|
||||
[ $FAST == yes && $ARCH == arm ]
|
||||
|
||||
# In fast mode on arm we try to skip all tests that would time out,
|
||||
# since running the tests takes so long in the first place.
|
||||
|
||||
js1_5/Regress/regress-280769-2: SKIP
|
||||
js1_5/Regress/regress-280769-3: SKIP
|
||||
js1_5/Regress/regress-244470: SKIP
|
||||
js1_5/Regress/regress-203278-1: SKIP
|
||||
js1_5/Regress/regress-290575: SKIP
|
||||
js1_5/Regress/regress-159334: SKIP
|
||||
js1_5/Regress/regress-321971: SKIP
|
||||
js1_5/Regress/regress-347306-01: SKIP
|
||||
js1_5/Regress/regress-280769-1: SKIP
|
||||
js1_5/Regress/regress-280769-5: SKIP
|
||||
js1_5/GC/regress-306788: SKIP
|
||||
js1_5/GC/regress-203278-2: SKIP
|
||||
js1_5/GC/regress-278725: SKIP
|
||||
js1_5/GC/regress-203278-3: SKIP
|
||||
js1_5/GC/regress-311497: SKIP
|
||||
js1_5/Array/regress-99120-02: SKIP
|
||||
ecma/Date/15.9.5.22-1: SKIP
|
||||
ecma/Date/15.9.5.20: SKIP
|
||||
ecma/Date/15.9.5.12-2: SKIP
|
||||
ecma/Date/15.9.5.8: SKIP
|
||||
ecma/Date/15.9.5.9: SKIP
|
||||
ecma/Date/15.9.5.10-2: SKIP
|
||||
ecma/Date/15.9.5.11-2: SKIP
|
||||
ecma/Expressions/11.7.2: SKIP
|
||||
ecma/Expressions/11.10-2: SKIP
|
||||
ecma/Expressions/11.7.3: SKIP
|
||||
ecma/Expressions/11.10-3: SKIP
|
||||
ecma/Expressions/11.7.1: SKIP
|
||||
ecma_3/RegExp/regress-209067: SKIP
|
125
test/mozilla/testcfg.py
Normal file
125
test/mozilla/testcfg.py
Normal file
@ -0,0 +1,125 @@
|
||||
# Copyright 2008 Google Inc. 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.
|
||||
|
||||
|
||||
import os
|
||||
from os.path import join, exists
|
||||
import test
|
||||
|
||||
|
||||
EXCLUDED = ['CVS']
|
||||
|
||||
|
||||
FRAMEWORK = """
|
||||
browser.js
|
||||
shell.js
|
||||
jsref.js
|
||||
template.js
|
||||
""".split()
|
||||
|
||||
|
||||
TEST_DIRS = """
|
||||
ecma
|
||||
ecma_2
|
||||
ecma_3
|
||||
js1_1
|
||||
js1_2
|
||||
js1_3
|
||||
js1_4
|
||||
js1_5
|
||||
""".split()
|
||||
|
||||
|
||||
class MozillaTestCase(test.TestCase):
|
||||
|
||||
def __init__(self, filename, path, context, mode, framework):
|
||||
super(MozillaTestCase, self).__init__(context, path)
|
||||
self.filename = filename
|
||||
self.mode = mode
|
||||
self.framework = framework
|
||||
|
||||
def IsNegative(self):
|
||||
return self.filename.endswith('-n.js')
|
||||
|
||||
def GetLabel(self):
|
||||
return "%s mozilla %s" % (self.mode, self.GetName())
|
||||
|
||||
def IsFailureOutput(self, output):
|
||||
if output.exit_code != 0:
|
||||
return True
|
||||
return 'FAILED!' in output.stdout
|
||||
|
||||
def GetCommand(self):
|
||||
result = [self.context.GetVm(self.mode), '--expose-gc']
|
||||
result += self.framework
|
||||
result.append(self.filename)
|
||||
return result
|
||||
|
||||
def GetName(self):
|
||||
return self.path[-1]
|
||||
|
||||
|
||||
class MozillaTestConfiguration(test.TestConfiguration):
|
||||
|
||||
def __init__(self, context, root):
|
||||
super(MozillaTestConfiguration, self).__init__(context, root)
|
||||
|
||||
def ListTests(self, current_path, path, mode):
|
||||
tests = []
|
||||
for test_dir in TEST_DIRS:
|
||||
current_root = join(self.root, test_dir)
|
||||
for root, dirs, files in os.walk(current_root):
|
||||
for dotted in [x for x in dirs if x.startswith('.')]:
|
||||
dirs.remove(dotted)
|
||||
for excluded in EXCLUDED:
|
||||
if excluded in dirs:
|
||||
dirs.remove(excluded)
|
||||
root_path = root[len(self.root):].split(os.path.sep)
|
||||
root_path = current_path + [x for x in root_path if x]
|
||||
framework = []
|
||||
for i in xrange(len(root_path)):
|
||||
if i == 0: dir = root_path[1:]
|
||||
else: dir = root_path[1:-i]
|
||||
script = join(self.root, reduce(join, dir, ''), 'shell.js')
|
||||
if exists(script):
|
||||
framework.append(script)
|
||||
framework.reverse()
|
||||
for file in files:
|
||||
if (not file in FRAMEWORK) and file.endswith('.js'):
|
||||
full_path = root_path + [file[:-3]]
|
||||
if self.Contains(path, full_path):
|
||||
test = MozillaTestCase(join(root, file), full_path, self.context,
|
||||
mode, framework)
|
||||
tests.append(test)
|
||||
return tests
|
||||
|
||||
def GetBuildRequirements(self):
|
||||
return ['sample', 'sample=shell']
|
||||
|
||||
|
||||
def GetConfiguration(context, root):
|
||||
return MozillaTestConfiguration(context, root)
|
286
tools/test.py
286
tools/test.py
@ -33,6 +33,7 @@ import platform
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import utils
|
||||
|
||||
@ -61,7 +62,7 @@ class ProgressIndicator(object):
|
||||
case = test.case
|
||||
self.AboutToRun(case)
|
||||
output = case.Run()
|
||||
if output.HasFailed():
|
||||
if output.UnexpectedOutput():
|
||||
self.failed += 1
|
||||
self.failed_tests.append(output)
|
||||
else:
|
||||
@ -91,7 +92,7 @@ class SimpleProgressIndicator(ProgressIndicator):
|
||||
def Done(self):
|
||||
print
|
||||
for failed in self.failed_tests:
|
||||
print "=== %s ===" % failed.test.GetName()
|
||||
print "=== %s ===" % failed.test.GetLabel()
|
||||
print "Command: %s" % EscapeCommand(failed.command)
|
||||
if failed.output.stderr:
|
||||
print "--- stderr ---"
|
||||
@ -113,11 +114,11 @@ class SimpleProgressIndicator(ProgressIndicator):
|
||||
class VerboseProgressIndicator(SimpleProgressIndicator):
|
||||
|
||||
def AboutToRun(self, case):
|
||||
print '%s:' % case.GetName(),
|
||||
print '%s:' % case.GetLabel(),
|
||||
sys.stdout.flush()
|
||||
|
||||
def has_run(self, output):
|
||||
if output.HasFailed():
|
||||
def HasRun(self, output):
|
||||
if output.UnexpectedOutput():
|
||||
print "FAIL"
|
||||
else:
|
||||
print "pass"
|
||||
@ -128,11 +129,11 @@ class DotsProgressIndicator(SimpleProgressIndicator):
|
||||
def AboutToRun(self, case):
|
||||
pass
|
||||
|
||||
def has_run(self, output):
|
||||
def HasRun(self, output):
|
||||
total = self.succeeded + self.failed
|
||||
if (total > 1) and (total % 50 == 1):
|
||||
sys.stdout.write('\n')
|
||||
if output.HasFailed():
|
||||
if output.UnexpectedOutput():
|
||||
sys.stdout.write('F')
|
||||
sys.stdout.flush()
|
||||
else:
|
||||
@ -147,19 +148,19 @@ class CompactProgressIndicator(ProgressIndicator):
|
||||
self.templates = templates
|
||||
self.last_status_length = 0
|
||||
self.start_time = time.time()
|
||||
|
||||
|
||||
def Starting(self):
|
||||
pass
|
||||
|
||||
|
||||
def Done(self):
|
||||
self.PrintProgress('Done')
|
||||
|
||||
|
||||
def AboutToRun(self, case):
|
||||
self.PrintProgress(case.GetName())
|
||||
|
||||
self.PrintProgress(case.GetLabel())
|
||||
|
||||
def HasRun(self, output):
|
||||
if output.HasFailed():
|
||||
print "\n--- Failed: %s ---" % str(output.test.GetName())
|
||||
if output.UnexpectedOutput():
|
||||
print "\n--- Failed: %s ---" % str(output.test.GetLabel())
|
||||
print "Command: %s" % EscapeCommand(output.command)
|
||||
stdout = output.output.stdout.strip()
|
||||
if len(stdout):
|
||||
@ -200,7 +201,7 @@ class ColorProgressIndicator(CompactProgressIndicator):
|
||||
'stderr': "\033[31m%s\033[0m",
|
||||
}
|
||||
super(ColorProgressIndicator, self).__init__(cases, templates)
|
||||
|
||||
|
||||
def ClearLine(self, last_line_length):
|
||||
print "\033[1K\r",
|
||||
|
||||
@ -216,7 +217,7 @@ class MonochromeProgressIndicator(CompactProgressIndicator):
|
||||
'max_length': 78
|
||||
}
|
||||
super(MonochromeProgressIndicator, self).__init__(cases, templates)
|
||||
|
||||
|
||||
def ClearLine(self, last_line_length):
|
||||
print ("\r" + (" " * last_line_length) + "\r"),
|
||||
|
||||
@ -244,12 +245,19 @@ class CommandOutput(object):
|
||||
|
||||
class TestCase(object):
|
||||
|
||||
def __init__(self, path):
|
||||
def __init__(self, context, path):
|
||||
self.path = path
|
||||
self.context = context
|
||||
|
||||
def IsNegative(self):
|
||||
return False
|
||||
|
||||
def IsFailureOutput(self, output):
|
||||
return output.exit_code != 0
|
||||
|
||||
def Run(self):
|
||||
command = self.GetCommand()
|
||||
output = Execute(command)
|
||||
output = Execute(command, self.context)
|
||||
return TestOutput(self, command, output)
|
||||
|
||||
|
||||
@ -260,27 +268,66 @@ class TestOutput(object):
|
||||
self.command = command
|
||||
self.output = output
|
||||
|
||||
def UnexpectedOutput(self):
|
||||
if self.HasFailed():
|
||||
outcome = FAIL
|
||||
else:
|
||||
outcome = PASS
|
||||
return not outcome in self.test.outcomes
|
||||
|
||||
def HasFailed(self):
|
||||
return self.output.exit_code != 0
|
||||
execution_failed = self.test.IsFailureOutput(self.output)
|
||||
if self.test.IsNegative():
|
||||
return not execution_failed
|
||||
else:
|
||||
return execution_failed
|
||||
|
||||
|
||||
def Execute(args):
|
||||
if VERBOSE: print " ".join(args)
|
||||
MAX_SLEEP_TIME = 0.1
|
||||
INITIAL_SLEEP_TIME = 0.0001
|
||||
SLEEP_TIME_FACTOR = 1.25
|
||||
|
||||
|
||||
def RunProcess(context, **args):
|
||||
if context.verbose: print "#", " ".join(args['args'])
|
||||
process = subprocess.Popen(
|
||||
args = args,
|
||||
stdout = subprocess.PIPE,
|
||||
stderr = subprocess.PIPE
|
||||
shell = (platform.system() == 'Windows'),
|
||||
**args
|
||||
)
|
||||
exit_code = process.wait()
|
||||
output = process.stdout.read()
|
||||
errors = process.stderr.read()
|
||||
exit_code = None
|
||||
sleep_time = INITIAL_SLEEP_TIME
|
||||
while exit_code is None:
|
||||
exit_code = process.poll()
|
||||
time.sleep(sleep_time)
|
||||
sleep_time = sleep_time * SLEEP_TIME_FACTOR
|
||||
if sleep_time > MAX_SLEEP_TIME:
|
||||
sleep_time = MAX_SLEEP_TIME
|
||||
return (process, exit_code)
|
||||
|
||||
|
||||
def Execute(args, context):
|
||||
(fd_out, outname) = tempfile.mkstemp()
|
||||
(fd_err, errname) = tempfile.mkstemp()
|
||||
(process, exit_code) = RunProcess(
|
||||
context,
|
||||
args = args,
|
||||
stdout = fd_out,
|
||||
stderr = fd_err,
|
||||
)
|
||||
os.close(fd_out)
|
||||
os.close(fd_err)
|
||||
output = file(outname).read()
|
||||
errors = file(errname).read()
|
||||
os.unlink(outname)
|
||||
os.unlink(errname)
|
||||
return CommandOutput(exit_code, output, errors)
|
||||
|
||||
|
||||
def ExecuteNoCapture(args):
|
||||
if VERBOSE: print " ".join(args)
|
||||
process = subprocess.Popen(args = args)
|
||||
exit_code = process.wait()
|
||||
def ExecuteNoCapture(args, context):
|
||||
(process, exit_code) = RunProcess(
|
||||
context,
|
||||
args = args,
|
||||
)
|
||||
return CommandOutput(exit_code, "", "")
|
||||
|
||||
|
||||
@ -297,6 +344,14 @@ class TestConfiguration(object):
|
||||
self.context = context
|
||||
self.root = root
|
||||
|
||||
def Contains(self, path, file):
|
||||
if len(path) > len(file):
|
||||
return False
|
||||
for i in xrange(len(path)):
|
||||
if not path[i].match(file[i]):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
class TestSuite(object):
|
||||
|
||||
@ -346,7 +401,7 @@ class LiteralTestSuite(TestSuite):
|
||||
(name, rest) = CarCdr(path)
|
||||
result = [ ]
|
||||
for test in self.tests:
|
||||
if not name or name == test.GetName():
|
||||
if not name or name.match(test.GetName()):
|
||||
result += test.GetBuildRequirements(rest, context)
|
||||
return result
|
||||
|
||||
@ -355,29 +410,42 @@ class LiteralTestSuite(TestSuite):
|
||||
result = [ ]
|
||||
for test in self.tests:
|
||||
test_name = test.GetName()
|
||||
if not name or name == test_name:
|
||||
if not name or name.match(test_name):
|
||||
full_path = current_path + [test_name]
|
||||
result += test.ListTests(full_path, rest, context, mode)
|
||||
result += test.ListTests(full_path, path, context, mode)
|
||||
return result
|
||||
|
||||
|
||||
PREFIX = {'debug': '_g', 'release': ''}
|
||||
|
||||
|
||||
class Context(object):
|
||||
|
||||
def __init__(self, workspace, buildspace, vm):
|
||||
def __init__(self, workspace, buildspace, verbose, vm, timeout):
|
||||
self.workspace = workspace
|
||||
self.buildspace = buildspace
|
||||
self.vm = vm
|
||||
self.verbose = verbose
|
||||
self.vm_root = vm
|
||||
self.timeout = timeout
|
||||
|
||||
def GetVm(self, mode):
|
||||
name = self.vm_root + PREFIX[mode]
|
||||
if platform.system() == 'Windows':
|
||||
return name + '.exe'
|
||||
else:
|
||||
return name
|
||||
|
||||
def RunTestCases(all_cases, progress):
|
||||
cases_to_run = [ c for c in all_cases if not SKIP in c.outcomes ]
|
||||
def DoSkip(case):
|
||||
return SKIP in c.outcomes or SLOW in c.outcomes
|
||||
cases_to_run = [ c for c in all_cases if not DoSkip(c) ]
|
||||
progress = PROGRESS_INDICATORS[progress](cases_to_run)
|
||||
progress.Run()
|
||||
|
||||
|
||||
def BuildRequirements(workspace, requirements, mode):
|
||||
command_line = ['scons', '-Y', workspace, 'mode=' + ",".join(mode)] + requirements
|
||||
output = ExecuteNoCapture(command_line)
|
||||
def BuildRequirements(context, requirements, mode):
|
||||
command_line = ['scons', '-Y', context.workspace, 'mode=' + ",".join(mode)] + requirements
|
||||
output = ExecuteNoCapture(command_line, context)
|
||||
return output.exit_code == 0
|
||||
|
||||
|
||||
@ -392,6 +460,7 @@ PASS = 'pass'
|
||||
OKAY = 'okay'
|
||||
TIMEOUT = 'timeout'
|
||||
CRASH = 'crash'
|
||||
SLOW = 'slow'
|
||||
|
||||
|
||||
class Expression(object):
|
||||
@ -424,7 +493,7 @@ class Outcome(Expression):
|
||||
|
||||
def GetOutcomes(self, env, defs):
|
||||
if self.name in defs:
|
||||
return defs[self.name].get_outcomes(env, defs)
|
||||
return defs[self.name].GetOutcomes(env, defs)
|
||||
else:
|
||||
return ListSet([self.name])
|
||||
|
||||
@ -437,7 +506,7 @@ class ListSet(Set):
|
||||
|
||||
def __init__(self, elms):
|
||||
self.elms = elms
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return "ListSet%s" % str(self.elms)
|
||||
|
||||
@ -450,7 +519,7 @@ class ListSet(Set):
|
||||
if not isinstance(that, ListSet):
|
||||
return that.Union(self)
|
||||
return ListSet(self.elms + [ x for x in that.elms if x not in self.elms ])
|
||||
|
||||
|
||||
def IsEmpty(self):
|
||||
return len(self.elms) == 0
|
||||
|
||||
@ -462,7 +531,7 @@ class Everything(Set):
|
||||
|
||||
def Union(self, that):
|
||||
return self
|
||||
|
||||
|
||||
def IsEmpty(self):
|
||||
return False
|
||||
|
||||
@ -474,7 +543,7 @@ class Nothing(Set):
|
||||
|
||||
def Union(self, that):
|
||||
return that
|
||||
|
||||
|
||||
def IsEmpty(self):
|
||||
return True
|
||||
|
||||
@ -527,7 +596,7 @@ class Tokenizer(object):
|
||||
self.tokens = None
|
||||
|
||||
def Current(self, length = 1):
|
||||
if not self.has_more(length): return ""
|
||||
if not self.HasMore(length): return ""
|
||||
return self.expr[self.index:self.index+length]
|
||||
|
||||
def HasMore(self, length = 1):
|
||||
@ -540,7 +609,7 @@ class Tokenizer(object):
|
||||
self.tokens.append(token)
|
||||
|
||||
def SkipSpaces(self):
|
||||
while self.HasMore() and self.current().isspace():
|
||||
while self.HasMore() and self.Current().isspace():
|
||||
self.Advance()
|
||||
|
||||
def Tokenize(self):
|
||||
@ -552,7 +621,7 @@ class Tokenizer(object):
|
||||
if self.Current() == '(':
|
||||
self.AddToken('(')
|
||||
self.Advance()
|
||||
elif self.current() == ')':
|
||||
elif self.Current() == ')':
|
||||
self.AddToken(')')
|
||||
self.Advance()
|
||||
elif self.Current() == '$':
|
||||
@ -670,7 +739,7 @@ def ParseLogicalExpression(scan):
|
||||
|
||||
def ParseCondition(expr):
|
||||
"""Parses a logical expression into an Expression object"""
|
||||
tokens = Tokenizer(expr).tokenize()
|
||||
tokens = Tokenizer(expr).Tokenize()
|
||||
if not tokens:
|
||||
print "Malformed expression: '%s'" % expr
|
||||
return None
|
||||
@ -705,8 +774,11 @@ class Configuration(object):
|
||||
matches = [ r for r in all_rules if r.Contains(case.path) ]
|
||||
outcomes = set([])
|
||||
for rule in matches:
|
||||
outcomes = outcomes.Union(rule.GetOutcomes(env, self.defs))
|
||||
outcomes = outcomes.union(rule.GetOutcomes(env, self.defs))
|
||||
unused_rules.discard(rule)
|
||||
if not outcomes:
|
||||
outcomes = [PASS]
|
||||
case.outcomes = outcomes
|
||||
result.append(ClassifiedTest(case, outcomes))
|
||||
return (result, list(unused_rules))
|
||||
|
||||
@ -727,7 +799,8 @@ class Rule(object):
|
||||
"""A single rule that specifies the expected outcome for a single
|
||||
test."""
|
||||
|
||||
def __init__(self, path, value):
|
||||
def __init__(self, raw_path, path, value):
|
||||
self.raw_path = raw_path
|
||||
self.path = path
|
||||
self.value = value
|
||||
|
||||
@ -735,24 +808,26 @@ class Rule(object):
|
||||
set = self.value.GetOutcomes(env, defs)
|
||||
assert isinstance(set, ListSet)
|
||||
return set.elms
|
||||
|
||||
|
||||
def Contains(self, path):
|
||||
if len(self.path) > len(path):
|
||||
return False
|
||||
for i in xrange(len(self.path)):
|
||||
if path[i] != self.path[i]:
|
||||
if not self.path[i].match(path[i]):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
HEADER_PATTERN = re.compile(r'\[([^]]+)\]')
|
||||
RULE_PATTERN = re.compile(r'\s*(%?)([^: ]*)\s*:(.*)')
|
||||
RULE_PATTERN = re.compile(r'\s*([^: ]*)\s*:(.*)')
|
||||
DEF_PATTERN = re.compile(r'^def\s*(\w+)\s*=(.*)$')
|
||||
PREFIX_PATTERN = re.compile(r'^\s*prefix\s+([\w\_\.\-\/]+)$')
|
||||
|
||||
|
||||
def ReadConfigurationInto(path, sections, defs):
|
||||
current_section = Section(Constant(True))
|
||||
sections.append(current_section)
|
||||
prefix = []
|
||||
for line in utils.ReadLinesFrom(path):
|
||||
header_match = HEADER_PATTERN.match(line)
|
||||
if header_match:
|
||||
@ -764,12 +839,12 @@ def ReadConfigurationInto(path, sections, defs):
|
||||
continue
|
||||
rule_match = RULE_PATTERN.match(line)
|
||||
if rule_match:
|
||||
path = SplitPath(rule_match.group(2).strip())
|
||||
value_str = rule_match.group(3).strip()
|
||||
path = prefix + SplitPath(rule_match.group(1).strip())
|
||||
value_str = rule_match.group(2).strip()
|
||||
value = ParseCondition(value_str)
|
||||
if not value:
|
||||
return False
|
||||
current_section.AddRule(Rule(path, value))
|
||||
current_section.AddRule(Rule(rule_match.group(1), path, value))
|
||||
continue
|
||||
def_match = DEF_PATTERN.match(line)
|
||||
if def_match:
|
||||
@ -779,6 +854,10 @@ def ReadConfigurationInto(path, sections, defs):
|
||||
return False
|
||||
defs[name] = value
|
||||
continue
|
||||
prefix_match = PREFIX_PATTERN.match(line)
|
||||
if prefix_match:
|
||||
prefix = SplitPath(prefix_match.group(1).strip())
|
||||
continue
|
||||
print "Malformed line: '%s'." % line
|
||||
return False
|
||||
return True
|
||||
@ -800,8 +879,8 @@ def ReadConfiguration(paths):
|
||||
|
||||
def BuildOptions():
|
||||
result = optparse.OptionParser()
|
||||
result.add_option("-m", "--mode", help="The test mode in which to run",
|
||||
choices=['release', 'debug'])
|
||||
result.add_option("-m", "--mode", help="The test modes in which to run (comma-separated)",
|
||||
default='release')
|
||||
result.add_option("-v", "--verbose", help="Verbose output",
|
||||
default=False, action="store_true")
|
||||
result.add_option("-p", "--progress",
|
||||
@ -814,27 +893,31 @@ def BuildOptions():
|
||||
default=False, action="store_true")
|
||||
result.add_option("--report", help="Print a summary of the tests to be run",
|
||||
default=False, action="store_true")
|
||||
result.add_option("-s", "--suite", help="A test suite",
|
||||
default=[], action="append")
|
||||
result.add_option("-t", "--timeout", help="Timeout in seconds",
|
||||
default=60, type="int")
|
||||
return result
|
||||
|
||||
|
||||
def ProcessOptions(options):
|
||||
global VERBOSE
|
||||
VERBOSE = options.verbose
|
||||
mode = options.mode
|
||||
if mode == 'all': mode = ['release', 'debug']
|
||||
elif not mode: mode = ['release']
|
||||
else: mode = [mode]
|
||||
options.mode = mode
|
||||
options.mode = options.mode.split(',')
|
||||
for mode in options.mode:
|
||||
if not mode in ['debug', 'release']:
|
||||
print "Unknown mode %s" % mode
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
REPORT_TEMPLATE = """\
|
||||
Total: %(total)i tests
|
||||
* %(skipped)3d tests will be skipped
|
||||
* %(nocrash)3d tests are expected to be flaky but not crash
|
||||
* %(pass)3d tests are expected to pass
|
||||
* %(fail_ok)3d tests are expected to fail that we won't fix
|
||||
* %(fail)3d tests are expected to fail that we should fix\
|
||||
* %(skipped)4d tests will be skipped
|
||||
* %(nocrash)4d tests are expected to be flaky but not crash
|
||||
* %(pass)4d tests are expected to pass
|
||||
* %(fail_ok)4d tests are expected to fail that we won't fix
|
||||
* %(fail)4d tests are expected to fail that we should fix\
|
||||
"""
|
||||
|
||||
def PrintReport(cases):
|
||||
@ -853,9 +936,28 @@ def PrintReport(cases):
|
||||
}
|
||||
|
||||
|
||||
class Pattern(object):
|
||||
|
||||
def __init__(self, pattern):
|
||||
self.pattern = pattern
|
||||
self.compiled = None
|
||||
|
||||
def match(self, str):
|
||||
if not self.compiled:
|
||||
pattern = "^" + self.pattern.replace('*', '.*') + "$"
|
||||
self.compiled = re.compile(pattern)
|
||||
return self.compiled.match(str)
|
||||
|
||||
def __str__(self):
|
||||
return self.pattern
|
||||
|
||||
|
||||
def SplitPath(s):
|
||||
stripped = [ c.strip() for c in s.split('/') ]
|
||||
return [ s for s in stripped if len(s) > 0 ]
|
||||
return [ Pattern(s) for s in stripped if len(s) > 0 ]
|
||||
|
||||
|
||||
BUILT_IN_TESTS = ['mjsunit', 'cctest']
|
||||
|
||||
|
||||
def Main():
|
||||
@ -869,11 +971,12 @@ def Main():
|
||||
return 1
|
||||
|
||||
workspace = abspath(join(dirname(sys.argv[0]), '..'))
|
||||
tests = ['mjsunit']
|
||||
repositories = [TestRepository(join(workspace, 'test', name)) for name in tests]
|
||||
repositories = [TestRepository(join(workspace, 'test', name)) for name in BUILT_IN_TESTS]
|
||||
repositories += [TestRepository(a) for a in options.suite]
|
||||
|
||||
root = LiteralTestSuite(repositories)
|
||||
if len(args) == 0:
|
||||
paths = [[]]
|
||||
paths = [SplitPath(t) for t in BUILT_IN_TESTS]
|
||||
else:
|
||||
paths = [ ]
|
||||
for arg in args:
|
||||
@ -882,36 +985,45 @@ def Main():
|
||||
|
||||
# First build the required targets
|
||||
buildspace = abspath('.')
|
||||
context = Context(workspace, buildspace, join(buildspace, 'shell'))
|
||||
context = Context(workspace, buildspace, VERBOSE,
|
||||
join(buildspace, 'shell'),
|
||||
options.timeout)
|
||||
if not options.no_build:
|
||||
reqs = [ ]
|
||||
for path in paths:
|
||||
reqs += root.GetBuildRequirements(path, context)
|
||||
reqs = list(set(reqs))
|
||||
if len(reqs) > 0:
|
||||
if not BuildRequirements(workspace, reqs, options.mode):
|
||||
if not BuildRequirements(context, reqs, options.mode):
|
||||
return 1
|
||||
|
||||
# Then list the tests
|
||||
cases = [ ]
|
||||
all_cases = [ ]
|
||||
all_unused = [ ]
|
||||
for path in paths:
|
||||
for mode in options.mode:
|
||||
cases += root.ListTests([], path, context, mode)
|
||||
env = {
|
||||
'mode': mode
|
||||
}
|
||||
test_list = root.ListTests([], path, context, mode)
|
||||
(cases, unused_rules) = config.ClassifyTests(test_list, env)
|
||||
all_cases += cases
|
||||
all_unused.append(unused_rules)
|
||||
|
||||
env = { }
|
||||
(cases, unused_rules) = config.ClassifyTests(cases, env)
|
||||
# for rule in unused_rules:
|
||||
# print "Rule for '%s' was not used." % '/'.join([str(s) for s in rule.path])
|
||||
|
||||
for rule in unused_rules:
|
||||
print "Rule for '%s' was not used." % "/".join(rule.path)
|
||||
return 0
|
||||
|
||||
if options.report:
|
||||
PrintReport(cases)
|
||||
|
||||
if len(cases) == 0:
|
||||
PrintReport(all_cases)
|
||||
|
||||
if len(all_cases) == 0:
|
||||
print "No tests to run."
|
||||
else:
|
||||
RunTestCases(cases, options.progress)
|
||||
try:
|
||||
RunTestCases(all_cases, options.progress)
|
||||
except KeyboardInterrupt:
|
||||
print "Interrupted"
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user