Included mjsunit JavaScript test suite and C++ unit tests.
In the shell sample don't print the result of executing a script, only evaluating expressions. Fixed issue when building samples on Windows using a shared V8 library. Added visibility option on Linux build which makes the generated library 18% smaller. Changed build system to accept multiple build modes in one build and generate seperate objects, libraries and executables for each mode. Removed deferred negation optimization (a * -b => -(a * b)) since this visibly changes operand conversion order. Improved parsing performance by introducing stack guard in preparsing. Without a stack guard preparsing always bails out with stack overflow. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
75bc1a2017
commit
c42f5829a1
350
SConstruct
350
SConstruct
@ -34,6 +34,156 @@ sys.path.append(join(root_dir, 'tools'))
|
||||
import js2c
|
||||
|
||||
|
||||
LIBRARY_FLAGS = {
|
||||
'all': {
|
||||
'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING']
|
||||
},
|
||||
'gcc': {
|
||||
'all': {
|
||||
'DIALECTFLAGS': ['-ansi'],
|
||||
'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
|
||||
'CXXFLAGS': ['$CCFLAGS', '-fno-rtti', '-fno-exceptions'],
|
||||
'LIBS': ['pthread']
|
||||
},
|
||||
'mode:debug': {
|
||||
'CCFLAGS': ['-g', '-O0'],
|
||||
'CPPDEFINES': ['ENABLE_DISASSEMBLER', 'DEBUG']
|
||||
},
|
||||
'mode:release': {
|
||||
'CCFLAGS': ['-O2']
|
||||
},
|
||||
},
|
||||
'msvc': {
|
||||
'all': {
|
||||
'DIALECTFLAGS': ['/nologo'],
|
||||
'WARNINGFLAGS': ['/W3', '/WX', '/wd4355', '/wd4800'],
|
||||
'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
|
||||
'CXXFLAGS': ['$CCFLAGS', '/GS-', '/GR-', '/Gy'],
|
||||
'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE',
|
||||
'_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T',
|
||||
'PCRE_STATIC'],
|
||||
'LINKFLAGS': ['/NOLOGO', '/MACHINE:X86', '/INCREMENTAL:NO',
|
||||
'/NXCOMPAT', '/IGNORE:4221'],
|
||||
'ARFLAGS': ['/NOLOGO'],
|
||||
'CCPDBFLAGS': ['/Zi']
|
||||
},
|
||||
'mode:debug': {
|
||||
'CCFLAGS': ['/Od', '/Gm', '/MTd'],
|
||||
'CPPDEFINES': ['_DEBUG', 'ENABLE_DISASSEMBLER', 'DEBUG'],
|
||||
'LINKFLAGS': ['/DEBUG']
|
||||
},
|
||||
'mode:release': {
|
||||
'CCFLAGS': ['/Ox', '/MT', '/Ob2', '/Oi', '/Oy'],
|
||||
'LINKFLAGS': ['/OPT:REF']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
V8_EXTRA_FLAGS = {
|
||||
'gcc': {
|
||||
'all': {
|
||||
'CXXFLAGS': ['-fvisibility=hidden'],
|
||||
'WARNINGFLAGS': ['-pedantic', '-Wall', '-Werror', '-W',
|
||||
'-Wno-unused-parameter']
|
||||
},
|
||||
},
|
||||
'msvc': {
|
||||
'all': {
|
||||
'WARNINGFLAGS': ['/W3', '/WX', '/wd4355', '/wd4800']
|
||||
},
|
||||
'library:shared': {
|
||||
'CPPDEFINES': ['BUILDING_V8_SHARED']
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
JSCRE_EXTRA_FLAGS = {
|
||||
'gcc': {
|
||||
'all': {
|
||||
'CPPDEFINES': ['SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
|
||||
'WARNINGFLAGS': ['-w']
|
||||
},
|
||||
},
|
||||
'msvc': {
|
||||
'all': {
|
||||
'CPPDEFINES': ['SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
|
||||
'WARNINGFLAGS': ['/W3', '/WX', '/wd4355', '/wd4800']
|
||||
},
|
||||
'library:shared': {
|
||||
'CPPDEFINES': ['BUILDING_V8_SHARED']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DTOA_EXTRA_FLAGS = {
|
||||
'gcc': {
|
||||
'all': {
|
||||
'WARNINGFLAGS': ['-Werror']
|
||||
}
|
||||
},
|
||||
'msvc': {
|
||||
'all': {
|
||||
'WARNINGFLAGS': ['/WX', '/wd4018', '/wd4244']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CCTEST_EXTRA_FLAGS = {
|
||||
'all': {
|
||||
'CPPPATH': [join(root_dir, 'src')],
|
||||
'LIBS': ['$LIBRARY']
|
||||
},
|
||||
'gcc': {
|
||||
'all': {
|
||||
'LIBPATH': [abspath('.')]
|
||||
}
|
||||
},
|
||||
'msvc': {
|
||||
'library:shared': {
|
||||
'CPPDEFINES': ['USING_V8_SHARED']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SAMPLE_FLAGS = {
|
||||
'all': {
|
||||
'CPPPATH': [join(abspath('.'), 'public')],
|
||||
'LIBS': ['$LIBRARY'],
|
||||
},
|
||||
'gcc': {
|
||||
'all': {
|
||||
'LIBS': ['pthread'],
|
||||
'LIBPATH': ['.']
|
||||
},
|
||||
},
|
||||
'msvc': {
|
||||
'all': {
|
||||
'CCFLAGS': ['/nologo'],
|
||||
},
|
||||
'library:shared': {
|
||||
'CPPDEFINES': ['USING_V8_SHARED']
|
||||
},
|
||||
'mode:release': {
|
||||
'CCFLAGS': ['/MT'],
|
||||
},
|
||||
'mode:debug': {
|
||||
'CCFLAGS': ['/MTd']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SUFFIXES = {
|
||||
'release': '',
|
||||
'debug': '_g'
|
||||
}
|
||||
|
||||
|
||||
def Abort(message):
|
||||
print message
|
||||
sys.exit(1)
|
||||
@ -82,13 +232,26 @@ def GetOptions():
|
||||
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 (process, shell)', '')
|
||||
result.Add('sample', 'build sample (shell, process)', '')
|
||||
return result
|
||||
|
||||
|
||||
def SplitList(str):
|
||||
return [ s for s in str.split(",") if len(s) > 0 ]
|
||||
|
||||
|
||||
def IsLegal(env, option, values):
|
||||
str = env[option]
|
||||
for s in SplitList(str):
|
||||
if not s in values:
|
||||
Abort("Illegal value for option %s '%s'." % (option, s))
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def VerifyOptions(env):
|
||||
if not env['mode'] in ['debug', 'release']:
|
||||
Abort("Unknown build mode '%s'." % env['mode'])
|
||||
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']:
|
||||
@ -99,8 +262,130 @@ def VerifyOptions(env):
|
||||
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 env['sample'] in ['', 'process', 'shell']:
|
||||
Abort("Illegal value for option sample: '%s'." % env['sample'])
|
||||
if not IsLegal(env, 'sample', ["shell", "process"]):
|
||||
return False
|
||||
|
||||
|
||||
class BuildContext(object):
|
||||
|
||||
def __init__(self, os, arch, toolchain, snapshot, library, samples, mode):
|
||||
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.samples = samples
|
||||
self.mode = mode
|
||||
self.use_snapshot = (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))
|
||||
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
|
||||
|
||||
def AppendFlags(self, options, added):
|
||||
if not added:
|
||||
return
|
||||
for (key, value) in added.items():
|
||||
if not key in options:
|
||||
options[key] = value
|
||||
else:
|
||||
options[key] = options[key] + value
|
||||
|
||||
def ConfigureObject(self, env, input, **kw):
|
||||
if self.library == 'static':
|
||||
return env.StaticObject(input, **kw)
|
||||
elif self.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)
|
||||
|
||||
library_flags = context.AddRelevantFlags({}, 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)
|
||||
|
||||
context.flags = {
|
||||
'v8': v8_flags,
|
||||
'jscre': jscre_flags,
|
||||
'dtoa': dtoa_flags,
|
||||
'cctest': cctest_flags,
|
||||
'sample': sample_flags
|
||||
}
|
||||
|
||||
target_id = mode
|
||||
suffix = SUFFIXES[target_id]
|
||||
library_name = 'v8' + suffix
|
||||
env['LIBRARY'] = library_name
|
||||
|
||||
# Build the object files by invoking SCons recursively.
|
||||
object_files = env.SConscript(
|
||||
join('src', 'SConscript'),
|
||||
build_dir=join('obj', target_id),
|
||||
exports='context',
|
||||
duplicate=False
|
||||
)
|
||||
|
||||
# Link the object files into a library.
|
||||
if context.library == 'static':
|
||||
library = env.StaticLibrary(library_name, object_files)
|
||||
elif context.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.
|
||||
pdb_name = library_name + '.dll.pdb'
|
||||
library = env.SharedLibrary(library_name, object_files, PDB=pdb_name)
|
||||
else:
|
||||
library = env.Library(library_name, object_files)
|
||||
context.library_targets.append(library)
|
||||
|
||||
for sample in context.samples:
|
||||
sample_env = Environment(LIBRARY=library_name)
|
||||
sample_env.Replace(**context.flags['sample'])
|
||||
sample_object = sample_env.SConscript(
|
||||
join('samples', 'SConscript'),
|
||||
build_dir=join('obj', 'sample', sample, target_id),
|
||||
exports='sample context',
|
||||
duplicate=False
|
||||
)
|
||||
sample_name = sample + suffix
|
||||
sample_program = sample_env.Program(sample_name, sample_object)
|
||||
sample_env.Depends(sample_program, library)
|
||||
context.sample_targets.append(sample_program)
|
||||
|
||||
cctest_program = env.SConscript(
|
||||
join('test', 'cctest', 'SConscript'),
|
||||
build_dir=join('obj', 'test', target_id),
|
||||
exports='context object_files',
|
||||
duplicate=False
|
||||
)
|
||||
context.cctest_targets.append(cctest_program)
|
||||
|
||||
return context
|
||||
|
||||
|
||||
def Build():
|
||||
@ -108,46 +393,25 @@ def Build():
|
||||
env = Environment(options=opts)
|
||||
Help(opts.GenerateHelpText(env))
|
||||
VerifyOptions(env)
|
||||
|
||||
libraries = []
|
||||
cctests = []
|
||||
samples = []
|
||||
modes = SplitList(env['mode'])
|
||||
for mode in modes:
|
||||
context = BuildSpecific(env.Copy(), mode)
|
||||
libraries += context.library_targets
|
||||
cctests += context.cctest_targets
|
||||
samples += context.sample_targets
|
||||
|
||||
os = env['os']
|
||||
arch = env['processor']
|
||||
toolchain = env['toolchain']
|
||||
mode = env['mode']
|
||||
use_snapshot = (env['snapshot'] == 'on')
|
||||
library_type = env['library']
|
||||
|
||||
# Build the object files by invoking SCons recursively.
|
||||
object_files = env.SConscript(
|
||||
join('src', 'SConscript'),
|
||||
build_dir='build',
|
||||
exports='toolchain arch os mode use_snapshot library_type',
|
||||
duplicate=False
|
||||
)
|
||||
|
||||
# Link the object files into a library.
|
||||
if library_type == 'static':
|
||||
library = env.StaticLibrary('v8', object_files)
|
||||
elif library_type == '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.
|
||||
library = env.SharedLibrary('v8', object_files, PDB='v8.dll.pdb')
|
||||
env.Alias('library', libraries)
|
||||
env.Alias('cctests', cctests)
|
||||
env.Alias('sample', samples)
|
||||
|
||||
if env['sample']:
|
||||
env.Default('sample')
|
||||
else:
|
||||
library = env.Library('v8', object_files)
|
||||
|
||||
# Bail out if we're not building any sample.
|
||||
sample = env['sample']
|
||||
if not sample: return
|
||||
|
||||
# Build the sample.
|
||||
env.Replace(CPPPATH='public')
|
||||
object_path = join('build', 'samples', sample)
|
||||
source_path = join('samples', sample + '.cc')
|
||||
object = env.Object(object_path, source_path)
|
||||
if toolchain == 'gcc':
|
||||
env.Program(sample, [object, library], LIBS='pthread')
|
||||
else:
|
||||
env.Program(sample, [object, library], LIBS='WS2_32')
|
||||
env.Default('library')
|
||||
|
||||
|
||||
Build()
|
||||
|
@ -30,12 +30,40 @@
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
#define EXPORT __attribute__((visibility("default")))
|
||||
#ifdef _WIN32
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef long long int64_t;
|
||||
|
||||
// Setup for Windows DLL export/import. See v8.h in this directory for
|
||||
// information on how to build/use V8 as a DLL.
|
||||
#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
|
||||
#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
|
||||
build configuration to ensure that at most one of these is set
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_V8_SHARED
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#elif USING_V8_SHARED
|
||||
#define EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define EXPORT
|
||||
#endif
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
// Setup for Linux shared library export. See v8.h in this directory for
|
||||
// information on how to build/use V8 as shared library.
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
#define EXPORT __attribute__ ((visibility("default")))
|
||||
#else // defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
#define EXPORT
|
||||
#endif // defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
/**
|
||||
* Debugger support for the V8 JavaScript engine.
|
||||
*/
|
||||
|
147
public/v8.h
147
public/v8.h
@ -43,10 +43,50 @@ typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef long long int64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
|
||||
// Setup for Windows DLL export/import. When building the V8 DLL the
|
||||
// BUILDING_V8_SHARED needs to be defined. When building a program which uses
|
||||
// the V8 DLL USING_V8_SHARED needs to be defined. When either building the V8
|
||||
// static library or building a program which uses the V8 static library neither
|
||||
// BUILDING_V8_SHARED nor USING_V8_SHARED should be defined.
|
||||
// The reason for having both EXPORT and EXPORT_INLINE is that classes which
|
||||
// have their code inside this header file needs to have __declspec(dllexport)
|
||||
// when building the DLL but cannot have __declspec(dllimport) when building
|
||||
// a program which uses the DLL.
|
||||
#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
|
||||
#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
|
||||
build configuration to ensure that at most one of these is set
|
||||
#endif
|
||||
|
||||
#ifdef BUILDING_V8_SHARED
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#define EXPORT_INLINE __declspec(dllexport)
|
||||
#elif USING_V8_SHARED
|
||||
#define EXPORT __declspec(dllimport)
|
||||
#define EXPORT_INLINE
|
||||
#else
|
||||
#define EXPORT
|
||||
#define EXPORT_INLINE
|
||||
#endif // BUILDING_V8_SHARED
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Setup for Linux shared library export. There is no need to destinguish
|
||||
// neither between building or using the V8 shared library nor between using
|
||||
// the shared or static V8 library as there is on Windows. Therefore there is
|
||||
// on checking of BUILDING_V8_SHARED and USING_V8_SHARED.
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
#define EXPORT __attribute__ ((visibility("default")))
|
||||
#define EXPORT_INLINE __attribute__ ((visibility("default")))
|
||||
#else // defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
#define EXPORT
|
||||
#define EXPORT_INLINE
|
||||
#endif // defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
/**
|
||||
* The v8 javascript engine.
|
||||
*/
|
||||
@ -122,7 +162,7 @@ typedef void (*WeakReferenceCallback)(Persistent<Object> object,
|
||||
* behind the scenes and the same rules apply to these values as to
|
||||
* their handles.
|
||||
*/
|
||||
template <class T> class Handle {
|
||||
template <class T> class EXPORT_INLINE Handle {
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -210,7 +250,7 @@ template <class T> class Handle {
|
||||
* handle scope are destroyed when the handle scope is destroyed. Hence it
|
||||
* is not necessary to explicitly deallocate local handles.
|
||||
*/
|
||||
template <class T> class Local : public Handle<T> {
|
||||
template <class T> class EXPORT_INLINE Local : public Handle<T> {
|
||||
public:
|
||||
Local();
|
||||
template <class S> inline Local(Local<S> that)
|
||||
@ -253,7 +293,7 @@ template <class T> class Local : public Handle<T> {
|
||||
* different storage cells but rather two references to the same
|
||||
* storage cell.
|
||||
*/
|
||||
template <class T> class Persistent : public Handle<T> {
|
||||
template <class T> class EXPORT_INLINE Persistent : public Handle<T> {
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -348,7 +388,7 @@ template <class T> class Persistent : public Handle<T> {
|
||||
* handle and may deallocate it. The behavior of accessing a handle
|
||||
* for which the handle scope has been deleted is undefined.
|
||||
*/
|
||||
class HandleScope {
|
||||
class EXPORT HandleScope {
|
||||
public:
|
||||
HandleScope() : previous_(current_), is_closed_(false) {
|
||||
current_.extensions = 0;
|
||||
@ -386,7 +426,7 @@ class HandleScope {
|
||||
void* operator new(size_t size);
|
||||
void operator delete(void*, size_t);
|
||||
|
||||
class Data {
|
||||
class EXPORT Data {
|
||||
public:
|
||||
int extensions;
|
||||
void** next;
|
||||
@ -434,7 +474,7 @@ class HandleScope {
|
||||
/**
|
||||
* The superclass of values and API object templates.
|
||||
*/
|
||||
class Data {
|
||||
class EXPORT Data {
|
||||
private:
|
||||
Data();
|
||||
};
|
||||
@ -446,7 +486,7 @@ class Data {
|
||||
* compiling it, and stored between compilations. When script data
|
||||
* is given to the compile method compilation will be faster.
|
||||
*/
|
||||
class ScriptData {
|
||||
class EXPORT ScriptData {
|
||||
public:
|
||||
virtual ~ScriptData() { }
|
||||
static ScriptData* PreCompile(const char* input, int length);
|
||||
@ -460,7 +500,7 @@ class ScriptData {
|
||||
/**
|
||||
* The origin, within a file, of a script.
|
||||
*/
|
||||
class ScriptOrigin {
|
||||
class EXPORT ScriptOrigin {
|
||||
public:
|
||||
ScriptOrigin(Handle<Value> resource_name,
|
||||
Handle<Integer> resource_line_offset = Handle<Integer>(),
|
||||
@ -481,7 +521,7 @@ class ScriptOrigin {
|
||||
/**
|
||||
* A compiled javascript script.
|
||||
*/
|
||||
class Script {
|
||||
class EXPORT Script {
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -507,7 +547,7 @@ class Script {
|
||||
/**
|
||||
* An error message.
|
||||
*/
|
||||
class Message {
|
||||
class EXPORT Message {
|
||||
public:
|
||||
Local<String> Get();
|
||||
Local<Value> GetSourceLine();
|
||||
@ -536,7 +576,7 @@ class Message {
|
||||
/**
|
||||
* The superclass of all javascript values and objects.
|
||||
*/
|
||||
class Value : public Data {
|
||||
class EXPORT Value : public Data {
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -632,14 +672,14 @@ class Value : public Data {
|
||||
/**
|
||||
* The superclass of primitive values. See ECMA-262 4.3.2.
|
||||
*/
|
||||
class Primitive : public Value { };
|
||||
class EXPORT Primitive : public Value { };
|
||||
|
||||
|
||||
/**
|
||||
* A primitive boolean value (ECMA-262, 4.3.14). Either the true
|
||||
* or false value.
|
||||
*/
|
||||
class Boolean : public Primitive {
|
||||
class EXPORT Boolean : public Primitive {
|
||||
public:
|
||||
bool Value();
|
||||
static inline Handle<Boolean> New(bool value);
|
||||
@ -649,7 +689,7 @@ class Boolean : public Primitive {
|
||||
/**
|
||||
* A javascript string value (ECMA-262, 4.3.17).
|
||||
*/
|
||||
class String : public Primitive {
|
||||
class EXPORT String : public Primitive {
|
||||
public:
|
||||
int Length();
|
||||
|
||||
@ -690,7 +730,7 @@ class String : public Primitive {
|
||||
* ExternalStringResource to manage the life cycle of the underlying
|
||||
* buffer.
|
||||
*/
|
||||
class ExternalStringResource {
|
||||
class EXPORT ExternalStringResource {
|
||||
public:
|
||||
/**
|
||||
* Override the destructor to manage the life cycle of the underlying
|
||||
@ -715,7 +755,7 @@ class String : public Primitive {
|
||||
* underlying buffer.
|
||||
*/
|
||||
|
||||
class ExternalAsciiStringResource {
|
||||
class EXPORT ExternalAsciiStringResource {
|
||||
public:
|
||||
/**
|
||||
* Override the destructor to manage the life cycle of the underlying
|
||||
@ -794,7 +834,7 @@ class String : public Primitive {
|
||||
* Converts an object to an ascii string.
|
||||
* Useful if you want to print the object.
|
||||
*/
|
||||
class AsciiValue {
|
||||
class EXPORT AsciiValue {
|
||||
public:
|
||||
explicit AsciiValue(Handle<v8::Value> obj);
|
||||
~AsciiValue();
|
||||
@ -806,7 +846,7 @@ class String : public Primitive {
|
||||
/**
|
||||
* Converts an object to a two-byte string.
|
||||
*/
|
||||
class Value {
|
||||
class EXPORT Value {
|
||||
public:
|
||||
explicit Value(Handle<v8::Value> obj);
|
||||
~Value();
|
||||
@ -820,7 +860,7 @@ class String : public Primitive {
|
||||
/**
|
||||
* A javascript number value (ECMA-262, 4.3.20)
|
||||
*/
|
||||
class Number : public Primitive {
|
||||
class EXPORT Number : public Primitive {
|
||||
public:
|
||||
double Value();
|
||||
static Local<Number> New(double value);
|
||||
@ -833,7 +873,7 @@ class Number : public Primitive {
|
||||
/**
|
||||
* A javascript value representing a signed integer.
|
||||
*/
|
||||
class Integer : public Number {
|
||||
class EXPORT Integer : public Number {
|
||||
public:
|
||||
static Local<Integer> New(int32_t value);
|
||||
int64_t Value();
|
||||
@ -846,7 +886,7 @@ class Integer : public Number {
|
||||
/**
|
||||
* A javascript value representing a 32-bit signed integer.
|
||||
*/
|
||||
class Int32 : public Integer {
|
||||
class EXPORT Int32 : public Integer {
|
||||
public:
|
||||
int32_t Value();
|
||||
private:
|
||||
@ -857,7 +897,7 @@ class Int32 : public Integer {
|
||||
/**
|
||||
* A javascript value representing a 32-bit unsigned integer.
|
||||
*/
|
||||
class Uint32 : public Integer {
|
||||
class EXPORT Uint32 : public Integer {
|
||||
public:
|
||||
uint32_t Value();
|
||||
private:
|
||||
@ -868,7 +908,7 @@ class Uint32 : public Integer {
|
||||
/**
|
||||
* An instance of the built-in Date constructor (ECMA-262, 15.9).
|
||||
*/
|
||||
class Date : public Value {
|
||||
class EXPORT Date : public Value {
|
||||
public:
|
||||
static Local<Value> New(double time);
|
||||
};
|
||||
@ -884,7 +924,7 @@ enum PropertyAttribute {
|
||||
/**
|
||||
* A javascript object (ECMA-262, 4.3.3)
|
||||
*/
|
||||
class Object : public Value {
|
||||
class EXPORT Object : public Value {
|
||||
public:
|
||||
bool Set(Handle<Value> key,
|
||||
Handle<Value> value,
|
||||
@ -947,7 +987,7 @@ class Object : public Value {
|
||||
/**
|
||||
* An instance of the built-in array constructor (ECMA-262, 15.4.2).
|
||||
*/
|
||||
class Array : public Object {
|
||||
class EXPORT Array : public Object {
|
||||
public:
|
||||
uint32_t Length();
|
||||
|
||||
@ -961,7 +1001,7 @@ class Array : public Object {
|
||||
/**
|
||||
* A javascript function object (ECMA-262, 15.3).
|
||||
*/
|
||||
class Function : public Object {
|
||||
class EXPORT Function : public Object {
|
||||
public:
|
||||
Local<Object> NewInstance();
|
||||
Local<Object> NewInstance(int argc, Handle<Value> argv[]);
|
||||
@ -979,7 +1019,7 @@ class Function : public Object {
|
||||
* mainly used to associate c++ data structures with javascript
|
||||
* objects.
|
||||
*/
|
||||
class External : public Value {
|
||||
class EXPORT External : public Value {
|
||||
public:
|
||||
static Local<External> New(void* value);
|
||||
static External* Cast(Value* obj);
|
||||
@ -995,7 +1035,7 @@ class External : public Value {
|
||||
/**
|
||||
* The superclass of object and function templates.
|
||||
*/
|
||||
class Template : public Data {
|
||||
class EXPORT Template : public Data {
|
||||
public:
|
||||
/** Adds a property to each instance created by this template.*/
|
||||
void Set(Handle<String> name, Handle<Data> value,
|
||||
@ -1015,7 +1055,7 @@ class Template : public Data {
|
||||
* including the receiver, the number and values of arguments, and
|
||||
* the holder of the function.
|
||||
*/
|
||||
class Arguments {
|
||||
class EXPORT Arguments {
|
||||
public:
|
||||
inline int Length() const;
|
||||
inline Local<Value> operator[](int i) const;
|
||||
@ -1045,7 +1085,7 @@ class Arguments {
|
||||
* The information passed to an accessor callback about the context
|
||||
* of the property access.
|
||||
*/
|
||||
class AccessorInfo {
|
||||
class EXPORT AccessorInfo {
|
||||
public:
|
||||
inline AccessorInfo(Local<Object> self,
|
||||
Local<Value> data,
|
||||
@ -1266,7 +1306,7 @@ typedef bool (*IndexedSecurityCallback)(Local<Object> global,
|
||||
* child_instance.instance_accessor calls InstanceAccessorCallback
|
||||
* child_instance.instance_property == 3;
|
||||
*/
|
||||
class FunctionTemplate : public Template {
|
||||
class EXPORT FunctionTemplate : public Template {
|
||||
public:
|
||||
/** Creates a function template.*/
|
||||
static Local<FunctionTemplate> New(InvocationCallback callback = 0,
|
||||
@ -1338,7 +1378,7 @@ class FunctionTemplate : public Template {
|
||||
/**
|
||||
* ObjectTemplate: (TODO(758124): Add comments.)
|
||||
*/
|
||||
class ObjectTemplate : public Template {
|
||||
class EXPORT ObjectTemplate : public Template {
|
||||
public:
|
||||
static Local<ObjectTemplate> New();
|
||||
/** Creates a new instance of this template.*/
|
||||
@ -1433,7 +1473,7 @@ class ObjectTemplate : public Template {
|
||||
* A function signature which specifies which receivers and arguments
|
||||
* in can legally be called with.
|
||||
*/
|
||||
class Signature : public Data {
|
||||
class EXPORT Signature : public Data {
|
||||
public:
|
||||
static Local<Signature> New(Handle<FunctionTemplate> receiver =
|
||||
Handle<FunctionTemplate>(),
|
||||
@ -1448,7 +1488,7 @@ class Signature : public Data {
|
||||
* A utility for determining the type of objects based on which
|
||||
* template they were constructed from.
|
||||
*/
|
||||
class TypeSwitch : public Data {
|
||||
class EXPORT TypeSwitch : public Data {
|
||||
public:
|
||||
static Local<TypeSwitch> New(Handle<FunctionTemplate> type);
|
||||
static Local<TypeSwitch> New(int argc, Handle<FunctionTemplate> types[]);
|
||||
@ -1464,7 +1504,7 @@ class TypeSwitch : public Data {
|
||||
/**
|
||||
* Ignore
|
||||
*/
|
||||
class Extension {
|
||||
class EXPORT Extension {
|
||||
public:
|
||||
Extension(const char* name,
|
||||
const char* source = 0,
|
||||
@ -1492,13 +1532,13 @@ class Extension {
|
||||
};
|
||||
|
||||
|
||||
void RegisterExtension(Extension* extension);
|
||||
void EXPORT RegisterExtension(Extension* extension);
|
||||
|
||||
|
||||
/**
|
||||
* Ignore
|
||||
*/
|
||||
class DeclareExtension {
|
||||
class EXPORT DeclareExtension {
|
||||
public:
|
||||
inline DeclareExtension(Extension* extension) {
|
||||
RegisterExtension(extension);
|
||||
@ -1509,17 +1549,17 @@ class DeclareExtension {
|
||||
// --- S t a t i c s ---
|
||||
|
||||
|
||||
Handle<Primitive> Undefined();
|
||||
Handle<Primitive> Null();
|
||||
Handle<Boolean> True();
|
||||
Handle<Boolean> False();
|
||||
Handle<Primitive> EXPORT Undefined();
|
||||
Handle<Primitive> EXPORT Null();
|
||||
Handle<Boolean> EXPORT True();
|
||||
Handle<Boolean> EXPORT False();
|
||||
|
||||
|
||||
/**
|
||||
* A set of constraints that specifies the limits of the runtime's
|
||||
* memory use.
|
||||
*/
|
||||
class ResourceConstraints {
|
||||
class EXPORT ResourceConstraints {
|
||||
public:
|
||||
ResourceConstraints();
|
||||
int max_young_space_size() { return max_young_space_size_; }
|
||||
@ -1553,13 +1593,13 @@ typedef void (*MessageCallback)(Handle<Message> message, Handle<Value> data);
|
||||
* operation; the caller must return immediately and only after the exception
|
||||
* has been handled does it become legal to invoke javascript operations.
|
||||
*/
|
||||
Handle<Value> ThrowException(Handle<Value> exception);
|
||||
Handle<Value> EXPORT ThrowException(Handle<Value> exception);
|
||||
|
||||
/**
|
||||
* Create new error objects by calling the corresponding error object
|
||||
* constructor with the message.
|
||||
*/
|
||||
class Exception {
|
||||
class EXPORT Exception {
|
||||
public:
|
||||
static Local<Value> RangeError(Handle<String> message);
|
||||
static Local<Value> ReferenceError(Handle<String> message);
|
||||
@ -1603,7 +1643,7 @@ typedef Persistent<Context> (*ContextGenerator)();
|
||||
/**
|
||||
* Container class for static utility functions.
|
||||
*/
|
||||
class V8 {
|
||||
class EXPORT V8 {
|
||||
public:
|
||||
static void SetFatalErrorHandler(FatalErrorCallback that);
|
||||
|
||||
@ -1711,7 +1751,7 @@ class V8 {
|
||||
/**
|
||||
* An external exception handler.
|
||||
*/
|
||||
class TryCatch {
|
||||
class EXPORT TryCatch {
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -1763,7 +1803,7 @@ class TryCatch {
|
||||
/**
|
||||
* Ignore
|
||||
*/
|
||||
class ExtensionConfiguration {
|
||||
class EXPORT ExtensionConfiguration {
|
||||
public:
|
||||
ExtensionConfiguration(int name_count, const char* names[])
|
||||
: name_count_(name_count), names_(names) { }
|
||||
@ -1778,7 +1818,7 @@ class ExtensionConfiguration {
|
||||
* A sandboxed execution context with its own set of built-in objects
|
||||
* and functions.
|
||||
*/
|
||||
class Context {
|
||||
class EXPORT Context {
|
||||
public:
|
||||
Local<Object> Global();
|
||||
|
||||
@ -1821,7 +1861,7 @@ class Context {
|
||||
* Stack-allocated class which sets the execution context for all
|
||||
* operations executed within a local scope.
|
||||
*/
|
||||
class Scope {
|
||||
class EXPORT Scope {
|
||||
public:
|
||||
inline Scope(Handle<Context> context) : context_(context) {
|
||||
context_->Enter();
|
||||
@ -1901,14 +1941,14 @@ class Context {
|
||||
* }
|
||||
* // V8 Now no longer locked.
|
||||
*/
|
||||
class Unlocker {
|
||||
class EXPORT Unlocker {
|
||||
public:
|
||||
Unlocker();
|
||||
~Unlocker();
|
||||
};
|
||||
|
||||
|
||||
class Locker {
|
||||
class EXPORT Locker {
|
||||
public:
|
||||
Locker();
|
||||
~Locker();
|
||||
@ -2100,6 +2140,7 @@ void Template::Set(const char* name, v8::Handle<Data> value) {
|
||||
|
||||
|
||||
#undef EXPORT
|
||||
#undef EXPORT_INLINE
|
||||
#undef TYPE_CHECK
|
||||
|
||||
|
||||
|
37
samples/SConscript
Normal file
37
samples/SConscript
Normal file
@ -0,0 +1,37 @@
|
||||
# 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.
|
||||
|
||||
from os.path import join
|
||||
Import('sample context')
|
||||
|
||||
def ConfigureObjectFiles():
|
||||
env = Environment()
|
||||
env.Replace(**context.flags['sample'])
|
||||
return env.Object(sample + '.cc')
|
||||
|
||||
sample_object = ConfigureObjectFiles()
|
||||
Return('sample_object')
|
@ -26,6 +26,9 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <v8.h>
|
||||
|
||||
// To avoid warnings from <map> on windows we disable exceptions.
|
||||
#define _HAS_EXCEPTIONS 0
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
|
271
src/SConscript
271
src/SConscript
@ -30,205 +30,36 @@ from os.path import join, dirname, abspath
|
||||
root_dir = dirname(File('SConstruct').rfile().abspath)
|
||||
sys.path.append(join(root_dir, 'tools'))
|
||||
import js2c
|
||||
Import('toolchain arch os mode use_snapshot library_type')
|
||||
Import('context')
|
||||
|
||||
|
||||
BUILD_OPTIONS_MAP = {
|
||||
'gcc': {
|
||||
'debug': {
|
||||
'default': {
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS -g -O0',
|
||||
'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING', 'ENABLE_DISASSEMBLER', 'DEBUG'],
|
||||
'CXXFLAGS': '$CCFLAGS -fno-rtti -fno-exceptions',
|
||||
'DIALECTFLAGS': '-ansi',
|
||||
'LIBS': 'pthread',
|
||||
'WARNINGFLAGS': '-pedantic -Wall -W -Wno-unused-parameter -Werror'
|
||||
},
|
||||
'dtoa': {
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS -g -O0',
|
||||
'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING', 'ENABLE_DISASSEMBLER', 'DEBUG'],
|
||||
'CXXFLAGS': '$CCFLAGS -fno-rtti -fno-exceptions',
|
||||
'DIALECTFLAGS': '-ansi',
|
||||
'LIBS': 'pthread',
|
||||
'WARNINGFLAGS': '-Werror'
|
||||
},
|
||||
'jscre': {
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS -g -O0',
|
||||
'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING', 'ENABLE_DISASSEMBLER', 'DEBUG', 'SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
|
||||
'CXXFLAGS': '$CCFLAGS -fno-rtti -fno-exceptions',
|
||||
'DIALECTFLAGS': '-ansi',
|
||||
'LIBS': 'pthread',
|
||||
'WARNINGFLAGS': '-w'
|
||||
}
|
||||
},
|
||||
'release': {
|
||||
'default': {
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS -O2',
|
||||
'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING'],
|
||||
'CXXFLAGS': '$CCFLAGS -fno-rtti -fno-exceptions',
|
||||
'DIALECTFLAGS': '-ansi',
|
||||
'LIBS': 'pthread',
|
||||
'WARNINGFLAGS': '-pedantic -Wall -W -Wno-unused-parameter -Werror'
|
||||
},
|
||||
'dtoa': {
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS -O2',
|
||||
'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING'],
|
||||
'CXXFLAGS': '$CCFLAGS -fno-rtti -fno-exceptions',
|
||||
'DIALECTFLAGS': '-ansi',
|
||||
'LIBS': 'pthread',
|
||||
'WARNINGFLAGS': '-Werror'
|
||||
},
|
||||
'jscre': {
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS -O2',
|
||||
'CPPDEFINES': ['ENABLE_LOGGING_AND_PROFILING', 'SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
|
||||
'CXXFLAGS': '$CCFLAGS -fno-rtti -fno-exceptions',
|
||||
'DIALECTFLAGS': '-ansi',
|
||||
'LIBS': 'pthread',
|
||||
'WARNINGFLAGS': '-w'
|
||||
}
|
||||
}
|
||||
},
|
||||
'msvc': {
|
||||
'debug': {
|
||||
'default': {
|
||||
'ARFLAGS': '/NOLOGO',
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Od /Gm /MTd',
|
||||
'CCPDBFLAGS': '/Zi',
|
||||
'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER'],
|
||||
'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
|
||||
'DIALECTFLAGS': '/nologo',
|
||||
'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /DEBUG',
|
||||
'PDB': '${TARGET}.pdb',
|
||||
'WARNINGFLAGS': '/W3 /WX /wd4355 /wd4800'
|
||||
},
|
||||
'dtoa': {
|
||||
'ARFLAGS': '/NOLOGO',
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Od /Gm /MTd',
|
||||
'CCPDBFLAGS': '/Zi',
|
||||
'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER'],
|
||||
'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
|
||||
'DIALECTFLAGS': '/nologo',
|
||||
'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /DEBUG',
|
||||
'PDB': '${TARGET}.pdb',
|
||||
'WARNINGFLAGS': '/WX /wd4018 /wd4244'
|
||||
},
|
||||
'jscre': {
|
||||
'ARFLAGS': '/NOLOGO',
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Od /Gm /MTd',
|
||||
'CCPDBFLAGS': '/Zi',
|
||||
'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'DEBUG', '_DEBUG', 'ENABLE_DISASSEMBLER', 'SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
|
||||
'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
|
||||
'DIALECTFLAGS': '/nologo',
|
||||
'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /DEBUG',
|
||||
'PDB': '${TARGET}.pdb',
|
||||
'WARNINGFLAGS': '/W3 /WX /wd4355 /wd4800'
|
||||
}
|
||||
},
|
||||
'release': {
|
||||
'default': {
|
||||
'ARFLAGS': '/NOLOGO',
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Ox /MT /Ob2 /Oi /Oy',
|
||||
'CCPDBFLAGS': '/Zi',
|
||||
'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING'],
|
||||
'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
|
||||
'DIALECTFLAGS': '/nologo',
|
||||
'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /OPT:REF',
|
||||
'PDB': '${TARGET}.pdb',
|
||||
'WARNINGFLAGS': '/W3 /WX /wd4355 /wd4800'
|
||||
},
|
||||
'dtoa': {
|
||||
'ARFLAGS': '/NOLOGO',
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Ox /MT /Ob2 /Oi /Oy',
|
||||
'CCPDBFLAGS': '/Zi',
|
||||
'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING'],
|
||||
'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
|
||||
'DIALECTFLAGS': '/nologo',
|
||||
'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /OPT:REF',
|
||||
'PDB': '${TARGET}.pdb',
|
||||
'WARNINGFLAGS': '/WX /wd4018 /wd4244'
|
||||
},
|
||||
'jscre': {
|
||||
'ARFLAGS': '/NOLOGO',
|
||||
'CCFLAGS': '$DIALECTFLAGS $WARNINGFLAGS /Ox /MT /Ob2 /Oi /Oy',
|
||||
'CCPDBFLAGS': '/Zi',
|
||||
'CPPDEFINES': ['WIN32', '_CRT_SECURE_NO_DEPRECATE', '_CRT_NONSTDC_NO_DEPRECATE', '_USE_32BIT_TIME_T', '_HAS_EXCEPTIONS=0', 'PCRE_STATIC', 'ENABLE_LOGGING_AND_PROFILING', 'SUPPORT_UTF8', 'NO_RECURSE', 'SUPPORT_UCP'],
|
||||
'CXXFLAGS': '$CCFLAGS /GS- /GR- /Gy',
|
||||
'DIALECTFLAGS': '/nologo',
|
||||
'LINKFLAGS': '/NOLOGO /MACHINE:X86 /INCREMENTAL:NO /NXCOMPAT /IGNORE:4221 /OPT:REF',
|
||||
'PDB': '${TARGET}.pdb',
|
||||
'WARNINGFLAGS': '/W3 /WX /wd4355 /wd4800'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PLATFORM_INDEPENDENT_SOURCES = '''
|
||||
accessors.cc
|
||||
allocation.cc
|
||||
api.cc
|
||||
assembler.cc
|
||||
ast.cc
|
||||
bootstrapper.cc
|
||||
builtins.cc
|
||||
checks.cc
|
||||
code-stubs.cc
|
||||
codegen.cc
|
||||
compiler.cc
|
||||
contexts.cc
|
||||
conversions.cc
|
||||
counters.cc
|
||||
dateparser.cc
|
||||
debug.cc
|
||||
disassembler.cc
|
||||
execution.cc
|
||||
factory.cc
|
||||
flags.cc
|
||||
frames.cc
|
||||
global-handles.cc
|
||||
handles.cc
|
||||
hashmap.cc
|
||||
heap.cc
|
||||
ic.cc
|
||||
jsregexp.cc
|
||||
log.cc
|
||||
mark-compact.cc
|
||||
messages.cc
|
||||
objects-debug.cc
|
||||
objects.cc
|
||||
parser.cc
|
||||
prettyprinter.cc
|
||||
property.cc
|
||||
rewriter.cc
|
||||
runtime.cc
|
||||
scanner.cc
|
||||
scopeinfo.cc
|
||||
scopes.cc
|
||||
serialize.cc
|
||||
snapshot-common.cc
|
||||
spaces.cc
|
||||
string-stream.cc
|
||||
stub-cache.cc
|
||||
token.cc
|
||||
top.cc
|
||||
unicode.cc
|
||||
usage-analyzer.cc
|
||||
utils.cc
|
||||
v8-counters.cc
|
||||
v8.cc
|
||||
v8threads.cc
|
||||
variables.cc
|
||||
zone.cc
|
||||
'''.split()
|
||||
|
||||
|
||||
PLATFORM_DEPENDENT_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'],
|
||||
'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'],
|
||||
'os:linux': ['platform-linux.cc'],
|
||||
'os:macos': ['platform-macos.cc'],
|
||||
SOURCES = {
|
||||
'all': [
|
||||
'accessors.cc', 'allocation.cc', 'api.cc', 'assembler.cc', 'ast.cc',
|
||||
'bootstrapper.cc', 'builtins.cc', 'checks.cc', 'code-stubs.cc',
|
||||
'codegen.cc', 'compiler.cc', 'contexts.cc', 'conversions.cc',
|
||||
'counters.cc', 'dateparser.cc', 'debug.cc', 'disassembler.cc',
|
||||
'execution.cc', 'factory.cc', 'flags.cc', 'frames.cc',
|
||||
'global-handles.cc', 'handles.cc', 'hashmap.cc', 'heap.cc', 'ic.cc',
|
||||
'jsregexp.cc', 'log.cc', 'mark-compact.cc', 'messages.cc', 'objects.cc',
|
||||
'parser.cc', 'property.cc', 'rewriter.cc', 'runtime.cc', 'scanner.cc',
|
||||
'scopeinfo.cc', 'scopes.cc', 'serialize.cc', 'snapshot-common.cc',
|
||||
'spaces.cc', 'string-stream.cc', 'stub-cache.cc', 'token.cc', 'top.cc',
|
||||
'unicode.cc', 'usage-analyzer.cc', 'utils.cc', 'v8-counters.cc',
|
||||
'v8.cc', 'v8threads.cc', 'variables.cc', 'zone.cc'
|
||||
],
|
||||
'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'],
|
||||
'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'],
|
||||
'os:linux': ['platform-linux.cc'],
|
||||
'os:macos': ['platform-macos.cc'],
|
||||
'os:nullos': ['platform-nullos.cc'],
|
||||
'os:win32': ['platform-win32.cc']
|
||||
'os:win32': ['platform-win32.cc'],
|
||||
'mode:release': [],
|
||||
'mode:debug': ['objects-debug.cc', 'prettyprinter.cc']
|
||||
}
|
||||
|
||||
|
||||
@ -262,66 +93,50 @@ def Abort(message):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def ConfigureObject(env, input, **kw):
|
||||
if library_type == 'static':
|
||||
return env.StaticObject(input, **kw)
|
||||
elif library_type == 'shared':
|
||||
return env.SharedObject(input, **kw)
|
||||
else:
|
||||
return env.Object(input, **kw)
|
||||
|
||||
|
||||
def ConfigureObjectFiles():
|
||||
env = Environment()
|
||||
options = BUILD_OPTIONS_MAP[toolchain][mode]['default']
|
||||
env.Replace(**options)
|
||||
env.Replace(**context.flags['v8'])
|
||||
env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C)
|
||||
env['BUILDERS']['Snapshot'] = Builder(action='$SOURCE $TARGET --logfile $LOGFILE')
|
||||
|
||||
# Build the standard platform-independent source files.
|
||||
source_files = PLATFORM_INDEPENDENT_SOURCES
|
||||
source_files += PLATFORM_DEPENDENT_SOURCES["arch:%s" % arch]
|
||||
source_files += PLATFORM_DEPENDENT_SOURCES["os:%s" % os]
|
||||
full_source_files = [s for s in source_files]
|
||||
source_files = context.GetRelevantSources(SOURCES)
|
||||
|
||||
# Combine the JavaScript library files into a single C++ file and
|
||||
# compile it.
|
||||
library_files = [s for s in LIBRARY_FILES]
|
||||
library_files.append('macros.py')
|
||||
libraries_src, libraries_empty_src = env.JS2C(['libraries.cc', 'libraries-empty.cc'], library_files)
|
||||
libraries_obj = ConfigureObject(env, libraries_src, CPPPATH=['.'])
|
||||
libraries_obj = context.ConfigureObject(env, libraries_src, CPPPATH=['.'])
|
||||
|
||||
# Build JSCRE.
|
||||
jscre_env = env.Copy()
|
||||
jscre_options = BUILD_OPTIONS_MAP[toolchain][mode]['jscre']
|
||||
jscre_env.Replace(**jscre_options)
|
||||
jscre_env.Replace(**context.flags['jscre'])
|
||||
jscre_files = [join('third_party', 'jscre', s) for s in JSCRE_FILES]
|
||||
jscre_obj = ConfigureObject(jscre_env, jscre_files)
|
||||
jscre_obj = context.ConfigureObject(jscre_env, jscre_files)
|
||||
|
||||
# Build dtoa.
|
||||
dtoa_env = env.Copy()
|
||||
dtoa_options = BUILD_OPTIONS_MAP[toolchain][mode]['dtoa']
|
||||
dtoa_env.Replace(**dtoa_options)
|
||||
dtoa_env.Replace(**context.flags['dtoa'])
|
||||
dtoa_files = ['dtoa-config.c']
|
||||
dtoa_obj = ConfigureObject(dtoa_env, dtoa_files)
|
||||
|
||||
full_source_objs = ConfigureObject(env, full_source_files)
|
||||
non_snapshot_files = [jscre_obj, dtoa_obj, full_source_objs]
|
||||
dtoa_obj = context.ConfigureObject(dtoa_env, dtoa_files)
|
||||
|
||||
source_objs = context.ConfigureObject(env, source_files)
|
||||
non_snapshot_files = [jscre_obj, dtoa_obj, source_objs]
|
||||
|
||||
# Create snapshot if necessary.
|
||||
empty_snapshot_obj = ConfigureObject(env, 'snapshot-empty.cc')
|
||||
if use_snapshot:
|
||||
empty_snapshot_obj = context.ConfigureObject(env, 'snapshot-empty.cc')
|
||||
if context.use_snapshot:
|
||||
mksnapshot_src = 'mksnapshot.cc'
|
||||
mksnapshot = env.Program('mksnapshot', [mksnapshot_src, libraries_obj, non_snapshot_files, empty_snapshot_obj], PDB='mksnapshot.exe.pdb')
|
||||
snapshot_cc = env.Snapshot('snapshot.cc', mksnapshot, LOGFILE=File('snapshot.log').abspath)
|
||||
snapshot_obj = ConfigureObject(env, snapshot_cc, CPPPATH=['.'])
|
||||
libraries_obj = ConfigureObject(env, libraries_empty_src, CPPPATH=['.'])
|
||||
snapshot_obj = context.ConfigureObject(env, snapshot_cc, CPPPATH=['.'])
|
||||
libraries_obj = context.ConfigureObject(env, libraries_empty_src, CPPPATH=['.'])
|
||||
else:
|
||||
snapshot_obj = empty_snapshot_obj
|
||||
|
||||
# Return all the object files needed to link the library.
|
||||
return [non_snapshot_files, libraries_obj, snapshot_obj]
|
||||
|
||||
|
||||
object_files = ConfigureObjectFiles()
|
||||
Return('object_files')
|
||||
library_objects = ConfigureObjectFiles()
|
||||
Return('library_objects')
|
||||
|
@ -2098,7 +2098,7 @@ bool v8::V8::Initialize() {
|
||||
|
||||
|
||||
const char* v8::V8::GetVersion() {
|
||||
return "0.2.3";
|
||||
return "0.2.4 (internal)";
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "v8.h"
|
||||
|
||||
#include "assembler-arm-inl.h"
|
||||
#include "serialize.h"
|
||||
|
||||
namespace v8 { namespace internal {
|
||||
|
||||
@ -1443,6 +1444,12 @@ void Assembler::RecordRelocInfo(RelocMode rmode, intptr_t data) {
|
||||
BlockConstPoolBefore(pc_offset() + kInstrSize);
|
||||
}
|
||||
if (rinfo.rmode() != no_reloc) {
|
||||
// Don't record external references unless the heap will be serialized.
|
||||
if (rmode == external_reference &&
|
||||
!Serializer::enabled() &&
|
||||
!FLAG_debug_code) {
|
||||
return;
|
||||
}
|
||||
ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
|
||||
reloc_info_writer.Write(&rinfo);
|
||||
}
|
||||
|
13
src/ast.h
13
src/ast.h
@ -660,12 +660,10 @@ class ObjectLiteral: public MaterializedLiteral {
|
||||
};
|
||||
|
||||
ObjectLiteral(Handle<FixedArray> constant_properties,
|
||||
Expression* result,
|
||||
ZoneList<Property*>* properties,
|
||||
int literal_index)
|
||||
: MaterializedLiteral(literal_index),
|
||||
constant_properties_(constant_properties),
|
||||
result_(result),
|
||||
properties_(properties) {
|
||||
}
|
||||
|
||||
@ -674,12 +672,10 @@ class ObjectLiteral: public MaterializedLiteral {
|
||||
Handle<FixedArray> constant_properties() const {
|
||||
return constant_properties_;
|
||||
}
|
||||
Expression* result() const { return result_; }
|
||||
ZoneList<Property*>* properties() const { return properties_; }
|
||||
|
||||
private:
|
||||
Handle<FixedArray> constant_properties_;
|
||||
Expression* result_;
|
||||
ZoneList<Property*>* properties_;
|
||||
};
|
||||
|
||||
@ -709,20 +705,17 @@ class RegExpLiteral: public MaterializedLiteral {
|
||||
class ArrayLiteral: public Expression {
|
||||
public:
|
||||
ArrayLiteral(Handle<FixedArray> literals,
|
||||
Expression* result,
|
||||
ZoneList<Expression*>* values)
|
||||
: literals_(literals), result_(result), values_(values) {
|
||||
: literals_(literals), values_(values) {
|
||||
}
|
||||
|
||||
virtual void Accept(Visitor* v);
|
||||
|
||||
Handle<FixedArray> literals() const { return literals_; }
|
||||
Expression* result() const { return result_; }
|
||||
ZoneList<Expression*>* values() const { return values_; }
|
||||
|
||||
private:
|
||||
Handle<FixedArray> literals_;
|
||||
Expression* result_;
|
||||
ZoneList<Expression*>* values_;
|
||||
};
|
||||
|
||||
@ -1119,6 +1112,7 @@ class FunctionLiteral: public Expression {
|
||||
Scope* scope,
|
||||
ZoneList<Statement*>* body,
|
||||
int materialized_literal_count,
|
||||
bool contains_array_literal,
|
||||
int expected_property_count,
|
||||
int num_parameters,
|
||||
int start_position,
|
||||
@ -1128,6 +1122,7 @@ class FunctionLiteral: public Expression {
|
||||
scope_(scope),
|
||||
body_(body),
|
||||
materialized_literal_count_(materialized_literal_count),
|
||||
contains_array_literal_(contains_array_literal),
|
||||
expected_property_count_(expected_property_count),
|
||||
num_parameters_(num_parameters),
|
||||
start_position_(start_position),
|
||||
@ -1151,6 +1146,7 @@ class FunctionLiteral: public Expression {
|
||||
bool is_expression() const { return is_expression_; }
|
||||
|
||||
int materialized_literal_count() { return materialized_literal_count_; }
|
||||
bool contains_array_literal() { return contains_array_literal_; }
|
||||
int expected_property_count() { return expected_property_count_; }
|
||||
int num_parameters() { return num_parameters_; }
|
||||
|
||||
@ -1161,6 +1157,7 @@ class FunctionLiteral: public Expression {
|
||||
Scope* scope_;
|
||||
ZoneList<Statement*>* body_;
|
||||
int materialized_literal_count_;
|
||||
bool contains_array_literal_;
|
||||
int expected_property_count_;
|
||||
int num_parameters_;
|
||||
int start_position_;
|
||||
|
@ -553,9 +553,11 @@ void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
|
||||
// Set the global context for the global object.
|
||||
object->set_global_context(*global_context());
|
||||
|
||||
// Security setup. Set the security token of the global object to
|
||||
// itself.
|
||||
object->set_security_token(*object);
|
||||
// Security setup: Set the security token of the global object to
|
||||
// its global context. This makes the security check between two
|
||||
// different contexts fail by default even in case of global
|
||||
// object reinitialization.
|
||||
object->set_security_token(*global_context());
|
||||
|
||||
{ // --- G l o b a l C o n t e x t ---
|
||||
// use the empty function as closure (no scope info)
|
||||
@ -766,8 +768,8 @@ bool Genesis::CompileScriptCached(Vector<const char> name,
|
||||
ASSERT(Top::context()->IsGlobalContext());
|
||||
Handle<Context> context =
|
||||
Handle<Context>(use_runtime_context
|
||||
? Top::context()->runtime_context()
|
||||
: Top::context());
|
||||
? Top::context()->runtime_context()
|
||||
: Top::context());
|
||||
Handle<JSFunction> fun =
|
||||
Factory::NewFunctionFromBoilerplate(boilerplate, context);
|
||||
|
||||
@ -775,8 +777,8 @@ bool Genesis::CompileScriptCached(Vector<const char> name,
|
||||
// object as the receiver. Provide no parameters.
|
||||
Handle<Object> receiver =
|
||||
Handle<Object>(use_runtime_context
|
||||
? Top::context()->builtins()
|
||||
: Top::context()->global());
|
||||
? Top::context()->builtins()
|
||||
: Top::context()->global());
|
||||
bool has_pending_exception;
|
||||
Handle<Object> result =
|
||||
Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
|
||||
|
@ -101,7 +101,6 @@ namespace v8 { namespace internal {
|
||||
V(ADD, 1) \
|
||||
V(SUB, 1) \
|
||||
V(MUL, 1) \
|
||||
V(MULNEG, 1) \
|
||||
V(DIV, 1) \
|
||||
V(MOD, 1) \
|
||||
V(INC, 0) \
|
||||
|
@ -1922,19 +1922,16 @@ void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
|
||||
case Token::SHR:
|
||||
case Token::SAR: {
|
||||
Label slow, exit;
|
||||
__ pop(r1); // get y
|
||||
__ pop(r0); // get x
|
||||
__ 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);
|
||||
// get copies of operands
|
||||
__ mov(r3, Operand(r0));
|
||||
__ mov(r2, Operand(r1));
|
||||
// remove tags from operands (but keep sign)
|
||||
__ mov(r3, Operand(r3, ASR, kSmiTagSize));
|
||||
__ mov(r2, Operand(r2, ASR, kSmiTagSize));
|
||||
__ 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
|
||||
@ -1971,8 +1968,8 @@ void ArmCodeGenerator::GenericBinaryOperation(Token::Value op) {
|
||||
__ b(&exit);
|
||||
// slow case
|
||||
__ bind(&slow);
|
||||
__ push(r0); // restore stack
|
||||
__ push(r1);
|
||||
__ 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;
|
||||
@ -2176,7 +2173,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
|
||||
// Slow-case: Non-function called.
|
||||
masm->bind(&slow);
|
||||
masm->mov(r0, Operand(argc_)); // Setup the number of arguments.
|
||||
masm->InvokeBuiltin("CALL_NON_FUNCTION", 0, JUMP_JS);
|
||||
masm->InvokeBuiltin("CALL_NON_FUNCTION", argc_, JUMP_JS);
|
||||
}
|
||||
|
||||
|
||||
@ -3354,8 +3351,24 @@ void ArmCodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
|
||||
void ArmCodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
// Load the resulting object.
|
||||
Load(node->result());
|
||||
|
||||
// Call runtime to create the array literal.
|
||||
__ mov(r0, Operand(node->literals()));
|
||||
__ push(r0);
|
||||
// TODO(1332579): The second argument to CreateArrayLiteral is
|
||||
// supposed to be the literals array of the function of this frame.
|
||||
// Until the new ARM calling convention is in place, that function
|
||||
// is not always available. Therefore, on ARM we pass in the hole
|
||||
// until the new calling convention is in place.
|
||||
__ mov(r0, Operand(Factory::the_hole_value()));
|
||||
__ push(r0);
|
||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 2);
|
||||
|
||||
// Push the resulting array literal on the stack.
|
||||
__ push(r0);
|
||||
|
||||
// Generate code to set the elements in the array that are not
|
||||
// literals.
|
||||
for (int i = 0; i < node->values()->length(); i++) {
|
||||
Expression* value = node->values()->at(i);
|
||||
|
||||
|
@ -189,8 +189,6 @@ class Ia32CodeGenerator: public CodeGenerator {
|
||||
void UnloadReference(Reference* ref);
|
||||
friend class Reference;
|
||||
|
||||
bool TryDeferNegate(Expression* x);
|
||||
|
||||
// State
|
||||
bool has_cc() const { return cc_reg_ >= 0; }
|
||||
CodeGenState::AccessType access() const { return state_->access(); }
|
||||
@ -256,8 +254,7 @@ class Ia32CodeGenerator: public CodeGenerator {
|
||||
|
||||
void GenericBinaryOperation(
|
||||
Token::Value op,
|
||||
const OverwriteMode overwrite_mode = NO_OVERWRITE,
|
||||
bool negate_result = false);
|
||||
const OverwriteMode overwrite_mode = NO_OVERWRITE);
|
||||
void Comparison(Condition cc, bool strict = false);
|
||||
|
||||
void SmiComparison(Condition cc, Handle<Object> value, bool strict = false);
|
||||
@ -1080,35 +1077,31 @@ class FloatingPointHelper : public AllStatic {
|
||||
|
||||
class GenericBinaryOpStub: public CodeStub {
|
||||
public:
|
||||
GenericBinaryOpStub(Token::Value op, OverwriteMode mode, bool negate_result)
|
||||
: op_(op), mode_(mode), negate_result_(negate_result) { }
|
||||
GenericBinaryOpStub(Token::Value op, OverwriteMode mode)
|
||||
: op_(op), mode_(mode) { }
|
||||
|
||||
private:
|
||||
Token::Value op_;
|
||||
OverwriteMode mode_;
|
||||
bool negate_result_;
|
||||
|
||||
const char* GetName();
|
||||
|
||||
#ifdef DEBUG
|
||||
void Print() {
|
||||
PrintF("GenericBinaryOpStub (op %s), (mode %d), (negate_result %s)\n",
|
||||
PrintF("GenericBinaryOpStub (op %s), (mode %d)\n",
|
||||
Token::String(op_),
|
||||
static_cast<int>(mode_),
|
||||
negate_result_ ? "true" : "false");
|
||||
static_cast<int>(mode_));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Minor key encoding in 16 bits OOOOOOOOOOOOOMMN.
|
||||
class NegateBits: public BitField<bool, 0, 1> {};
|
||||
class ModeBits: public BitField<OverwriteMode, 1, 2> {};
|
||||
class OpBits: public BitField<Token::Value, 3, 13> {};
|
||||
// Minor key encoding in 16 bits OOOOOOOOOOOOOOMM.
|
||||
class ModeBits: public BitField<OverwriteMode, 0, 2> {};
|
||||
class OpBits: public BitField<Token::Value, 2, 14> {};
|
||||
|
||||
Major MajorKey() { return GenericBinaryOp; }
|
||||
int MinorKey() {
|
||||
// Encode the three parameters in a unique 16 bit value.
|
||||
return NegateBits::encode(negate_result_) |
|
||||
OpBits::encode(op_) |
|
||||
// Encode the parameters in a unique 16 bit value.
|
||||
return OpBits::encode(op_) |
|
||||
ModeBits::encode(mode_);
|
||||
}
|
||||
void Generate(MacroAssembler* masm);
|
||||
@ -1134,7 +1127,6 @@ const char* GenericBinaryOpStub::GetName() {
|
||||
|
||||
void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
|
||||
Label call_runtime;
|
||||
if (negate_result_ && op_ != Token::MUL) UNIMPLEMENTED();
|
||||
__ mov(eax, Operand(esp, 1 * kPointerSize)); // Get y.
|
||||
__ mov(edx, Operand(esp, 2 * kPointerSize)); // Get x.
|
||||
|
||||
@ -1209,13 +1201,6 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
|
||||
__ j(overflow, &non_smi_result, not_taken);
|
||||
// ...but operands OK for float arithmetic.
|
||||
|
||||
if (negate_result_) {
|
||||
__ xor_(ecx, Operand(ecx));
|
||||
__ sub(ecx, Operand(eax));
|
||||
// Go slow on overflows.
|
||||
__ j(overflow, &non_smi_result, not_taken);
|
||||
__ mov(eax, Operand(ecx));
|
||||
}
|
||||
// If the result is +0 we may need to check if the result should
|
||||
// really be -0. Welcome to the -0 fan club.
|
||||
__ NegativeZeroTest(eax, ebx, edx, ecx, &non_smi_result);
|
||||
@ -1355,7 +1340,6 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
|
||||
case Token::DIV: __ fdivp(1); break;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
if (negate_result_) __ fchs();
|
||||
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
||||
__ ret(2 * kPointerSize);
|
||||
}
|
||||
@ -1468,9 +1452,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
|
||||
__ InvokeBuiltin(Builtins::SUB, JUMP_FUNCTION);
|
||||
break;
|
||||
case Token::MUL:
|
||||
__ InvokeBuiltin(negate_result_ ? Builtins::MULNEG
|
||||
: Builtins::MUL,
|
||||
JUMP_FUNCTION);
|
||||
__ InvokeBuiltin(Builtins::MUL, JUMP_FUNCTION);
|
||||
break;
|
||||
case Token::DIV:
|
||||
__ InvokeBuiltin(Builtins::DIV, JUMP_FUNCTION);
|
||||
@ -1588,10 +1570,11 @@ void UnarySubStub::Generate(MacroAssembler* masm) {
|
||||
Label undo;
|
||||
Label slow;
|
||||
Label done;
|
||||
Label try_float;
|
||||
|
||||
// Enter runtime system if the value is not a smi.
|
||||
// Check whether the value is a smi.
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
__ j(not_zero, &slow, not_taken);
|
||||
__ j(not_zero, &try_float, not_taken);
|
||||
|
||||
// Enter runtime system if the value of the expression is zero
|
||||
// to make sure that we switch between 0 and -0.
|
||||
@ -1609,7 +1592,7 @@ void UnarySubStub::Generate(MacroAssembler* masm) {
|
||||
__ test(eax, Immediate(kSmiTagMask));
|
||||
__ j(zero, &done, taken);
|
||||
|
||||
// Undo optimistic sub and enter runtime system.
|
||||
// Restore eax and enter runtime system.
|
||||
__ bind(&undo);
|
||||
__ mov(eax, Operand(edx));
|
||||
|
||||
@ -1620,6 +1603,19 @@ void UnarySubStub::Generate(MacroAssembler* masm) {
|
||||
__ push(ecx); // push return address
|
||||
__ InvokeBuiltin(Builtins::UNARY_MINUS, JUMP_FUNCTION);
|
||||
|
||||
// Try floating point case.
|
||||
__ bind(&try_float);
|
||||
__ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
|
||||
__ cmp(edx, Factory::heap_number_map());
|
||||
__ j(not_equal, &slow);
|
||||
__ mov(edx, Operand(eax));
|
||||
// edx: operand
|
||||
FloatingPointHelper::AllocateHeapNumber(masm, &undo, ebx, ecx);
|
||||
// eax: allocated 'empty' number
|
||||
__ fld_d(FieldOperand(edx, HeapNumber::kValueOffset));
|
||||
__ fchs();
|
||||
__ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
|
||||
|
||||
__ bind(&done);
|
||||
|
||||
masm->StubReturn(1);
|
||||
@ -1725,18 +1721,16 @@ void ArgumentsAccessStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op,
|
||||
OverwriteMode overwrite_mode,
|
||||
bool negate_result) {
|
||||
OverwriteMode overwrite_mode) {
|
||||
Comment cmnt(masm_, "[ BinaryOperation");
|
||||
Comment cmnt_token(masm_, Token::String(op));
|
||||
if (negate_result && op != Token::MUL) UNIMPLEMENTED();
|
||||
switch (op) {
|
||||
case Token::ADD:
|
||||
case Token::SUB:
|
||||
case Token::MUL:
|
||||
case Token::DIV:
|
||||
case Token::MOD: {
|
||||
GenericBinaryOpStub stub(op, overwrite_mode, negate_result);
|
||||
GenericBinaryOpStub stub(op, overwrite_mode);
|
||||
__ CallStub(&stub);
|
||||
__ push(eax);
|
||||
break;
|
||||
@ -1763,7 +1757,7 @@ void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op,
|
||||
__ bind(&slow);
|
||||
__ push(edx); // restore stack slots
|
||||
__ push(eax);
|
||||
GenericBinaryOpStub stub(op, overwrite_mode, false);
|
||||
GenericBinaryOpStub stub(op, overwrite_mode);
|
||||
__ CallStub(&stub);
|
||||
__ bind(&exit);
|
||||
__ push(eax); // push the result to the stack
|
||||
@ -1821,7 +1815,7 @@ void Ia32CodeGenerator::GenericBinaryOperation(Token::Value op,
|
||||
__ bind(&slow);
|
||||
__ push(eax); // restore stack
|
||||
__ push(edx);
|
||||
GenericBinaryOpStub stub(op, overwrite_mode, false);
|
||||
GenericBinaryOpStub stub(op, overwrite_mode);
|
||||
__ CallStub(&stub);
|
||||
__ bind(&exit);
|
||||
__ push(eax);
|
||||
@ -1851,7 +1845,7 @@ class DeferredInlinedSmiOperation: public DeferredCode {
|
||||
virtual void Generate() {
|
||||
__ push(eax);
|
||||
__ push(Immediate(Smi::FromInt(value_)));
|
||||
GenericBinaryOpStub igostub(op_, overwrite_mode_, false);
|
||||
GenericBinaryOpStub igostub(op_, overwrite_mode_);
|
||||
__ CallStub(&igostub);
|
||||
}
|
||||
|
||||
@ -1874,7 +1868,7 @@ class DeferredInlinedSmiOperationReversed: public DeferredCode {
|
||||
virtual void Generate() {
|
||||
__ push(Immediate(Smi::FromInt(value_)));
|
||||
__ push(eax);
|
||||
GenericBinaryOpStub igostub(op_, overwrite_mode_, false);
|
||||
GenericBinaryOpStub igostub(op_, overwrite_mode_);
|
||||
__ CallStub(&igostub);
|
||||
}
|
||||
|
||||
@ -1899,7 +1893,7 @@ class DeferredInlinedSmiAdd: public DeferredCode {
|
||||
__ sub(Operand(eax), immediate);
|
||||
__ push(eax);
|
||||
__ push(immediate);
|
||||
GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, false);
|
||||
GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_);
|
||||
__ CallStub(&igostub);
|
||||
}
|
||||
|
||||
@ -1923,7 +1917,7 @@ class DeferredInlinedSmiAddReversed: public DeferredCode {
|
||||
__ sub(Operand(eax), immediate);
|
||||
__ push(immediate);
|
||||
__ push(eax);
|
||||
GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, false);
|
||||
GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_);
|
||||
__ CallStub(&igostub);
|
||||
}
|
||||
|
||||
@ -1947,7 +1941,7 @@ class DeferredInlinedSmiSub: public DeferredCode {
|
||||
__ add(Operand(eax), immediate);
|
||||
__ push(eax);
|
||||
__ push(immediate);
|
||||
GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, false);
|
||||
GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_);
|
||||
__ CallStub(&igostub);
|
||||
}
|
||||
|
||||
@ -1973,7 +1967,7 @@ class DeferredInlinedSmiSubReversed: public DeferredCode {
|
||||
__ add(eax, Operand(tos_reg_));
|
||||
__ push(eax);
|
||||
__ push(Operand(tos_reg_));
|
||||
GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, false);
|
||||
GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_);
|
||||
__ CallStub(&igostub);
|
||||
}
|
||||
|
||||
@ -2971,9 +2965,6 @@ void Ia32CodeGenerator::VisitForInStatement(ForInStatement* node) {
|
||||
__ mov(eax, Operand(esp, 0 * kPointerSize)); // load the current count
|
||||
__ cmp(eax, Operand(esp, kPointerSize)); // compare to the array length
|
||||
__ j(above_equal, &cleanup);
|
||||
// TODO(1222589): remove redundant load here, which is only needed in
|
||||
// PUSH_TOS/POP_TOS mode
|
||||
__ mov(eax, Operand(esp, 0 * kPointerSize)); // load the current count
|
||||
|
||||
// Get the i'th entry of the array.
|
||||
__ mov(edx, Operand(esp, 2 * kPointerSize));
|
||||
@ -3668,8 +3659,21 @@ void Ia32CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
|
||||
void Ia32CodeGenerator::VisitArrayLiteral(ArrayLiteral* node) {
|
||||
Comment cmnt(masm_, "[ ArrayLiteral");
|
||||
// Load the resulting object.
|
||||
Load(node->result());
|
||||
|
||||
// Call runtime to create the array literal.
|
||||
__ push(Immediate(node->literals()));
|
||||
// Load the function of this frame.
|
||||
__ mov(ecx, FunctionOperand());
|
||||
// Load the literals array of the function.
|
||||
__ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
|
||||
__ push(ecx);
|
||||
__ CallRuntime(Runtime::kCreateArrayLiteral, 2);
|
||||
|
||||
// Push the resulting array literal on the stack.
|
||||
__ push(eax);
|
||||
|
||||
// Generate code to set the elements in the array that are not
|
||||
// literals.
|
||||
for (int i = 0; i < node->values()->length(); i++) {
|
||||
Expression* value = node->values()->at(i);
|
||||
|
||||
@ -4578,20 +4582,6 @@ void Ia32CodeGenerator::VisitCountOperation(CountOperation* node) {
|
||||
}
|
||||
|
||||
|
||||
// Returns 'true' if able to defer negation to the consuming arithmetic
|
||||
// operation.
|
||||
bool Ia32CodeGenerator::TryDeferNegate(Expression* x) {
|
||||
UnaryOperation* unary = x->AsUnaryOperation();
|
||||
if (FLAG_defer_negation && unary != NULL && unary->op() == Token::SUB) {
|
||||
Load(unary->expression());
|
||||
return true;
|
||||
} else {
|
||||
Load(x);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ia32CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
|
||||
Comment cmnt(masm_, "[ BinaryOperation");
|
||||
Token::Value op = node->op();
|
||||
@ -4706,16 +4696,9 @@ void Ia32CodeGenerator::VisitBinaryOperation(BinaryOperation* node) {
|
||||
SmiOperation(node->op(), lliteral->handle(), true, overwrite_mode);
|
||||
|
||||
} else {
|
||||
bool negate_result = false;
|
||||
if (node->op() == Token::MUL) { // Implement only MUL for starters
|
||||
bool left_negated = TryDeferNegate(node->left());
|
||||
bool right_negated = TryDeferNegate(node->right());
|
||||
negate_result = left_negated != right_negated;
|
||||
} else {
|
||||
Load(node->left());
|
||||
Load(node->right());
|
||||
}
|
||||
GenericBinaryOperation(node->op(), overwrite_mode, negate_result);
|
||||
Load(node->left());
|
||||
Load(node->right());
|
||||
GenericBinaryOperation(node->op(), overwrite_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5207,7 +5190,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
|
||||
// CopyRegistersFromStackToMemory() but it isn't! esp is assumed
|
||||
// correct here, but computed for the other call. Very error
|
||||
// prone! FIX THIS. Actually there are deeper problems with
|
||||
// register saving than this assymetry (see the buganizer report
|
||||
// register saving than this assymetry (see the bug report
|
||||
// associated with this issue).
|
||||
__ PushRegistersFromMemory(kJSCallerSaved);
|
||||
}
|
||||
|
@ -129,6 +129,7 @@ Handle<JSFunction> CodeGenerator::BuildBoilerplate(FunctionLiteral* node) {
|
||||
Handle<JSFunction> function =
|
||||
Factory::NewFunctionBoilerplate(node->name(),
|
||||
node->materialized_literal_count(),
|
||||
node->contains_array_literal(),
|
||||
code);
|
||||
CodeGenerator::SetFunctionInfo(function, node->num_parameters(),
|
||||
node->function_token_position(),
|
||||
|
@ -158,6 +158,7 @@ static Handle<JSFunction> MakeFunction(bool is_global,
|
||||
Handle<JSFunction> fun =
|
||||
Factory::NewFunctionBoilerplate(lit->name(),
|
||||
lit->materialized_literal_count(),
|
||||
lit->contains_array_literal(),
|
||||
code);
|
||||
|
||||
CodeGenerator::SetFunctionInfo(fun, lit->scope()->num_parameters(),
|
||||
|
@ -172,7 +172,7 @@ BreakPoint.prototype.isTriggered = function(exec_state) {
|
||||
if (this.condition()) {
|
||||
// If break point has condition try to evaluate it in the top frame.
|
||||
try {
|
||||
var mirror = exec_state.GetFrame(0).evaluate(this.condition());
|
||||
var mirror = exec_state.frame(0).evaluate(this.condition());
|
||||
// If no sensible mirror or non true value break point not triggered.
|
||||
if (!(mirror instanceof ValueMirror) || !%ToBoolean(mirror.value_)) {
|
||||
return false;
|
||||
@ -394,7 +394,7 @@ Debug.removeListener = function(listener) {
|
||||
%RemoveDebugEventListener(listener);
|
||||
};
|
||||
|
||||
Debug.Break = function(f) {
|
||||
Debug.breakExecution = function(f) {
|
||||
%Break();
|
||||
};
|
||||
|
||||
@ -710,14 +710,15 @@ ExecutionState.prototype.prepareStep = function(opt_action, opt_count) {
|
||||
}
|
||||
|
||||
ExecutionState.prototype.evaluateGlobal = function(source, disable_break) {
|
||||
return %DebugEvaluateGlobal(this.break_id, source, Boolean(disable_break));
|
||||
return MakeMirror(
|
||||
%DebugEvaluateGlobal(this.break_id, source, Boolean(disable_break)));
|
||||
};
|
||||
|
||||
ExecutionState.prototype.GetFrameCount = function() {
|
||||
ExecutionState.prototype.frameCount = function() {
|
||||
return %GetFrameCount(this.break_id);
|
||||
};
|
||||
|
||||
ExecutionState.prototype.GetFrame = function(opt_index) {
|
||||
ExecutionState.prototype.frame = function(opt_index) {
|
||||
// If no index supplied return the selected frame.
|
||||
if (opt_index == null) opt_index = this.selected_frame;
|
||||
return new FrameMirror(this.break_id, opt_index);
|
||||
@ -729,11 +730,11 @@ ExecutionState.prototype.cframesValue = function(opt_from_index, opt_to_index) {
|
||||
|
||||
ExecutionState.prototype.setSelectedFrame = function(index) {
|
||||
var i = %ToNumber(index);
|
||||
if (i < 0 || i >= this.GetFrameCount()) throw new Error('Illegal frame index.');
|
||||
if (i < 0 || i >= this.frameCount()) throw new Error('Illegal frame index.');
|
||||
this.selected_frame = i;
|
||||
};
|
||||
|
||||
ExecutionState.prototype.getSelectedFrame = function() {
|
||||
ExecutionState.prototype.selectedFrame = function() {
|
||||
return this.selected_frame;
|
||||
};
|
||||
|
||||
@ -754,22 +755,22 @@ function BreakEvent(exec_state, break_points_hit) {
|
||||
|
||||
|
||||
BreakEvent.prototype.func = function() {
|
||||
return this.exec_state_.GetFrame(0).func();
|
||||
return this.exec_state_.frame(0).func();
|
||||
};
|
||||
|
||||
|
||||
BreakEvent.prototype.sourceLine = function() {
|
||||
return this.exec_state_.GetFrame(0).sourceLine();
|
||||
return this.exec_state_.frame(0).sourceLine();
|
||||
};
|
||||
|
||||
|
||||
BreakEvent.prototype.sourceColumn = function() {
|
||||
return this.exec_state_.GetFrame(0).sourceColumn();
|
||||
return this.exec_state_.frame(0).sourceColumn();
|
||||
};
|
||||
|
||||
|
||||
BreakEvent.prototype.sourceLineText = function() {
|
||||
return this.exec_state_.GetFrame(0).sourceLineText();
|
||||
return this.exec_state_.frame(0).sourceLineText();
|
||||
};
|
||||
|
||||
|
||||
@ -797,12 +798,12 @@ BreakEvent.prototype.details = function() {
|
||||
details += 'break';
|
||||
}
|
||||
details += ' in ';
|
||||
details += this.exec_state_.GetFrame(0).invocationText();
|
||||
details += this.exec_state_.frame(0).invocationText();
|
||||
details += ' at ';
|
||||
details += this.exec_state_.GetFrame(0).sourceAndPositionText();
|
||||
details += this.exec_state_.frame(0).sourceAndPositionText();
|
||||
details += '\n'
|
||||
if (this.func().script()) {
|
||||
details += FrameSourceUnderline(this.exec_state_.GetFrame(0));
|
||||
details += FrameSourceUnderline(this.exec_state_.frame(0));
|
||||
}
|
||||
return details;
|
||||
};
|
||||
@ -822,7 +823,7 @@ BreakEvent.prototype.toJSONProtocol = function() {
|
||||
var o = { seq: next_response_seq++,
|
||||
type: "event",
|
||||
event: "break",
|
||||
body: { invocationText: this.exec_state_.GetFrame(0).invocationText(),
|
||||
body: { invocationText: this.exec_state_.frame(0).invocationText(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -876,22 +877,22 @@ ExceptionEvent.prototype.uncaught = function() {
|
||||
}
|
||||
|
||||
ExceptionEvent.prototype.func = function() {
|
||||
return this.exec_state_.GetFrame(0).func();
|
||||
return this.exec_state_.frame(0).func();
|
||||
};
|
||||
|
||||
|
||||
ExceptionEvent.prototype.sourceLine = function() {
|
||||
return this.exec_state_.GetFrame(0).sourceLine();
|
||||
return this.exec_state_.frame(0).sourceLine();
|
||||
};
|
||||
|
||||
|
||||
ExceptionEvent.prototype.sourceColumn = function() {
|
||||
return this.exec_state_.GetFrame(0).sourceColumn();
|
||||
return this.exec_state_.frame(0).sourceColumn();
|
||||
};
|
||||
|
||||
|
||||
ExceptionEvent.prototype.sourceLineText = function() {
|
||||
return this.exec_state_.GetFrame(0).sourceLineText();
|
||||
return this.exec_state_.frame(0).sourceLineText();
|
||||
};
|
||||
|
||||
|
||||
@ -906,9 +907,9 @@ ExceptionEvent.prototype.details = function() {
|
||||
details += '"';
|
||||
details += MakeMirror(this.exception_).toText();
|
||||
details += '" at ';
|
||||
details += this.exec_state_.GetFrame(0).sourceAndPositionText();
|
||||
details += this.exec_state_.frame(0).sourceAndPositionText();
|
||||
details += '\n';
|
||||
details += FrameSourceUnderline(this.exec_state_.GetFrame(0));
|
||||
details += FrameSourceUnderline(this.exec_state_.frame(0));
|
||||
|
||||
return details;
|
||||
};
|
||||
@ -1201,11 +1202,11 @@ DebugCommandProcessor.prototype.sourceCommandToJSONRequest_ = function(args) {
|
||||
|
||||
// Request source arround current source location.
|
||||
request.arguments = {};
|
||||
request.arguments.fromLine = this.exec_state_.GetFrame().sourceLine() - before;
|
||||
request.arguments.fromLine = this.exec_state_.frame().sourceLine() - before;
|
||||
if (request.arguments.fromLine < 0) {
|
||||
request.arguments.fromLine = 0
|
||||
}
|
||||
request.arguments.toLine = this.exec_state_.GetFrame().sourceLine() + after + 1;
|
||||
request.arguments.toLine = this.exec_state_.frame().sourceLine() + after + 1;
|
||||
|
||||
return request.toJSONProtocol();
|
||||
};
|
||||
@ -1610,7 +1611,7 @@ DebugCommandProcessor.prototype.setBreakPointRequest_ =
|
||||
var f;
|
||||
try {
|
||||
// Find the function through a global evaluate.
|
||||
f = this.exec_state_.evaluateGlobal(target);
|
||||
f = this.exec_state_.evaluateGlobal(target).value();
|
||||
} catch (e) {
|
||||
response.failed('Error: "' + %ToString(e) +
|
||||
'" evaluating "' + target + '"');
|
||||
@ -1718,7 +1719,7 @@ DebugCommandProcessor.prototype.clearBreakPointRequest_ = function(request, resp
|
||||
|
||||
DebugCommandProcessor.prototype.backtraceRequest_ = function(request, response) {
|
||||
// Get the number of frames.
|
||||
var total_frames = this.exec_state_.GetFrameCount();
|
||||
var total_frames = this.exec_state_.frameCount();
|
||||
|
||||
// Default frame range to include in backtrace.
|
||||
var from_index = 0
|
||||
@ -1747,7 +1748,7 @@ DebugCommandProcessor.prototype.backtraceRequest_ = function(request, response)
|
||||
// Create the response body.
|
||||
var frames = [];
|
||||
for (var i = from_index; i < to_index; i++) {
|
||||
frames.push(this.exec_state_.GetFrame(i));
|
||||
frames.push(this.exec_state_.frame(i));
|
||||
}
|
||||
response.body = {
|
||||
fromFrame: from_index,
|
||||
@ -1768,7 +1769,7 @@ DebugCommandProcessor.prototype.frameRequest_ = function(request, response) {
|
||||
if (request.arguments && request.arguments.number >= 0) {
|
||||
this.exec_state_.setSelectedFrame(request.arguments.number);
|
||||
}
|
||||
response.body = this.exec_state_.GetFrame();
|
||||
response.body = this.exec_state_.frame();
|
||||
};
|
||||
|
||||
|
||||
@ -1799,8 +1800,8 @@ DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
|
||||
// Global evaluate.
|
||||
if (global) {
|
||||
// Evaluate in the global context.
|
||||
response.body = MakeMirror(
|
||||
this.exec_state_.evaluateGlobal(expression), Boolean(disable_break));
|
||||
response.body =
|
||||
this.exec_state_.evaluateGlobal(expression), Boolean(disable_break);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1812,16 +1813,16 @@ DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
|
||||
// Check whether a frame was specified.
|
||||
if (!IS_UNDEFINED(frame)) {
|
||||
var frame_number = %ToNumber(frame);
|
||||
if (frame_number < 0 || frame_number >= this.exec_state_.GetFrameCount()) {
|
||||
if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
|
||||
return response.failed('Invalid frame "' + frame + '"');
|
||||
}
|
||||
// Evaluate in the specified frame.
|
||||
response.body = this.exec_state_.GetFrame(frame_number).evaluate(
|
||||
response.body = this.exec_state_.frame(frame_number).evaluate(
|
||||
expression, Boolean(disable_break));
|
||||
return;
|
||||
} else {
|
||||
// Evaluate in the selected frame.
|
||||
response.body = this.exec_state_.GetFrame().evaluate(
|
||||
response.body = this.exec_state_.frame().evaluate(
|
||||
expression, Boolean(disable_break));
|
||||
return;
|
||||
}
|
||||
@ -1831,7 +1832,7 @@ DebugCommandProcessor.prototype.evaluateRequest_ = function(request, response) {
|
||||
DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
|
||||
var from_line;
|
||||
var to_line;
|
||||
var frame = this.exec_state_.GetFrame();
|
||||
var frame = this.exec_state_.frame();
|
||||
if (request.arguments) {
|
||||
// Pull out arguments.
|
||||
from_line = request.arguments.fromLine;
|
||||
@ -1839,10 +1840,10 @@ DebugCommandProcessor.prototype.sourceRequest_ = function(request, response) {
|
||||
|
||||
if (!IS_UNDEFINED(request.arguments.frame)) {
|
||||
var frame_number = %ToNumber(request.arguments.frame);
|
||||
if (frame_number < 0 || frame_number >= this.exec_state_.GetFrameCount()) {
|
||||
if (frame_number < 0 || frame_number >= this.exec_state_.frameCount()) {
|
||||
return response.failed('Invalid frame "' + frame + '"');
|
||||
}
|
||||
frame = this.exec_state_.GetFrame(frame_number);
|
||||
frame = this.exec_state_.frame(frame_number);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,12 +198,21 @@ Handle<JSFunction> Factory::NewFunctionFromBoilerplate(
|
||||
Handle<JSFunction> result =
|
||||
BaseNewFunctionFromBoilerplate(boilerplate, Top::function_map());
|
||||
result->set_context(*context);
|
||||
int number_of_literals = boilerplate->literals()->length();
|
||||
int number_of_literals = boilerplate->NumberOfLiterals();
|
||||
Handle<FixedArray> literals =
|
||||
Factory::NewFixedArray(number_of_literals, TENURED);
|
||||
if (number_of_literals > 0) {
|
||||
Handle<FixedArray> literals =
|
||||
Factory::NewFixedArray(number_of_literals, TENURED);
|
||||
result->set_literals(*literals);
|
||||
// Store the object, regexp and array functions in the literals
|
||||
// array prefix. These functions will be used when creating
|
||||
// object, regexp and array literals in this function.
|
||||
literals->set(JSFunction::kLiteralObjectFunctionIndex,
|
||||
context->global_context()->object_function());
|
||||
literals->set(JSFunction::kLiteralRegExpFunctionIndex,
|
||||
context->global_context()->regexp_function());
|
||||
literals->set(JSFunction::kLiteralArrayFunctionIndex,
|
||||
context->global_context()->array_function());
|
||||
}
|
||||
result->set_literals(*literals);
|
||||
ASSERT(!result->IsBoilerplate());
|
||||
return result;
|
||||
}
|
||||
@ -370,16 +379,20 @@ Handle<JSFunction> Factory::NewFunction(Handle<String> name,
|
||||
|
||||
Handle<JSFunction> Factory::NewFunctionBoilerplate(Handle<String> name,
|
||||
int number_of_literals,
|
||||
bool contains_array_literal,
|
||||
Handle<Code> code) {
|
||||
Handle<JSFunction> function = NewFunctionBoilerplate(name);
|
||||
function->set_code(*code);
|
||||
if (number_of_literals > 0) {
|
||||
Handle<FixedArray> literals =
|
||||
Factory::NewFixedArray(number_of_literals, TENURED);
|
||||
function->set_literals(*literals);
|
||||
} else {
|
||||
function->set_literals(Heap::empty_fixed_array());
|
||||
int literals_array_size = number_of_literals;
|
||||
// If the function contains object, regexp or array literals,
|
||||
// allocate extra space for a literals array prefix containing the
|
||||
// object, regexp and array constructor functions.
|
||||
if (number_of_literals > 0 || contains_array_literal) {
|
||||
literals_array_size += JSFunction::kLiteralsPrefixSize;
|
||||
}
|
||||
Handle<FixedArray> literals =
|
||||
Factory::NewFixedArray(literals_array_size, TENURED);
|
||||
function->set_literals(*literals);
|
||||
ASSERT(!function->has_initial_map());
|
||||
ASSERT(!function->has_prototype());
|
||||
return function;
|
||||
|
@ -237,6 +237,7 @@ class Factory : public AllStatic {
|
||||
|
||||
static Handle<JSFunction> NewFunctionBoilerplate(Handle<String> name,
|
||||
int number_of_literals,
|
||||
bool contains_array_literal,
|
||||
Handle<Code> code);
|
||||
|
||||
static Handle<JSFunction> NewFunctionBoilerplate(Handle<String> name);
|
||||
|
@ -202,7 +202,7 @@ class RelocInfo;
|
||||
class Deserializer;
|
||||
class MessageLocation;
|
||||
class ObjectGroup;
|
||||
struct TickSample;
|
||||
class TickSample;
|
||||
class VirtualMemory;
|
||||
class Mutex;
|
||||
|
||||
|
@ -1628,9 +1628,8 @@ Object* Heap::AllocateFunction(Map* function_map,
|
||||
|
||||
|
||||
Object* Heap::AllocateArgumentsObject(Object* callee, int length) {
|
||||
// This allocation is odd since allocate an argument object
|
||||
// based on the arguments_boilerplate.
|
||||
// We do this to ensure fast allocation and map sharing.
|
||||
// To get fast allocation and map sharing for arguments objects we
|
||||
// allocate them based on an arguments boilerplate.
|
||||
|
||||
// This calls Copy directly rather than using Heap::AllocateRaw so we
|
||||
// duplicate the check here.
|
||||
|
@ -85,18 +85,19 @@ void RegExpImpl::OldSpaceCollectionPrologue() {
|
||||
}
|
||||
|
||||
|
||||
Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<String> pattern,
|
||||
Handle<Object> RegExpImpl::CreateRegExpLiteral(Handle<JSFunction> constructor,
|
||||
Handle<String> pattern,
|
||||
Handle<String> flags,
|
||||
bool* has_pending_exception) {
|
||||
// Ensure that RegExp has been loaded.
|
||||
if (!Top::regexp_function()->IsLoaded()) {
|
||||
LoadLazy(Top::regexp_function(), has_pending_exception);
|
||||
// Ensure that the constructor function has been loaded.
|
||||
if (!constructor->IsLoaded()) {
|
||||
LoadLazy(constructor, has_pending_exception);
|
||||
if (*has_pending_exception) return Handle<Object>(Failure::Exception());
|
||||
}
|
||||
// Call the construct code with 2 arguments.
|
||||
Object** argv[2] = { Handle<Object>::cast(pattern).location(),
|
||||
Handle<Object>::cast(flags).location() };
|
||||
return Execution::New(Top::regexp_function(), 2, argv, has_pending_exception);
|
||||
return Execution::New(constructor, 2, argv, has_pending_exception);
|
||||
}
|
||||
|
||||
|
||||
|
@ -34,7 +34,8 @@ class RegExpImpl {
|
||||
public:
|
||||
// Creates a regular expression literal in the old space.
|
||||
// This function calls the garbage collector if necessary.
|
||||
static Handle<Object> CreateRegExpLiteral(Handle<String> pattern,
|
||||
static Handle<Object> CreateRegExpLiteral(Handle<JSFunction> constructor,
|
||||
Handle<String> pattern,
|
||||
Handle<String> flags,
|
||||
bool* has_pending_exception);
|
||||
|
||||
|
@ -144,16 +144,16 @@ class Profiler: public Thread {
|
||||
// Ticker used to provide ticks to the profiler and the sliding state
|
||||
// window.
|
||||
//
|
||||
class Ticker: public ProfileSampler {
|
||||
class Ticker: public Sampler {
|
||||
public:
|
||||
explicit Ticker(int interval):
|
||||
ProfileSampler(interval), window_(NULL), profiler_(NULL) {}
|
||||
Sampler(interval, FLAG_prof), window_(NULL), profiler_(NULL) {}
|
||||
|
||||
~Ticker() { if (IsActive()) Stop(); }
|
||||
|
||||
void Tick(TickSample* sample) {
|
||||
if (profiler_) profiler_->Insert(sample);
|
||||
if (window_) window_->AddState(Logger::state());
|
||||
if (window_) window_->AddState(sample->state);
|
||||
}
|
||||
|
||||
void SetWindow(SlidingStateWindow* window) {
|
||||
|
@ -231,7 +231,7 @@ function MakeError(type, args) {
|
||||
Script.prototype.initSourceInfo_ = function () {
|
||||
// Just return if initialized.
|
||||
if (this.lineEnds_) return;
|
||||
|
||||
|
||||
// Collect all line endings.
|
||||
this.lineEnds_ = [];
|
||||
for (var i = 0; i < this.source.length; i++) {
|
||||
@ -240,7 +240,7 @@ Script.prototype.initSourceInfo_ = function () {
|
||||
this.lineEnds_.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If the script does not end with a line ending add the final end position
|
||||
// as just past the last line ending.
|
||||
if (this.lineEnds_[this.lineEnds_.length - 1] != this.source.length - 1) {
|
||||
@ -258,7 +258,7 @@ Script.prototype.initSourceInfo_ = function () {
|
||||
Script.prototype.locationFromPosition = function (position) {
|
||||
// Make sure source info has been initialized.
|
||||
this.initSourceInfo_();
|
||||
|
||||
|
||||
var lineCount = this.lineCount();
|
||||
var line = -1;
|
||||
if (position <= this.lineEnds_[0]) {
|
||||
@ -271,9 +271,9 @@ Script.prototype.locationFromPosition = function (position) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (line == -1) return null;
|
||||
|
||||
|
||||
// Determine start, end and column.
|
||||
var start = line == 0 ? 0 : this.lineEnds_[line - 1] + 1;
|
||||
var end = this.lineEnds_[line];
|
||||
@ -314,7 +314,7 @@ Script.prototype.locationFromLine = function (opt_line, opt_column, opt_offset_p
|
||||
if (!IS_UNDEFINED(opt_line)) {
|
||||
line = opt_line - this.line_offset;
|
||||
}
|
||||
|
||||
|
||||
// Default is first column. If on the first line add the offset within the
|
||||
// resource.
|
||||
var column = opt_column || 0;
|
||||
|
@ -25,6 +25,8 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// To avoid warnings from <map> on windows we disable exceptions.
|
||||
#define _HAS_EXCEPTIONS 0
|
||||
#include <signal.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -918,6 +918,10 @@ void JSObject::JSObjectIterateBody(int object_size, ObjectVisitor* v) {
|
||||
|
||||
|
||||
Object* JSObject::Copy(PretenureFlag pretenure) {
|
||||
// Never used to copy functions. If functions need to be copied we
|
||||
// have to be careful to clear the literals array.
|
||||
ASSERT(!IsJSFunction());
|
||||
|
||||
// Copy the elements and properties.
|
||||
Object* elem = FixedArray::cast(elements())->Copy();
|
||||
if (elem->IsFailure()) return elem;
|
||||
@ -935,11 +939,6 @@ Object* JSObject::Copy(PretenureFlag pretenure) {
|
||||
JSObject::cast(clone)->set_elements(FixedArray::cast(elem));
|
||||
JSObject::cast(clone)->set_properties(FixedArray::cast(prop));
|
||||
|
||||
// NOTE: Copy is only used for copying objects and functions from
|
||||
// boilerplates. This means if we have a function the prototype is
|
||||
// not present.
|
||||
ASSERT(!IsJSFunction() || !JSFunction::cast(clone)->has_prototype());
|
||||
|
||||
// Return the new clone.
|
||||
return clone;
|
||||
}
|
||||
|
@ -2568,6 +2568,14 @@ class JSFunction: public JSObject {
|
||||
inline bool IsLoaded();
|
||||
|
||||
// [literals]: Fixed array holding the materialized literals.
|
||||
//
|
||||
// If the function contains object, regexp or array literals, the
|
||||
// literals array prefix contains the object, regexp, and array
|
||||
// function to be used when creating these literals. This is
|
||||
// necessary so that we do not dynamically lookup the object, regexp
|
||||
// or array functions. Performing a dynamic lookup, we might end up
|
||||
// using the functions from a new context that we should not have
|
||||
// access to.
|
||||
DECL_ACCESSORS(literals, FixedArray)
|
||||
|
||||
// The initial map for an object created by this constructor.
|
||||
@ -2620,6 +2628,12 @@ class JSFunction: public JSObject {
|
||||
static const int kLiteralsOffset = kContextOffset + kPointerSize;
|
||||
static const int kSize = kLiteralsOffset + kPointerSize;
|
||||
|
||||
// Layout of the literals array.
|
||||
static const int kLiteralsPrefixSize = 3;
|
||||
static const int kLiteralObjectFunctionIndex = 0;
|
||||
static const int kLiteralRegExpFunctionIndex = 1;
|
||||
static const int kLiteralArrayFunctionIndex = 2;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(JSFunction);
|
||||
};
|
||||
|
@ -232,17 +232,32 @@ class TemporaryScope BASE_EMBEDDED {
|
||||
public:
|
||||
explicit TemporaryScope(Parser* parser);
|
||||
~TemporaryScope();
|
||||
int NextMaterializedLiteralIndex() { return materialized_literal_count_++; }
|
||||
void AddProperty() { expected_property_count_++; }
|
||||
|
||||
int NextMaterializedLiteralIndex() {
|
||||
int next_index =
|
||||
materialized_literal_count_ + JSFunction::kLiteralsPrefixSize;
|
||||
materialized_literal_count_++;
|
||||
return next_index;
|
||||
}
|
||||
int materialized_literal_count() { return materialized_literal_count_; }
|
||||
|
||||
void set_contains_array_literal() { contains_array_literal_ = true; }
|
||||
bool contains_array_literal() { return contains_array_literal_; }
|
||||
|
||||
void AddProperty() { expected_property_count_++; }
|
||||
int expected_property_count() { return expected_property_count_; }
|
||||
private:
|
||||
// Captures the number of nodes that need materialization in the
|
||||
// function. regexp literals, boilerplate for array literals, and
|
||||
// boilerplate for object literals.
|
||||
// function. regexp literals, and boilerplate for object literals.
|
||||
int materialized_literal_count_;
|
||||
|
||||
// Captures whether or not the function contains array literals. If
|
||||
// the function contains array literals, we have to allocate space
|
||||
// for the array constructor in the literals array of the function.
|
||||
// This array constructor is used when creating the actual array
|
||||
// literals.
|
||||
bool contains_array_literal_;
|
||||
|
||||
// Properties count estimation.
|
||||
int expected_property_count_;
|
||||
|
||||
@ -256,6 +271,7 @@ class TemporaryScope BASE_EMBEDDED {
|
||||
|
||||
TemporaryScope::TemporaryScope(Parser* parser)
|
||||
: materialized_literal_count_(0),
|
||||
contains_array_literal_(false),
|
||||
expected_property_count_(0),
|
||||
parser_(parser),
|
||||
parent_(parser->temp_scope_) {
|
||||
@ -695,7 +711,7 @@ Parser::Parser(Handle<Script> script,
|
||||
|
||||
bool Parser::PreParseProgram(unibrow::CharacterStream* stream) {
|
||||
StatsRateScope timer(&Counters::pre_parse);
|
||||
|
||||
StackGuard guard;
|
||||
AssertNoZoneAllocation assert_no_zone_allocation;
|
||||
AssertNoAllocation assert_no_allocation;
|
||||
NoHandleAllocation no_handle_allocation;
|
||||
@ -744,6 +760,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source,
|
||||
result = NEW(FunctionLiteral(no_name, top_scope_,
|
||||
body.elements(),
|
||||
temp_scope.materialized_literal_count(),
|
||||
temp_scope.contains_array_literal(),
|
||||
temp_scope.expected_property_count(),
|
||||
0, 0, source->length(), false));
|
||||
} else if (scanner().stack_overflow()) {
|
||||
@ -1109,7 +1126,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
||||
const int literals = fun->NumberOfLiterals();
|
||||
Handle<Code> code = Handle<Code>(fun->shared()->code());
|
||||
Handle<JSFunction> boilerplate =
|
||||
Factory::NewFunctionBoilerplate(name, literals, code);
|
||||
Factory::NewFunctionBoilerplate(name, literals, false, code);
|
||||
|
||||
// Copy the function data to the boilerplate. Used by
|
||||
// builtins.cc:HandleApiCall to perform argument type checks and to
|
||||
@ -1699,13 +1716,10 @@ Expression* Parser::MakeCatchContext(Handle<String> id, VariableProxy* value) {
|
||||
Handle<FixedArray> constant_properties = Factory::empty_fixed_array();
|
||||
ZoneList<Expression*>* arguments = new ZoneList<Expression*>(1);
|
||||
arguments->Add(new Literal(constant_properties));
|
||||
Expression* literal = new CallRuntime(
|
||||
Factory::CreateObjectLiteralBoilerplate_symbol(),
|
||||
Runtime::FunctionForId(Runtime::kCreateObjectLiteralBoilerplate),
|
||||
arguments);
|
||||
|
||||
return new ObjectLiteral(constant_properties, literal,
|
||||
properties.elements(), literal_index);
|
||||
return new ObjectLiteral(constant_properties,
|
||||
properties.elements(),
|
||||
literal_index);
|
||||
}
|
||||
|
||||
|
||||
@ -2602,7 +2616,11 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
|
||||
}
|
||||
}
|
||||
Expect(Token::RBRACK, CHECK_OK);
|
||||
if (values.elements() == NULL) return NULL;
|
||||
|
||||
// Update the scope information before the pre-parsing bailout.
|
||||
temp_scope_->set_contains_array_literal();
|
||||
|
||||
if (is_pre_parsing_) return NULL;
|
||||
|
||||
// Allocate a fixed array with all the literals.
|
||||
Handle<FixedArray> literals =
|
||||
@ -2618,16 +2636,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the expression for calling Runtime::CreateArray
|
||||
// with the literal array as argument.
|
||||
ZoneList<Expression*>* arguments = new ZoneList<Expression*>(1);
|
||||
arguments->Add(NEW(Literal(literals)));
|
||||
Expression* result =
|
||||
NEW(CallRuntime(Factory::CreateArrayLiteral_symbol(),
|
||||
Runtime::FunctionForId(Runtime::kCreateArrayLiteral),
|
||||
arguments));
|
||||
|
||||
return NEW(ArrayLiteral(literals, result, values.elements()));
|
||||
return NEW(ArrayLiteral(literals, values.elements()));
|
||||
}
|
||||
|
||||
|
||||
@ -2736,13 +2745,9 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
|
||||
// with the literal array as argument.
|
||||
ZoneList<Expression*>* arguments = new ZoneList<Expression*>(1);
|
||||
arguments->Add(new Literal(constant_properties));
|
||||
Expression* result =
|
||||
new CallRuntime(
|
||||
Factory::CreateObjectLiteralBoilerplate_symbol(),
|
||||
Runtime::FunctionForId(Runtime::kCreateObjectLiteralBoilerplate),
|
||||
arguments);
|
||||
return new ObjectLiteral(constant_properties, result,
|
||||
properties.elements(), literal_index);
|
||||
return new ObjectLiteral(constant_properties,
|
||||
properties.elements(),
|
||||
literal_index);
|
||||
}
|
||||
|
||||
|
||||
@ -2864,6 +2869,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
||||
|
||||
int materialized_literal_count;
|
||||
int expected_property_count;
|
||||
bool contains_array_literal;
|
||||
if (is_lazily_compiled && pre_data() != NULL) {
|
||||
FunctionEntry entry = pre_data()->GetFunctionEnd(start_pos);
|
||||
int end_pos = entry.end_pos();
|
||||
@ -2871,10 +2877,12 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
||||
scanner_.SeekForward(end_pos);
|
||||
materialized_literal_count = entry.literal_count();
|
||||
expected_property_count = entry.property_count();
|
||||
contains_array_literal = entry.contains_array_literal();
|
||||
} else {
|
||||
ParseSourceElements(&body, Token::RBRACE, CHECK_OK);
|
||||
materialized_literal_count = temp_scope.materialized_literal_count();
|
||||
expected_property_count = temp_scope.expected_property_count();
|
||||
contains_array_literal = temp_scope.contains_array_literal();
|
||||
}
|
||||
|
||||
Expect(Token::RBRACE, CHECK_OK);
|
||||
@ -2885,12 +2893,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
|
||||
entry.set_end_pos(end_pos);
|
||||
entry.set_literal_count(materialized_literal_count);
|
||||
entry.set_property_count(expected_property_count);
|
||||
entry.set_contains_array_literal(contains_array_literal);
|
||||
}
|
||||
|
||||
FunctionLiteral *function_literal =
|
||||
NEW(FunctionLiteral(name, top_scope_,
|
||||
body.elements(), materialized_literal_count,
|
||||
expected_property_count,
|
||||
contains_array_literal, expected_property_count,
|
||||
num_parameters, start_pos, end_pos,
|
||||
function_name->length() > 0));
|
||||
if (!is_pre_parsing_) {
|
||||
@ -3159,7 +3168,7 @@ unsigned* ScriptDataImpl::Data() {
|
||||
|
||||
|
||||
ScriptDataImpl* PreParse(unibrow::CharacterStream* stream,
|
||||
v8::Extension* extension) {
|
||||
v8::Extension* extension) {
|
||||
Handle<Script> no_script;
|
||||
bool allow_natives_syntax =
|
||||
always_allow_natives_syntax ||
|
||||
|
10
src/parser.h
10
src/parser.h
@ -68,9 +68,16 @@ class FunctionEntry BASE_EMBEDDED {
|
||||
int property_count() { return backing_[kPropertyCountOffset]; }
|
||||
void set_property_count(int value) { backing_[kPropertyCountOffset] = value; }
|
||||
|
||||
bool contains_array_literal() {
|
||||
return backing_[kContainsArrayLiteralOffset] != 0;
|
||||
}
|
||||
void set_contains_array_literal(bool value) {
|
||||
backing_[kContainsArrayLiteralOffset] = value ? 1 : 0;
|
||||
}
|
||||
|
||||
bool is_valid() { return backing_.length() > 0; }
|
||||
|
||||
static const int kSize = 4;
|
||||
static const int kSize = 5;
|
||||
|
||||
private:
|
||||
Vector<unsigned> backing_;
|
||||
@ -78,6 +85,7 @@ class FunctionEntry BASE_EMBEDDED {
|
||||
static const int kEndPosOffset = 1;
|
||||
static const int kLiteralCountOffset = 2;
|
||||
static const int kPropertyCountOffset = 3;
|
||||
static const int kContainsArrayLiteralOffset = 4;
|
||||
};
|
||||
|
||||
|
||||
|
@ -552,31 +552,37 @@ Semaphore* OS::CreateSemaphore(int count) {
|
||||
|
||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||
|
||||
static ProfileSampler* active_sampler_ = NULL;
|
||||
static Sampler* active_sampler_ = NULL;
|
||||
|
||||
static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
|
||||
USE(info);
|
||||
if (signal != SIGPROF) return;
|
||||
if (active_sampler_ == NULL) return;
|
||||
|
||||
// Extracting the sample from the context is extremely machine dependent.
|
||||
TickSample sample;
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
mcontext_t& mcontext = ucontext->uc_mcontext;
|
||||
|
||||
// If profiling, we extract the current pc and sp.
|
||||
if (active_sampler_->IsProfiling()) {
|
||||
// Extracting the sample from the context is extremely machine dependent.
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
mcontext_t& mcontext = ucontext->uc_mcontext;
|
||||
#if defined (__arm__) || defined(__thumb__)
|
||||
sample.pc = mcontext.gregs[R15];
|
||||
sample.sp = mcontext.gregs[R13];
|
||||
sample.pc = mcontext.gregs[R15];
|
||||
sample.sp = mcontext.gregs[R13];
|
||||
#else
|
||||
sample.pc = mcontext.gregs[REG_EIP];
|
||||
sample.sp = mcontext.gregs[REG_ESP];
|
||||
sample.pc = mcontext.gregs[REG_EIP];
|
||||
sample.sp = mcontext.gregs[REG_ESP];
|
||||
#endif
|
||||
}
|
||||
|
||||
// We always sample the VM state.
|
||||
sample.state = Logger::state();
|
||||
|
||||
if (active_sampler_ == NULL) return;
|
||||
active_sampler_->Tick(&sample);
|
||||
}
|
||||
|
||||
|
||||
class ProfileSampler::PlatformData : public Malloced {
|
||||
class Sampler::PlatformData : public Malloced {
|
||||
public:
|
||||
PlatformData() {
|
||||
signal_handler_installed_ = false;
|
||||
@ -588,19 +594,18 @@ class ProfileSampler::PlatformData : public Malloced {
|
||||
};
|
||||
|
||||
|
||||
ProfileSampler::ProfileSampler(int interval) {
|
||||
Sampler::Sampler(int interval, bool profiling)
|
||||
: interval_(interval), profiling_(profiling), active_(false) {
|
||||
data_ = new PlatformData();
|
||||
interval_ = interval;
|
||||
active_ = false;
|
||||
}
|
||||
|
||||
|
||||
ProfileSampler::~ProfileSampler() {
|
||||
Sampler::~Sampler() {
|
||||
delete data_;
|
||||
}
|
||||
|
||||
|
||||
void ProfileSampler::Start() {
|
||||
void Sampler::Start() {
|
||||
// There can only be one active sampler at the time on POSIX
|
||||
// platforms.
|
||||
if (active_sampler_ != NULL) return;
|
||||
@ -627,7 +632,7 @@ void ProfileSampler::Start() {
|
||||
}
|
||||
|
||||
|
||||
void ProfileSampler::Stop() {
|
||||
void Sampler::Stop() {
|
||||
// Restore old signal handler
|
||||
if (data_->signal_handler_installed_) {
|
||||
setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
|
||||
|
@ -515,31 +515,37 @@ Semaphore* OS::CreateSemaphore(int count) {
|
||||
|
||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||
|
||||
static ProfileSampler* active_sampler_ = NULL;
|
||||
static Sampler* active_sampler_ = NULL;
|
||||
|
||||
static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
|
||||
USE(info);
|
||||
if (signal != SIGPROF) return;
|
||||
if (active_sampler_ == NULL) return;
|
||||
|
||||
// Extracting the sample from the context is extremely machine dependent.
|
||||
TickSample sample;
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
mcontext_t& mcontext = ucontext->uc_mcontext;
|
||||
|
||||
// If profiling, we extract the current pc and sp.
|
||||
if (active_sampler_->IsProfiling()) {
|
||||
// Extracting the sample from the context is extremely machine dependent.
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
mcontext_t& mcontext = ucontext->uc_mcontext;
|
||||
#if __DARWIN_UNIX03
|
||||
sample.pc = mcontext->__ss.__eip;
|
||||
sample.sp = mcontext->__ss.__esp;
|
||||
sample.pc = mcontext->__ss.__eip;
|
||||
sample.sp = mcontext->__ss.__esp;
|
||||
#else // !__DARWIN_UNIX03
|
||||
sample.pc = mcontext->ss.eip;
|
||||
sample.sp = mcontext->ss.esp;
|
||||
sample.pc = mcontext->ss.eip;
|
||||
sample.sp = mcontext->ss.esp;
|
||||
#endif // __DARWIN_UNIX03
|
||||
}
|
||||
|
||||
// We always sample the VM state.
|
||||
sample.state = Logger::state();
|
||||
|
||||
if (active_sampler_ == NULL) return;
|
||||
active_sampler_->Tick(&sample);
|
||||
}
|
||||
|
||||
|
||||
class ProfileSampler::PlatformData : public Malloced {
|
||||
class Sampler::PlatformData : public Malloced {
|
||||
public:
|
||||
PlatformData() {
|
||||
signal_handler_installed_ = false;
|
||||
@ -551,19 +557,18 @@ class ProfileSampler::PlatformData : public Malloced {
|
||||
};
|
||||
|
||||
|
||||
ProfileSampler::ProfileSampler(int interval) {
|
||||
Sampler::Sampler(int interval, bool profiling)
|
||||
: interval_(interval), profiling_(profiling), active_(false) {
|
||||
data_ = new PlatformData();
|
||||
interval_ = interval;
|
||||
active_ = false;
|
||||
}
|
||||
|
||||
|
||||
ProfileSampler::~ProfileSampler() {
|
||||
Sampler::~Sampler() {
|
||||
delete data_;
|
||||
}
|
||||
|
||||
|
||||
void ProfileSampler::Start() {
|
||||
void Sampler::Start() {
|
||||
// There can only be one active sampler at the time on POSIX
|
||||
// platforms.
|
||||
if (active_sampler_ != NULL) return;
|
||||
@ -590,7 +595,7 @@ void ProfileSampler::Start() {
|
||||
}
|
||||
|
||||
|
||||
void ProfileSampler::Stop() {
|
||||
void Sampler::Stop() {
|
||||
// Restore old signal handler
|
||||
if (data_->signal_handler_installed_) {
|
||||
setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
|
||||
|
@ -1424,15 +1424,15 @@ Semaphore* OS::CreateSemaphore(int count) {
|
||||
// On win32 we use a sampler thread with high priority to sample the program
|
||||
// counter for the profiled thread.
|
||||
|
||||
class ProfileSampler::PlatformData : public Malloced {
|
||||
class Sampler::PlatformData : public Malloced {
|
||||
public:
|
||||
explicit PlatformData(ProfileSampler* sampler) {
|
||||
explicit PlatformData(Sampler* sampler) {
|
||||
sampler_ = sampler;
|
||||
sampler_thread_ = INVALID_HANDLE_VALUE;
|
||||
profiled_thread_ = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
ProfileSampler* sampler_;
|
||||
Sampler* sampler_;
|
||||
HANDLE sampler_thread_;
|
||||
HANDLE profiled_thread_;
|
||||
|
||||
@ -1443,18 +1443,24 @@ class ProfileSampler::PlatformData : public Malloced {
|
||||
memset(&context, 0, sizeof(context));
|
||||
// Loop until the sampler is disengaged.
|
||||
while (sampler_->IsActive()) {
|
||||
// Pause the profiled thread and get its context.
|
||||
SuspendThread(profiled_thread_);
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
GetThreadContext(profiled_thread_, &context);
|
||||
ResumeThread(profiled_thread_);
|
||||
|
||||
// Invoke tick handler with program counter and stack pointer.
|
||||
TickSample sample;
|
||||
sample.pc = context.Eip;
|
||||
sample.sp = context.Esp;
|
||||
|
||||
// If profiling, we record the pc and sp of the profiled thread.
|
||||
if (sampler_->IsProfiling()) {
|
||||
// Pause the profiled thread and get its context.
|
||||
SuspendThread(profiled_thread_);
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
GetThreadContext(profiled_thread_, &context);
|
||||
ResumeThread(profiled_thread_);
|
||||
// Invoke tick handler with program counter and stack pointer.
|
||||
sample.pc = context.Eip;
|
||||
sample.sp = context.Esp;
|
||||
}
|
||||
|
||||
// We always sample the VM state.
|
||||
sample.state = Logger::state();
|
||||
sampler_->Tick(&sample);
|
||||
|
||||
// Wait until next sampling.
|
||||
Sleep(sampler_->interval_);
|
||||
}
|
||||
@ -1463,51 +1469,54 @@ class ProfileSampler::PlatformData : public Malloced {
|
||||
|
||||
|
||||
// Entry point for sampler thread.
|
||||
static unsigned int __stdcall ProfileSamplerEntry(void* arg) {
|
||||
ProfileSampler::PlatformData* data =
|
||||
reinterpret_cast<ProfileSampler::PlatformData*>(arg);
|
||||
static unsigned int __stdcall SamplerEntry(void* arg) {
|
||||
Sampler::PlatformData* data =
|
||||
reinterpret_cast<Sampler::PlatformData*>(arg);
|
||||
data->Runner();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Initialize a profile sampler.
|
||||
ProfileSampler::ProfileSampler(int interval) {
|
||||
Sampler::Sampler(int interval, bool profiling)
|
||||
: interval_(interval), profiling_(profiling), active_(false) {
|
||||
data_ = new PlatformData(this);
|
||||
interval_ = interval;
|
||||
active_ = false;
|
||||
}
|
||||
|
||||
|
||||
ProfileSampler::~ProfileSampler() {
|
||||
Sampler::~Sampler() {
|
||||
delete data_;
|
||||
}
|
||||
|
||||
|
||||
// Start profiling.
|
||||
void ProfileSampler::Start() {
|
||||
// Get a handle to the calling thread. This is the thread that we are
|
||||
// going to profile. We need to duplicate the handle because we are
|
||||
// going to use it in the samler thread. using GetThreadHandle() will
|
||||
// not work in this case.
|
||||
BOOL ok = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
|
||||
GetCurrentProcess(), &data_->profiled_thread_,
|
||||
THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME |
|
||||
THREAD_QUERY_INFORMATION, FALSE, 0);
|
||||
if (!ok) return;
|
||||
void Sampler::Start() {
|
||||
// If we are profiling, we need to be able to access the calling
|
||||
// thread.
|
||||
if (IsProfiling()) {
|
||||
// Get a handle to the calling thread. This is the thread that we are
|
||||
// going to profile. We need to duplicate the handle because we are
|
||||
// going to use it in the sampler thread. using GetThreadHandle() will
|
||||
// not work in this case.
|
||||
BOOL ok = DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
|
||||
GetCurrentProcess(), &data_->profiled_thread_,
|
||||
THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME |
|
||||
THREAD_QUERY_INFORMATION, FALSE, 0);
|
||||
if (!ok) return;
|
||||
}
|
||||
|
||||
// Start sampler thread.
|
||||
unsigned int tid;
|
||||
active_ = true;
|
||||
data_->sampler_thread_ = reinterpret_cast<HANDLE>(
|
||||
_beginthreadex(NULL, 0, ProfileSamplerEntry, data_, 0, &tid));
|
||||
_beginthreadex(NULL, 0, SamplerEntry, data_, 0, &tid));
|
||||
// Set thread to high priority to increase sampling accuracy.
|
||||
SetThreadPriority(data_->sampler_thread_, THREAD_PRIORITY_TIME_CRITICAL);
|
||||
}
|
||||
|
||||
|
||||
// Stop profiling.
|
||||
void ProfileSampler::Stop() {
|
||||
void Sampler::Stop() {
|
||||
// Seting active to false triggers termination of the sampler
|
||||
// thread.
|
||||
active_ = false;
|
||||
|
@ -390,42 +390,48 @@ class Semaphore {
|
||||
|
||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||
// ----------------------------------------------------------------------------
|
||||
// ProfileSampler
|
||||
// Sampler
|
||||
//
|
||||
// A profile sampler periodically samples the program counter and stack pointer
|
||||
// for the thread that created it.
|
||||
// A sampler periodically samples the state of the VM and optionally
|
||||
// (if used for profiling) the program counter and stack pointer for
|
||||
// the thread that created it.
|
||||
|
||||
// TickSample captures the information collected
|
||||
// for each profiling sample.
|
||||
struct TickSample {
|
||||
// TickSample captures the information collected for each sample.
|
||||
class TickSample {
|
||||
public:
|
||||
TickSample() : pc(0), sp(0), state(OTHER) {}
|
||||
unsigned int pc; // Instruction pointer.
|
||||
unsigned int sp; // Stack pointer.
|
||||
StateTag state; // The state of the VM.
|
||||
StateTag state; // The state of the VM.
|
||||
};
|
||||
|
||||
class ProfileSampler {
|
||||
class Sampler {
|
||||
public:
|
||||
// Initialize sampler.
|
||||
explicit ProfileSampler(int interval);
|
||||
virtual ~ProfileSampler();
|
||||
explicit Sampler(int interval, bool profiling);
|
||||
virtual ~Sampler();
|
||||
|
||||
// This method is called for each sampling period with the current program
|
||||
// counter.
|
||||
// This method is called for each sampling period with the current
|
||||
// program counter.
|
||||
virtual void Tick(TickSample* sample) = 0;
|
||||
|
||||
// Start and stop sampler.
|
||||
void Start();
|
||||
void Stop();
|
||||
|
||||
// Is the sampler used for profiling.
|
||||
inline bool IsProfiling() { return profiling_; }
|
||||
|
||||
class PlatformData;
|
||||
protected:
|
||||
inline bool IsActive() { return active_; }
|
||||
|
||||
private:
|
||||
int interval_;
|
||||
bool profiling_;
|
||||
bool active_;
|
||||
PlatformData* data_; // Platform specific data.
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ProfileSampler);
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
|
||||
};
|
||||
|
||||
#endif // ENABLE_LOGGING_AND_PROFILING
|
||||
|
@ -263,8 +263,6 @@ void PrettyPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
|
||||
|
||||
void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
Print("{ ");
|
||||
Visit(node->result());
|
||||
Print(" <- ");
|
||||
for (int i = 0; i < node->properties()->length(); i++) {
|
||||
if (i != 0) Print(",");
|
||||
ObjectLiteral::Property* property = node->properties()->at(i);
|
||||
@ -279,8 +277,6 @@ void PrettyPrinter::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
|
||||
void PrettyPrinter::VisitArrayLiteral(ArrayLiteral* node) {
|
||||
Print("[ ");
|
||||
Visit(node->result());
|
||||
Print(" <- ");
|
||||
for (int i = 0; i < node->values()->length(); i++) {
|
||||
if (i != 0) Print(",");
|
||||
Visit(node->values()->at(i));
|
||||
@ -898,7 +894,6 @@ void AstPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
|
||||
|
||||
void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
IndentedScope indent("OBJ LITERAL");
|
||||
Visit(node->result());
|
||||
for (int i = 0; i < node->properties()->length(); i++) {
|
||||
const char* prop_kind = NULL;
|
||||
switch (node->properties()->at(i)->kind()) {
|
||||
@ -930,7 +925,6 @@ void AstPrinter::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
|
||||
void AstPrinter::VisitArrayLiteral(ArrayLiteral* node) {
|
||||
IndentedScope indent("ARRAY LITERAL");
|
||||
Visit(node->result());
|
||||
if (node->values()->length() > 0) {
|
||||
IndentedScope indent("VALUES");
|
||||
for (int i = 0; i < node->values()->length(); i++) {
|
||||
|
@ -93,11 +93,6 @@ static Object* IllegalOperation() {
|
||||
|
||||
static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) {
|
||||
CONVERT_CHECKED(JSObject, boilerplate, args[0]);
|
||||
|
||||
// Verify that the constructor of the boilerplate is equal to the
|
||||
// object function in the current global context.
|
||||
ASSERT(boilerplate->map()->constructor() ==
|
||||
Top::context()->global_context()->object_function());
|
||||
return boilerplate->Copy();
|
||||
}
|
||||
|
||||
@ -110,9 +105,16 @@ static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
|
||||
int literals_index = Smi::cast(args[1])->value();
|
||||
Handle<FixedArray> constant_properties = args.at<FixedArray>(2);
|
||||
|
||||
// Create the boilerplate object for the function literal
|
||||
Handle<JSObject> boilerplate =
|
||||
Factory::NewJSObject(Top::object_function(), TENURED);
|
||||
// Get the object function from the literals array. This is the
|
||||
// object function from the context in which the function was
|
||||
// created. We do not use the object function from the current
|
||||
// global context because this might be the object function from
|
||||
// another context which we should not have access to.
|
||||
const int kObjectFunIndex = JSFunction::kLiteralObjectFunctionIndex;
|
||||
Handle<JSFunction> constructor =
|
||||
Handle<JSFunction>(JSFunction::cast(literals->get(kObjectFunIndex)));
|
||||
|
||||
Handle<JSObject> boilerplate = Factory::NewJSObject(constructor, TENURED);
|
||||
|
||||
{ // Add the constant propeties to the boilerplate.
|
||||
int length = constant_properties->length();
|
||||
@ -150,25 +152,40 @@ static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
|
||||
|
||||
|
||||
static Object* Runtime_CreateArrayLiteral(Arguments args) {
|
||||
// Takes a FixedArray containing literals and produces
|
||||
// JSArray with the elements matching the literals.
|
||||
ASSERT(args.length() == 1);
|
||||
CONVERT_CHECKED(FixedArray, literals, args[0]);
|
||||
// Takes a FixedArray of elements containing the literal elements of
|
||||
// the array literal and produces JSArray with those elements.
|
||||
// Additionally takes the literals array of the surrounding function
|
||||
// which contains the Array function to use for creating the array
|
||||
// literal.
|
||||
ASSERT(args.length() == 2);
|
||||
CONVERT_CHECKED(FixedArray, elements, args[0]);
|
||||
|
||||
// Retrieve the array constructor from the global context.
|
||||
#ifdef USE_OLD_CALLING_CONVENTIONS
|
||||
ASSERT(args[1]->IsTheHole());
|
||||
// TODO(1332579): Pass in the literals array from the function once
|
||||
// the new calling convention is in place on ARM. Currently, we
|
||||
// retrieve the array constructor from the global context. This is
|
||||
// a security problem since the global object might have been
|
||||
// reinitialized and the array constructor from the global context
|
||||
// might be from a context that we are not allowed to access.
|
||||
JSFunction* constructor =
|
||||
JSFunction::cast(Top::context()->global_context()->array_function());
|
||||
#else
|
||||
CONVERT_CHECKED(FixedArray, literals, args[1]);
|
||||
const int kArrayFunIndex = JSFunction::kLiteralArrayFunctionIndex;
|
||||
JSFunction* constructor = JSFunction::cast(literals->get(kArrayFunIndex));
|
||||
#endif
|
||||
|
||||
// Create the JSArray.
|
||||
Object* object = Heap::AllocateJSObject(constructor);
|
||||
if (object->IsFailure()) return object;
|
||||
|
||||
// Copy the literals.
|
||||
Object* elements = literals->Copy();
|
||||
if (elements->IsFailure()) return elements;
|
||||
// Copy the elements.
|
||||
Object* content = elements->Copy();
|
||||
if (content->IsFailure()) return content;
|
||||
|
||||
// Set the elements.
|
||||
JSArray::cast(object)->SetContent(FixedArray::cast(elements));
|
||||
JSArray::cast(object)->SetContent(FixedArray::cast(content));
|
||||
return object;
|
||||
}
|
||||
|
||||
@ -691,10 +708,20 @@ static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
|
||||
Handle<String> pattern = args.at<String>(2);
|
||||
Handle<String> flags = args.at<String>(3);
|
||||
|
||||
// Get the RegExp function from the literals array. This is the
|
||||
// RegExp function from the context in which the function was
|
||||
// created. We do not use the RegExp function from the current
|
||||
// global context because this might be the RegExp function from
|
||||
// another context which we should not have access to.
|
||||
const int kRegexpFunIndex = JSFunction::kLiteralRegExpFunctionIndex;
|
||||
Handle<JSFunction> constructor =
|
||||
Handle<JSFunction>(JSFunction::cast(literals->get(kRegexpFunIndex)));
|
||||
|
||||
// Compute the regular expression literal.
|
||||
bool has_pending_exception;
|
||||
Handle<Object> regexp =
|
||||
RegExpImpl::CreateRegExpLiteral(pattern, flags, &has_pending_exception);
|
||||
RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
|
||||
&has_pending_exception);
|
||||
if (has_pending_exception) {
|
||||
ASSERT(Top::has_pending_exception());
|
||||
return Failure::Exception();
|
||||
@ -807,12 +834,21 @@ static Object* Runtime_SetCode(Arguments args) {
|
||||
|
||||
// Make sure we get a fresh copy of the literal vector to avoid
|
||||
// cross context contamination.
|
||||
int number_of_literals = fun->literals()->length();
|
||||
int number_of_literals = fun->NumberOfLiterals();
|
||||
Handle<FixedArray> literals =
|
||||
Factory::NewFixedArray(number_of_literals, TENURED);
|
||||
if (number_of_literals > 0) {
|
||||
Handle<FixedArray> literals =
|
||||
Factory::NewFixedArray(number_of_literals, TENURED);
|
||||
target->set_literals(*literals);
|
||||
// Insert the object, regexp and array functions in the literals
|
||||
// array prefix. These are the functions that will be used when
|
||||
// creating object, regexp and array literals.
|
||||
literals->set(JSFunction::kLiteralObjectFunctionIndex,
|
||||
context->global_context()->object_function());
|
||||
literals->set(JSFunction::kLiteralRegExpFunctionIndex,
|
||||
context->global_context()->regexp_function());
|
||||
literals->set(JSFunction::kLiteralArrayFunctionIndex,
|
||||
context->global_context()->array_function());
|
||||
}
|
||||
target->set_literals(*literals);
|
||||
}
|
||||
|
||||
target->set_context(*context);
|
||||
|
@ -237,7 +237,7 @@ namespace v8 { namespace internal {
|
||||
\
|
||||
/* Literals */ \
|
||||
F(MaterializeRegExpLiteral, 4)\
|
||||
F(CreateArrayLiteral, 1) \
|
||||
F(CreateArrayLiteral, 2) \
|
||||
F(CreateObjectLiteralBoilerplate, 3) \
|
||||
F(CloneObjectLiteralBoilerplate, 1) \
|
||||
\
|
||||
|
@ -172,11 +172,6 @@ function MUL(x) {
|
||||
};
|
||||
|
||||
|
||||
function MULNEG(x) {
|
||||
return %NumberUnaryMinus(%NumberMul(%ToNumber(this), %ToNumber(x)));
|
||||
};
|
||||
|
||||
|
||||
// ECMA-262, section 11.5.2, page 49.
|
||||
function DIV(x) {
|
||||
return %NumberDiv(%ToNumber(this), %ToNumber(x));
|
||||
@ -358,7 +353,7 @@ function APPLY_PREPARE(args) {
|
||||
%ClassOf(args) != 'Arguments') {
|
||||
throw %MakeTypeError('apply_wrong_args', []);
|
||||
}
|
||||
|
||||
|
||||
// Return the length which is the number of arguments to copy to the
|
||||
// stack. It is guaranteed to be a small integer at this point.
|
||||
return length;
|
||||
|
@ -1614,8 +1614,7 @@ void OldSpace::Verify() {
|
||||
ASSERT(!object->IsMap());
|
||||
|
||||
// The object itself should look OK.
|
||||
// This is blocked by bug #1006953.
|
||||
// object->Verify();
|
||||
object->Verify();
|
||||
|
||||
// All the interior pointers should be contained in the heap and have
|
||||
// their remembered set bits set if they point to new space. Code
|
||||
@ -2091,8 +2090,7 @@ void MapSpace::Verify() {
|
||||
ASSERT(object->IsMap() || object->IsByteArray());
|
||||
|
||||
// The object itself should look OK.
|
||||
// This is blocked by bug #1006953.
|
||||
// object->Verify();
|
||||
object->Verify();
|
||||
|
||||
// All the interior pointers should be contained in the heap and
|
||||
// have their remembered set bits set if they point to new space.
|
||||
@ -2429,8 +2427,7 @@ void LargeObjectSpace::Verify() {
|
||||
|| object->IsFixedArray() || object->IsByteArray());
|
||||
|
||||
// The object itself should look OK.
|
||||
// This is blocked by bug #1006953.
|
||||
// object->Verify();
|
||||
object->Verify();
|
||||
|
||||
// Byte arrays and strings don't have interior pointers.
|
||||
if (object->IsCode()) {
|
||||
|
5
src/third_party/jscre/pcre.h
vendored
5
src/third_party/jscre/pcre.h
vendored
@ -44,6 +44,11 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "../../../public/v8.h"
|
||||
|
||||
// JSCRE is very chatty in debug mode, so in order to keep it slient
|
||||
// while still importing v8.h correctly (it contains #ifdef DEBUGs)
|
||||
// we allow DEBUG to be set and undef it manually.
|
||||
#undef DEBUG
|
||||
|
||||
typedef uint16_t UChar;
|
||||
|
||||
struct JSRegExp;
|
||||
|
@ -285,13 +285,11 @@ void UsageComputer::VisitRegExpLiteral(RegExpLiteral* node) {
|
||||
|
||||
|
||||
void UsageComputer::VisitObjectLiteral(ObjectLiteral* node) {
|
||||
Read(node->result());
|
||||
ReadList(node->properties());
|
||||
}
|
||||
|
||||
|
||||
void UsageComputer::VisitArrayLiteral(ArrayLiteral* node) {
|
||||
Read(node->result());
|
||||
ReadList(node->values());
|
||||
}
|
||||
|
||||
|
64
test/cctest/SConscript
Normal file
64
test/cctest/SConscript
Normal file
@ -0,0 +1,64 @@
|
||||
# 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 sys
|
||||
from os.path import join, dirname, abspath
|
||||
root_dir = dirname(File('SConstruct').rfile().abspath)
|
||||
sys.path.append(join(root_dir, 'tools'))
|
||||
Import('context object_files')
|
||||
|
||||
|
||||
SOURCES = {
|
||||
'all': [
|
||||
'test-hashmap.cc', 'test-debug.cc', 'test-api.cc', 'test-flags.cc',
|
||||
'test-ast.cc', 'test-heap.cc', 'test-utils.cc', 'test-compiler.cc',
|
||||
'test-spaces.cc', 'test-mark-compact.cc', 'test-lock.cc',
|
||||
'test-conversions.cc', 'test-strings.cc', 'test-serialize.cc',
|
||||
'test-decls.cc'
|
||||
],
|
||||
'arch:arm': ['test-assembler-arm.cc', 'test-disasm-arm.cc'],
|
||||
'arch:ia32': ['test-assembler-ia32.cc', 'test-disasm-ia32.cc'],
|
||||
'os:linux': ['test-platform-linux.cc'],
|
||||
'os:macos': ['test-platform-macos.cc'],
|
||||
'os:nullos': ['test-platform-nullos.cc'],
|
||||
'os:win32': ['test-platform-win32.cc']
|
||||
}
|
||||
|
||||
|
||||
def Build():
|
||||
cctest_files = context.GetRelevantSources(SOURCES)
|
||||
env = Environment()
|
||||
env.Replace(**context.flags['cctest'])
|
||||
# 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.
|
||||
return env.Program('cctest', ['cctest.cc', cctest_files, object_files],
|
||||
PDB='cctest.exe.pdb')
|
||||
|
||||
|
||||
program = Build()
|
||||
Return('program')
|
65
test/cctest/cctest.cc
Normal file
65
test/cctest/cctest.cc
Normal file
@ -0,0 +1,65 @@
|
||||
// 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.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include "cctest.h"
|
||||
|
||||
|
||||
CcTest* CcTest::first_ = NULL;
|
||||
|
||||
|
||||
CcTest::CcTest(TestFunction* callback, const char* file, const char* name)
|
||||
: callback_(callback), name_(name), prev_(first_) {
|
||||
// Find the base name of this test (const_cast required on Windows).
|
||||
char *basename = strrchr(const_cast<char *>(file), '/');
|
||||
if (!basename) {
|
||||
basename = strrchr(const_cast<char *>(file), '\\');
|
||||
}
|
||||
if (!basename) {
|
||||
basename = strdup(file);
|
||||
} else {
|
||||
basename = strdup(basename + 1);
|
||||
}
|
||||
// Drop the extension, if there is one.
|
||||
char *extension = strrchr(basename, '.');
|
||||
if (extension) *extension = 0;
|
||||
// Install this test in the list of tests
|
||||
file_ = basename;
|
||||
prev_ = first_;
|
||||
first_ = 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();
|
||||
}
|
||||
}
|
57
test/cctest/cctest.h
Normal file
57
test/cctest/cctest.h
Normal file
@ -0,0 +1,57 @@
|
||||
// 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.
|
||||
|
||||
#ifndef CCTEST_H_
|
||||
#define CCTEST_H_
|
||||
|
||||
#ifndef TEST
|
||||
#define TEST(Name) \
|
||||
static void Test##Name(); \
|
||||
CcTest register_test_##Name(Test##Name, __FILE__, #Name); \
|
||||
static void Test##Name()
|
||||
#endif
|
||||
|
||||
|
||||
class CcTest {
|
||||
public:
|
||||
typedef void (TestFunction)();
|
||||
CcTest(TestFunction* callback, const char* file, const char* name);
|
||||
static int test_count();
|
||||
static CcTest* first() { return first_; }
|
||||
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_;
|
||||
CcTest* prev_;
|
||||
};
|
||||
|
||||
#endif // ifndef CCTEST_H_
|
4819
test/cctest/test-api.cc
Normal file
4819
test/cctest/test-api.cc
Normal file
File diff suppressed because it is too large
Load Diff
273
test/cctest/test-assembler-arm.cc
Normal file
273
test/cctest/test-assembler-arm.cc
Normal file
@ -0,0 +1,273 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "disassembler.h"
|
||||
#include "factory.h"
|
||||
#include "simulator-arm.h"
|
||||
#include "assembler-arm-inl.h"
|
||||
#include "cctest.h"
|
||||
|
||||
// The test framework does not accept flags on the command line, so we set them
|
||||
namespace v8 { namespace internal {
|
||||
DECLARE_string(natives_file);
|
||||
DECLARE_bool(debug_code);
|
||||
DECLARE_bool(eliminate_jumps);
|
||||
DECLARE_bool(print_jump_elimination);
|
||||
} } // namespace v8::internal
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
|
||||
// Define these function prototypes to match JSEntryFunction in execution.cc.
|
||||
typedef int (*F1)(int x, int p1, int p2, int p3, int p4);
|
||||
typedef int (*F2)(int x, int y, int p2, int p3, int p4);
|
||||
typedef int (*F3)(void* p, int p1, int p2, int p3, int p4);
|
||||
|
||||
|
||||
static v8::Persistent<v8::Context> env;
|
||||
|
||||
|
||||
static void InitializeVM() {
|
||||
// disable compilation of natives by specifying an empty natives file
|
||||
FLAG_natives_file = "";
|
||||
|
||||
// enable generation of comments
|
||||
FLAG_debug_code = true;
|
||||
|
||||
if (env.IsEmpty()) {
|
||||
env = v8::Context::New();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define __ assm.
|
||||
|
||||
TEST(0) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
Assembler assm(NULL, 0);
|
||||
|
||||
__ add(r0, r0, Operand(r1));
|
||||
__ mov(pc, Operand(lr));
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
||||
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(7, res);
|
||||
}
|
||||
|
||||
|
||||
TEST(1) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
Assembler assm(NULL, 0);
|
||||
Label L, C;
|
||||
|
||||
__ mov(r1, Operand(r0));
|
||||
__ mov(r0, Operand(0));
|
||||
__ b(&C);
|
||||
|
||||
__ bind(&L);
|
||||
__ add(r0, r0, Operand(r1));
|
||||
__ sub(r1, r1, Operand(1));
|
||||
|
||||
__ bind(&C);
|
||||
__ teq(r1, Operand(0));
|
||||
__ b(ne, &L);
|
||||
__ mov(pc, Operand(lr));
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
|
||||
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(5050, res);
|
||||
}
|
||||
|
||||
|
||||
TEST(2) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
Assembler assm(NULL, 0);
|
||||
Label L, C;
|
||||
|
||||
__ mov(r1, Operand(r0));
|
||||
__ mov(r0, Operand(1));
|
||||
__ b(&C);
|
||||
|
||||
__ bind(&L);
|
||||
__ mul(r0, r1, r0);
|
||||
__ sub(r1, r1, Operand(1));
|
||||
|
||||
__ bind(&C);
|
||||
__ teq(r1, Operand(0));
|
||||
__ b(ne, &L);
|
||||
__ mov(pc, Operand(lr));
|
||||
|
||||
// some relocated stuff here, not executed
|
||||
__ RecordComment("dead code, just testing relocations");
|
||||
__ mov(r0, Operand(Factory::true_value()));
|
||||
__ RecordComment("dead code, just testing immediate operands");
|
||||
__ mov(r0, Operand(-1));
|
||||
__ mov(r0, Operand(0xFF000000));
|
||||
__ mov(r0, Operand(0xF0F0F0F0));
|
||||
__ mov(r0, Operand(0xFFF0FFFF));
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
|
||||
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(3628800, res);
|
||||
}
|
||||
|
||||
|
||||
TEST(3) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
typedef struct {
|
||||
int i;
|
||||
char c;
|
||||
int16_t s;
|
||||
} T;
|
||||
T t;
|
||||
|
||||
Assembler assm(NULL, 0);
|
||||
Label L, C;
|
||||
|
||||
__ mov(ip, Operand(sp));
|
||||
__ stm(db_w, sp, r4.bit() | fp.bit() | sp.bit() | lr.bit());
|
||||
__ sub(fp, ip, Operand(4));
|
||||
__ mov(r4, Operand(r0));
|
||||
__ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
|
||||
__ mov(r2, Operand(r0, ASR, 1));
|
||||
__ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
|
||||
__ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
|
||||
__ add(r0, r2, Operand(r0));
|
||||
__ mov(r2, Operand(r2, LSL, 2));
|
||||
__ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
|
||||
__ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
|
||||
__ add(r0, r2, Operand(r0));
|
||||
__ mov(r2, Operand(r2, ASR, 3));
|
||||
__ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
|
||||
__ ldm(ia, sp, r4.bit() | fp.bit() | sp.bit() | pc.bit());
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
|
||||
t.i = 100000;
|
||||
t.c = 10;
|
||||
t.s = 1000;
|
||||
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(101010, res);
|
||||
CHECK_EQ(100000/2, t.i);
|
||||
CHECK_EQ(10*4, t.c);
|
||||
CHECK_EQ(1000/8, t.s);
|
||||
}
|
||||
|
||||
|
||||
TEST(4) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
// enable jump elimination
|
||||
bool je_save = FLAG_eliminate_jumps;
|
||||
bool pje_save = FLAG_print_jump_elimination;
|
||||
FLAG_eliminate_jumps = true;
|
||||
FLAG_print_jump_elimination = true;
|
||||
|
||||
Assembler assm(NULL, 0);
|
||||
Label L0, L1, L2, L3;
|
||||
|
||||
__ mov(r1, Operand(r0));
|
||||
__ mov(r0, Operand(1));
|
||||
__ b(&L0); // can be eliminated
|
||||
|
||||
__ bind(&L0);
|
||||
__ b(&L2);
|
||||
|
||||
__ bind(&L1);
|
||||
__ mul(r0, r1, r0);
|
||||
__ sub(r1, r1, Operand(1));
|
||||
|
||||
__ bind(&L2);
|
||||
__ teq(r1, Operand(0));
|
||||
__ b(ne, &L3); // can be replaced by bne L1
|
||||
__ mov(pc, Operand(lr));
|
||||
|
||||
__ bind(&L3);
|
||||
__ b(&L1);
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
|
||||
// restore jump elimination flags
|
||||
FLAG_eliminate_jumps = je_save;
|
||||
FLAG_print_jump_elimination = pje_save;
|
||||
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
|
||||
int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(3628800, res);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
370
test/cctest/test-assembler-ia32.cc
Normal file
370
test/cctest/test-assembler-ia32.cc
Normal file
@ -0,0 +1,370 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "disassembler.h"
|
||||
#include "factory.h"
|
||||
#include "macro-assembler.h"
|
||||
#include "platform.h"
|
||||
#include "serialize.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
|
||||
typedef int (*F0)();
|
||||
typedef int (*F1)(int x);
|
||||
typedef int (*F2)(int x, int y);
|
||||
|
||||
|
||||
static v8::Persistent<v8::Context> env;
|
||||
|
||||
|
||||
static void InitializeVM() {
|
||||
if (env.IsEmpty()) {
|
||||
env = v8::Context::New();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define __ assm.
|
||||
|
||||
TEST(AssemblerIa320) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
v8::internal::byte buffer[256];
|
||||
Assembler assm(buffer, sizeof buffer);
|
||||
|
||||
__ mov(eax, Operand(esp, 4));
|
||||
__ add(eax, Operand(esp, 8));
|
||||
__ ret(0);
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
|
||||
int res = f(3, 4);
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(7, res);
|
||||
}
|
||||
|
||||
|
||||
TEST(AssemblerIa321) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
v8::internal::byte buffer[256];
|
||||
Assembler assm(buffer, sizeof buffer);
|
||||
Label L, C;
|
||||
|
||||
__ mov(edx, Operand(esp, 4));
|
||||
__ xor_(eax, Operand(eax)); // clear eax
|
||||
__ jmp(&C);
|
||||
|
||||
__ bind(&L);
|
||||
__ add(eax, Operand(edx));
|
||||
__ sub(Operand(edx), Immediate(1));
|
||||
|
||||
__ bind(&C);
|
||||
__ test(edx, Operand(edx));
|
||||
__ j(not_zero, &L, taken);
|
||||
__ ret(0);
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
|
||||
int res = f(100);
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(5050, res);
|
||||
}
|
||||
|
||||
|
||||
TEST(AssemblerIa322) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
v8::internal::byte buffer[256];
|
||||
Assembler assm(buffer, sizeof buffer);
|
||||
Label L, C;
|
||||
|
||||
__ mov(edx, Operand(esp, 4));
|
||||
__ mov(eax, 1);
|
||||
__ jmp(&C);
|
||||
|
||||
__ bind(&L);
|
||||
__ imul(eax, Operand(edx));
|
||||
__ sub(Operand(edx), Immediate(1));
|
||||
|
||||
__ bind(&C);
|
||||
__ test(edx, Operand(edx));
|
||||
__ j(not_zero, &L, taken);
|
||||
__ ret(0);
|
||||
|
||||
// some relocated stuff here, not executed
|
||||
__ mov(eax, Factory::true_value());
|
||||
__ jmp(NULL, runtime_entry);
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
|
||||
int res = f(10);
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(3628800, res);
|
||||
}
|
||||
|
||||
|
||||
typedef int (*F3)(float x);
|
||||
|
||||
TEST(AssemblerIa323) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
v8::internal::byte buffer[256];
|
||||
Assembler assm(buffer, sizeof buffer);
|
||||
|
||||
Serializer::disable(); // Needed for Probe when running without snapshot.
|
||||
CpuFeatures::Probe();
|
||||
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
|
||||
{ CpuFeatures::Scope fscope(CpuFeatures::SSE2);
|
||||
__ cvttss2si(eax, Operand(esp, 4));
|
||||
__ ret(0);
|
||||
}
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Code* code =
|
||||
Code::cast(Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB)));
|
||||
// don't print the code - our disassembler can't handle cvttss2si
|
||||
// instead print bytes
|
||||
Disassembler::Dump(stdout,
|
||||
code->instruction_start(),
|
||||
code->instruction_start() + code->instruction_size());
|
||||
F3 f = FUNCTION_CAST<F3>(code->entry());
|
||||
int res = f(static_cast<float>(-3.1415));
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(-3, res);
|
||||
}
|
||||
|
||||
|
||||
typedef int (*F4)(double x);
|
||||
|
||||
TEST(AssemblerIa324) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
v8::internal::byte buffer[256];
|
||||
Assembler assm(buffer, sizeof buffer);
|
||||
|
||||
Serializer::disable(); // Needed for Probe when running without snapshot.
|
||||
CpuFeatures::Probe();
|
||||
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
|
||||
CpuFeatures::Scope fscope(CpuFeatures::SSE2);
|
||||
__ cvttsd2si(eax, Operand(esp, 4));
|
||||
__ ret(0);
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Code* code =
|
||||
Code::cast(Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB)));
|
||||
// don't print the code - our disassembler can't handle cvttsd2si
|
||||
// instead print bytes
|
||||
Disassembler::Dump(stdout,
|
||||
code->instruction_start(),
|
||||
code->instruction_start() + code->instruction_size());
|
||||
F4 f = FUNCTION_CAST<F4>(code->entry());
|
||||
int res = f(2.718281828);
|
||||
::printf("f() = %d\n", res);
|
||||
CHECK_EQ(2, res);
|
||||
}
|
||||
|
||||
|
||||
static int baz = 42;
|
||||
TEST(AssemblerIa325) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
v8::internal::byte buffer[256];
|
||||
Assembler assm(buffer, sizeof buffer);
|
||||
|
||||
__ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), no_reloc));
|
||||
__ ret(0);
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Code* code =
|
||||
Code::cast(Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB)));
|
||||
F0 f = FUNCTION_CAST<F0>(code->entry());
|
||||
int res = f();
|
||||
CHECK_EQ(42, res);
|
||||
}
|
||||
|
||||
|
||||
typedef double (*F5)(double x, double y);
|
||||
|
||||
TEST(AssemblerIa326) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
Serializer::disable(); // Needed for Probe when running without snapshot.
|
||||
CpuFeatures::Probe();
|
||||
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
|
||||
CpuFeatures::Scope fscope(CpuFeatures::SSE2);
|
||||
v8::internal::byte buffer[256];
|
||||
Assembler assm(buffer, sizeof buffer);
|
||||
|
||||
__ movdbl(xmm0, Operand(esp, 1 * kPointerSize));
|
||||
__ movdbl(xmm1, Operand(esp, 3 * kPointerSize));
|
||||
__ addsd(xmm0, xmm1);
|
||||
__ mulsd(xmm0, xmm1);
|
||||
__ subsd(xmm0, xmm1);
|
||||
__ divsd(xmm0, xmm1);
|
||||
__ movdbl(Operand(esp, 4), xmm0);
|
||||
__ fld_d(Operand(esp, 4));
|
||||
__ ret(0);
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Code* code =
|
||||
Code::cast(Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB)));
|
||||
#ifdef DEBUG
|
||||
::printf("\n---\n");
|
||||
// don't print the code - our disassembler can't handle SSE instructions
|
||||
// instead print bytes
|
||||
Disassembler::Dump(stdout,
|
||||
code->instruction_start(),
|
||||
code->instruction_start() + code->instruction_size());
|
||||
#endif
|
||||
F5 f = FUNCTION_CAST<F5>(code->entry());
|
||||
double res = f(2.2, 1.1);
|
||||
::printf("f() = %f\n", res);
|
||||
CHECK(2.29 < res && res < 2.31);
|
||||
}
|
||||
|
||||
|
||||
typedef double (*F6)(int x);
|
||||
|
||||
TEST(AssemblerIa328) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
Serializer::disable(); // Needed for Probe when running without snapshot.
|
||||
CpuFeatures::Probe();
|
||||
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
|
||||
CpuFeatures::Scope fscope(CpuFeatures::SSE2);
|
||||
v8::internal::byte buffer[256];
|
||||
Assembler assm(buffer, sizeof buffer);
|
||||
__ mov(eax, Operand(esp, 4));
|
||||
__ cvtsi2sd(xmm0, Operand(eax));
|
||||
__ movdbl(Operand(esp, 4), xmm0);
|
||||
__ fld_d(Operand(esp, 4));
|
||||
__ ret(0);
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Code* code =
|
||||
Code::cast(Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB)));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
F6 f = FUNCTION_CAST<F6>(Code::cast(code)->entry());
|
||||
double res = f(12);
|
||||
|
||||
::printf("f() = %f\n", res);
|
||||
CHECK(11.99 < res && res < 12.001);
|
||||
}
|
||||
|
||||
|
||||
typedef int (*F7)(double x, double y);
|
||||
|
||||
TEST(AssemblerIa329) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
v8::internal::byte buffer[256];
|
||||
MacroAssembler assm(buffer, sizeof buffer);
|
||||
enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
|
||||
Label equal_l, less_l, greater_l, nan_l;
|
||||
__ fld_d(Operand(esp, 3 * kPointerSize));
|
||||
__ fld_d(Operand(esp, 1 * kPointerSize));
|
||||
__ FCmp();
|
||||
__ j(parity_even, &nan_l, taken);
|
||||
__ j(equal, &equal_l, taken);
|
||||
__ j(below, &less_l, taken);
|
||||
__ j(above, &greater_l, taken);
|
||||
|
||||
__ mov(eax, kUndefined);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&equal_l);
|
||||
__ mov(eax, kEqual);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&greater_l);
|
||||
__ mov(eax, kGreater);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&less_l);
|
||||
__ mov(eax, kLess);
|
||||
__ ret(0);
|
||||
|
||||
__ bind(&nan_l);
|
||||
__ mov(eax, kNaN);
|
||||
__ ret(0);
|
||||
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Code* code =
|
||||
Code::cast(Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB)));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
#endif
|
||||
|
||||
F7 f = FUNCTION_CAST<F7>(Code::cast(code)->entry());
|
||||
CHECK_EQ(kLess, f(1.1, 2.2));
|
||||
CHECK_EQ(kEqual, f(2.2, 2.2));
|
||||
CHECK_EQ(kGreater, f(3.3, 2.2));
|
||||
CHECK_EQ(kNaN, f(OS::nan_value(), 1.1));
|
||||
}
|
||||
|
||||
#undef __
|
95
test/cctest/test-ast.cc
Normal file
95
test/cctest/test-ast.cc
Normal file
@ -0,0 +1,95 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "ast.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
TEST(List) {
|
||||
List<Node*>* list = new List<Node*>(0);
|
||||
CHECK_EQ(0, list->length());
|
||||
|
||||
Node* node = new EmptyStatement();
|
||||
list->Add(node);
|
||||
CHECK_EQ(1, list->length());
|
||||
CHECK_EQ(node, list->at(0));
|
||||
CHECK_EQ(node, list->last());
|
||||
|
||||
const int kElements = 100;
|
||||
for (int i = 0; i < kElements; i++) {
|
||||
list->Add(node);
|
||||
}
|
||||
CHECK_EQ(1 + kElements, list->length());
|
||||
|
||||
list->Clear();
|
||||
CHECK_EQ(0, list->length());
|
||||
}
|
||||
|
||||
|
||||
TEST(RemoveLast) {
|
||||
List<int> list(4);
|
||||
CHECK_EQ(0, list.length());
|
||||
list.Add(1);
|
||||
CHECK_EQ(1, list.length());
|
||||
CHECK_EQ(1, list.last());
|
||||
list.RemoveLast();
|
||||
CHECK_EQ(0, list.length());
|
||||
list.Add(2);
|
||||
list.Add(3);
|
||||
CHECK_EQ(2, list.length());
|
||||
CHECK_EQ(3, list.last());
|
||||
list.RemoveLast();
|
||||
CHECK_EQ(1, list.length());
|
||||
CHECK_EQ(2, list.last());
|
||||
list.RemoveLast();
|
||||
CHECK_EQ(0, list.length());
|
||||
|
||||
const int kElements = 100;
|
||||
for (int i = 0; i < kElements; i++) list.Add(i);
|
||||
for (int j = kElements - 1; j >= 0; j--) {
|
||||
CHECK_EQ(j + 1, list.length());
|
||||
CHECK_EQ(j, list.last());
|
||||
list.RemoveLast();
|
||||
CHECK_EQ(j, list.length());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(DeleteEmpty) {
|
||||
{
|
||||
List<int>* list = new List<int>(0);
|
||||
delete list;
|
||||
}
|
||||
{
|
||||
List<int> list(0);
|
||||
}
|
||||
}
|
259
test/cctest/test-compiler.cc
Normal file
259
test/cctest/test-compiler.cc
Normal file
@ -0,0 +1,259 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "compiler.h"
|
||||
#include "execution.h"
|
||||
#include "factory.h"
|
||||
#include "platform.h"
|
||||
#include "top.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
static v8::Persistent<v8::Context> env;
|
||||
|
||||
static void InitializeVM() {
|
||||
if (env.IsEmpty()) {
|
||||
v8::HandleScope scope;
|
||||
const char* extensions[] = { "v8/print", "v8/gc" };
|
||||
v8::ExtensionConfiguration config(2, extensions);
|
||||
env = v8::Context::New(&config);
|
||||
}
|
||||
v8::HandleScope scope;
|
||||
env->Enter();
|
||||
}
|
||||
|
||||
|
||||
static Object* GetGlobalProperty(const char* name) {
|
||||
Handle<String> symbol = Factory::LookupAsciiSymbol(name);
|
||||
return Top::context()->global()->GetProperty(*symbol);
|
||||
}
|
||||
|
||||
|
||||
static void SetGlobalProperty(const char* name, Object* value) {
|
||||
Handle<Object> object(value);
|
||||
Handle<String> symbol = Factory::LookupAsciiSymbol(name);
|
||||
Handle<JSObject> global(Top::context()->global());
|
||||
SetProperty(global, symbol, object, NONE);
|
||||
}
|
||||
|
||||
|
||||
static Handle<JSFunction> Compile(const char* source) {
|
||||
Handle<String> source_code(Factory::NewStringFromUtf8(CStrVector(source)));
|
||||
Handle<JSFunction> boilerplate =
|
||||
Compiler::Compile(source_code, Handle<String>(), 0, 0, NULL, NULL);
|
||||
return Factory::NewFunctionFromBoilerplate(boilerplate,
|
||||
Top::global_context());
|
||||
}
|
||||
|
||||
|
||||
static double Inc(int x) {
|
||||
const char* source = "result = %d + 1;";
|
||||
char buffer[512];
|
||||
OS::SNPrintF(buffer, sizeof(buffer), source, x);
|
||||
|
||||
Handle<JSFunction> fun = Compile(buffer);
|
||||
if (fun.is_null()) return -1;
|
||||
|
||||
bool has_pending_exception;
|
||||
Handle<JSObject> global(Top::context()->global());
|
||||
Execution::Call(fun, global, 0, NULL, &has_pending_exception);
|
||||
CHECK(!has_pending_exception);
|
||||
return GetGlobalProperty("result")->Number();
|
||||
}
|
||||
|
||||
|
||||
TEST(Inc) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
CHECK_EQ(4.0, Inc(3));
|
||||
}
|
||||
|
||||
|
||||
static double Add(int x, int y) {
|
||||
Handle<JSFunction> fun = Compile("result = x + y;");
|
||||
if (fun.is_null()) return -1;
|
||||
|
||||
SetGlobalProperty("x", Smi::FromInt(x));
|
||||
SetGlobalProperty("y", Smi::FromInt(y));
|
||||
bool has_pending_exception;
|
||||
Handle<JSObject> global(Top::context()->global());
|
||||
Execution::Call(fun, global, 0, NULL, &has_pending_exception);
|
||||
CHECK(!has_pending_exception);
|
||||
return GetGlobalProperty("result")->Number();
|
||||
}
|
||||
|
||||
|
||||
TEST(Add) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
CHECK_EQ(5.0, Add(2, 3));
|
||||
}
|
||||
|
||||
|
||||
static double Abs(int x) {
|
||||
Handle<JSFunction> fun = Compile("if (x < 0) result = -x; else result = x;");
|
||||
if (fun.is_null()) return -1;
|
||||
|
||||
SetGlobalProperty("x", Smi::FromInt(x));
|
||||
bool has_pending_exception;
|
||||
Handle<JSObject> global(Top::context()->global());
|
||||
Execution::Call(fun, global, 0, NULL, &has_pending_exception);
|
||||
CHECK(!has_pending_exception);
|
||||
return GetGlobalProperty("result")->Number();
|
||||
}
|
||||
|
||||
|
||||
TEST(Abs) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
CHECK_EQ(3.0, Abs(-3));
|
||||
}
|
||||
|
||||
|
||||
static double Sum(int n) {
|
||||
Handle<JSFunction> fun =
|
||||
Compile("s = 0; while (n > 0) { s += n; n -= 1; }; result = s;");
|
||||
if (fun.is_null()) return -1;
|
||||
|
||||
SetGlobalProperty("n", Smi::FromInt(n));
|
||||
bool has_pending_exception;
|
||||
Handle<JSObject> global(Top::context()->global());
|
||||
Execution::Call(fun, global, 0, NULL, &has_pending_exception);
|
||||
CHECK(!has_pending_exception);
|
||||
return GetGlobalProperty("result")->Number();
|
||||
}
|
||||
|
||||
|
||||
TEST(Sum) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
CHECK_EQ(5050.0, Sum(100));
|
||||
}
|
||||
|
||||
|
||||
TEST(Print) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
const char* source = "for (n = 0; n < 100; ++n) print(n, 1, 2);";
|
||||
Handle<JSFunction> fun = Compile(source);
|
||||
if (fun.is_null()) return;
|
||||
bool has_pending_exception;
|
||||
Handle<JSObject> global(Top::context()->global());
|
||||
Execution::Call(fun, global, 0, NULL, &has_pending_exception);
|
||||
CHECK(!has_pending_exception);
|
||||
}
|
||||
|
||||
|
||||
// The following test method stems from my coding efforts today. It
|
||||
// tests all the functionality I have added to the compiler today
|
||||
TEST(Stuff) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
const char* source =
|
||||
"r = 0;\n"
|
||||
"a = new Object;\n"
|
||||
"if (a == a) r+=1;\n" // 1
|
||||
"if (a != new Object()) r+=2;\n" // 2
|
||||
"a.x = 42;\n"
|
||||
"if (a.x == 42) r+=4;\n" // 4
|
||||
"function foo() { var x = 87; return x; }\n"
|
||||
"if (foo() == 87) r+=8;\n" // 8
|
||||
"function bar() { var x; x = 99; return x; }\n"
|
||||
"if (bar() == 99) r+=16;\n" // 16
|
||||
"function baz() { var x = 1, y, z = 2; y = 3; return x + y + z; }\n"
|
||||
"if (baz() == 6) r+=32;\n" // 32
|
||||
"function Cons0() { this.x = 42; this.y = 87; }\n"
|
||||
"if (new Cons0().x == 42) r+=64;\n" // 64
|
||||
"if (new Cons0().y == 87) r+=128;\n" // 128
|
||||
"function Cons2(x, y) { this.sum = x + y; }\n"
|
||||
"if (new Cons2(3,4).sum == 7) r+=256;"; // 256
|
||||
|
||||
Handle<JSFunction> fun = Compile(source);
|
||||
CHECK(!fun.is_null());
|
||||
bool has_pending_exception;
|
||||
Handle<JSObject> global(Top::context()->global());
|
||||
Execution::Call(fun, global, 0, NULL, &has_pending_exception);
|
||||
CHECK(!has_pending_exception);
|
||||
CHECK_EQ(511.0, GetGlobalProperty("r")->Number());
|
||||
}
|
||||
|
||||
|
||||
TEST(UncaughtThrow) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
const char* source = "throw 42;";
|
||||
Handle<JSFunction> fun = Compile(source);
|
||||
CHECK(!fun.is_null());
|
||||
bool has_pending_exception;
|
||||
Handle<JSObject> global(Top::context()->global());
|
||||
Handle<Object> result =
|
||||
Execution::Call(fun, global, 0, NULL, &has_pending_exception);
|
||||
CHECK(has_pending_exception);
|
||||
CHECK_EQ(42.0, Top::pending_exception()->Number());
|
||||
}
|
||||
|
||||
|
||||
// Tests calling a builtin function from C/C++ code, and the builtin function
|
||||
// performs GC. It creates a stack frame looks like following:
|
||||
// | C (PerformGC) |
|
||||
// | JS-to-C |
|
||||
// | JS |
|
||||
// | C-to-JS |
|
||||
TEST(C2JSFrames) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
const char* source = "function foo(a) { gc(), print(a); }";
|
||||
|
||||
Handle<JSFunction> fun0 = Compile(source);
|
||||
CHECK(!fun0.is_null());
|
||||
|
||||
// Run the generated code to populate the global object with 'foo'.
|
||||
bool has_pending_exception;
|
||||
Handle<JSObject> global(Top::context()->global());
|
||||
Execution::Call(fun0, global, 0, NULL, &has_pending_exception);
|
||||
CHECK(!has_pending_exception);
|
||||
|
||||
Handle<Object> fun1 =
|
||||
Handle<Object>(
|
||||
Top::context()->global()->GetProperty(
|
||||
*Factory::LookupAsciiSymbol("foo")));
|
||||
CHECK(fun1->IsJSFunction());
|
||||
|
||||
Object** argv[1] = {
|
||||
Handle<Object>::cast(Factory::LookupAsciiSymbol("hello")).location()
|
||||
};
|
||||
Execution::Call(Handle<JSFunction>::cast(fun1), global, 1, argv,
|
||||
&has_pending_exception);
|
||||
CHECK(!has_pending_exception);
|
||||
}
|
130
test/cctest/test-conversions.cc
Normal file
130
test/cctest/test-conversions.cc
Normal file
@ -0,0 +1,130 @@
|
||||
// Copyright 2006-2008 Google, Inc. All Rights Reserved.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
|
||||
TEST(Hex) {
|
||||
CHECK_EQ(0.0, StringToDouble("0x0", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(0.0, StringToDouble("0X0", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(1.0, StringToDouble("0x1", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(16.0, StringToDouble("0x10", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(255.0, StringToDouble("0xff", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(175.0, StringToDouble("0xAF", ALLOW_HEX | ALLOW_OCTALS));
|
||||
|
||||
CHECK_EQ(0.0, StringToDouble("0x0", ALLOW_HEX));
|
||||
CHECK_EQ(0.0, StringToDouble("0X0", ALLOW_HEX));
|
||||
CHECK_EQ(1.0, StringToDouble("0x1", ALLOW_HEX));
|
||||
CHECK_EQ(16.0, StringToDouble("0x10", ALLOW_HEX));
|
||||
CHECK_EQ(255.0, StringToDouble("0xff", ALLOW_HEX));
|
||||
CHECK_EQ(175.0, StringToDouble("0xAF", ALLOW_HEX));
|
||||
}
|
||||
|
||||
|
||||
TEST(Octal) {
|
||||
CHECK_EQ(0.0, StringToDouble("0", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(0.0, StringToDouble("00", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(1.0, StringToDouble("01", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(7.0, StringToDouble("07", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(8.0, StringToDouble("010", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(63.0, StringToDouble("077", ALLOW_HEX | ALLOW_OCTALS));
|
||||
|
||||
CHECK_EQ(0.0, StringToDouble("0", ALLOW_HEX));
|
||||
CHECK_EQ(0.0, StringToDouble("00", ALLOW_HEX));
|
||||
CHECK_EQ(1.0, StringToDouble("01", ALLOW_HEX));
|
||||
CHECK_EQ(7.0, StringToDouble("07", ALLOW_HEX));
|
||||
CHECK_EQ(10.0, StringToDouble("010", ALLOW_HEX));
|
||||
CHECK_EQ(77.0, StringToDouble("077", ALLOW_HEX));
|
||||
}
|
||||
|
||||
|
||||
TEST(MalformedOctal) {
|
||||
CHECK_EQ(8.0, StringToDouble("08", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(81.0, StringToDouble("081", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(78.0, StringToDouble("078", ALLOW_HEX | ALLOW_OCTALS));
|
||||
|
||||
CHECK(isnan(StringToDouble("07.7", ALLOW_HEX | ALLOW_OCTALS)));
|
||||
CHECK(isnan(StringToDouble("07.8", ALLOW_HEX | ALLOW_OCTALS)));
|
||||
CHECK(isnan(StringToDouble("07e8", ALLOW_HEX | ALLOW_OCTALS)));
|
||||
CHECK(isnan(StringToDouble("07e7", ALLOW_HEX | ALLOW_OCTALS)));
|
||||
|
||||
CHECK_EQ(8.7, StringToDouble("08.7", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(8e7, StringToDouble("08e7", ALLOW_HEX | ALLOW_OCTALS));
|
||||
|
||||
CHECK_EQ(0.001, StringToDouble("0.001", ALLOW_HEX | ALLOW_OCTALS));
|
||||
CHECK_EQ(0.713, StringToDouble("0.713", ALLOW_HEX | ALLOW_OCTALS));
|
||||
|
||||
CHECK_EQ(8.0, StringToDouble("08", ALLOW_HEX));
|
||||
CHECK_EQ(81.0, StringToDouble("081", ALLOW_HEX));
|
||||
CHECK_EQ(78.0, StringToDouble("078", ALLOW_HEX));
|
||||
|
||||
CHECK_EQ(7.7, StringToDouble("07.7", ALLOW_HEX));
|
||||
CHECK_EQ(7.8, StringToDouble("07.8", ALLOW_HEX));
|
||||
CHECK_EQ(7e8, StringToDouble("07e8", ALLOW_HEX));
|
||||
CHECK_EQ(7e7, StringToDouble("07e7", ALLOW_HEX));
|
||||
|
||||
CHECK_EQ(8.7, StringToDouble("08.7", ALLOW_HEX));
|
||||
CHECK_EQ(8e7, StringToDouble("08e7", ALLOW_HEX));
|
||||
|
||||
CHECK_EQ(0.001, StringToDouble("0.001", ALLOW_HEX));
|
||||
CHECK_EQ(0.713, StringToDouble("0.713", ALLOW_HEX));
|
||||
}
|
||||
|
||||
|
||||
TEST(TrailingJunk) {
|
||||
CHECK_EQ(8.0, StringToDouble("8q", ALLOW_TRAILING_JUNK));
|
||||
CHECK_EQ(63.0, StringToDouble("077qqq", ALLOW_OCTALS | ALLOW_TRAILING_JUNK));
|
||||
}
|
||||
|
||||
|
||||
TEST(NonStrDecimalLiteral) {
|
||||
CHECK(isnan(StringToDouble(" ", NO_FLAGS, OS::nan_value())));
|
||||
CHECK(isnan(StringToDouble("", NO_FLAGS, OS::nan_value())));
|
||||
CHECK(isnan(StringToDouble(" ", NO_FLAGS, OS::nan_value())));
|
||||
CHECK_EQ(0.0, StringToDouble("", NO_FLAGS));
|
||||
CHECK_EQ(0.0, StringToDouble(" ", NO_FLAGS));
|
||||
}
|
||||
|
||||
|
||||
TEST(BitField) {
|
||||
uint32_t x;
|
||||
|
||||
// One bit bit field can hold values 0 and 1.
|
||||
class OneBit1: public BitField<uint32_t, 0, 1> {};
|
||||
class OneBit2: public BitField<uint32_t, 7, 1> {};
|
||||
CHECK(!OneBit1::is_valid(static_cast<uint32_t>(-1)));
|
||||
CHECK(!OneBit2::is_valid(static_cast<uint32_t>(-1)));
|
||||
for (int i = 0; i < 2; i++) {
|
||||
CHECK(OneBit1::is_valid(i));
|
||||
x = OneBit1::encode(i);
|
||||
CHECK_EQ(i, OneBit1::decode(x));
|
||||
|
||||
CHECK(OneBit2::is_valid(i));
|
||||
x = OneBit2::encode(i);
|
||||
CHECK_EQ(i, OneBit2::decode(x));
|
||||
}
|
||||
CHECK(!OneBit1::is_valid(2));
|
||||
CHECK(!OneBit2::is_valid(2));
|
||||
|
||||
// Eight bit bit field can hold values from 0 tp 255.
|
||||
class EightBit1: public BitField<uint32_t, 0, 8> {};
|
||||
class EightBit2: public BitField<uint32_t, 13, 8> {};
|
||||
CHECK(!EightBit1::is_valid(static_cast<uint32_t>(-1)));
|
||||
CHECK(!EightBit2::is_valid(static_cast<uint32_t>(-1)));
|
||||
for (int i = 0; i < 256; i++) {
|
||||
CHECK(EightBit1::is_valid(i));
|
||||
x = EightBit1::encode(i);
|
||||
CHECK_EQ(i, EightBit1::decode(x));
|
||||
CHECK(EightBit2::is_valid(i));
|
||||
x = EightBit2::encode(i);
|
||||
CHECK_EQ(i, EightBit2::decode(x));
|
||||
}
|
||||
CHECK(!EightBit1::is_valid(256));
|
||||
CHECK(!EightBit2::is_valid(256));
|
||||
}
|
3148
test/cctest/test-debug.cc
Normal file
3148
test/cctest/test-debug.cc
Normal file
File diff suppressed because it is too large
Load Diff
594
test/cctest/test-decls.cc
Normal file
594
test/cctest/test-decls.cc
Normal file
@ -0,0 +1,594 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "heap.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
|
||||
enum Expectations {
|
||||
EXPECT_RESULT,
|
||||
EXPECT_EXCEPTION
|
||||
};
|
||||
|
||||
|
||||
// A DeclarationContext holds a reference to a v8::Context and keeps
|
||||
// track of various declaration related counters to make it easier to
|
||||
// track if global declarations in the presence of interceptors behave
|
||||
// the right way.
|
||||
class DeclarationContext {
|
||||
public:
|
||||
DeclarationContext();
|
||||
|
||||
virtual ~DeclarationContext() {
|
||||
if (is_initialized_) {
|
||||
context_->Exit();
|
||||
context_.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
void Check(const char* source,
|
||||
int get, int set, int has,
|
||||
Expectations expectations,
|
||||
v8::Handle<Value> value = Local<Value>());
|
||||
|
||||
int get_count() const { return get_count_; }
|
||||
int set_count() const { return set_count_; }
|
||||
int has_count() const { return has_count_; }
|
||||
|
||||
protected:
|
||||
virtual v8::Handle<Value> Get(Local<String> key);
|
||||
virtual v8::Handle<Value> Set(Local<String> key, Local<Value> value);
|
||||
virtual v8::Handle<Boolean> Has(Local<String> key);
|
||||
|
||||
void InitializeIfNeeded();
|
||||
|
||||
// Get the holder for the interceptor. Default to the instance template
|
||||
// but may be overwritten.
|
||||
virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
|
||||
return function->InstanceTemplate();
|
||||
}
|
||||
|
||||
// The handlers are called as static functions that forward
|
||||
// to the instance specific virtual methods.
|
||||
static v8::Handle<Value> HandleGet(Local<String> key,
|
||||
const AccessorInfo& info);
|
||||
static v8::Handle<Value> HandleSet(Local<String> key,
|
||||
Local<Value> value,
|
||||
const AccessorInfo& info);
|
||||
static v8::Handle<Boolean> HandleHas(Local<String> key,
|
||||
const AccessorInfo& info);
|
||||
|
||||
private:
|
||||
bool is_initialized_;
|
||||
Persistent<Context> context_;
|
||||
Local<String> property_;
|
||||
|
||||
int get_count_;
|
||||
int set_count_;
|
||||
int has_count_;
|
||||
|
||||
static DeclarationContext* GetInstance(const AccessorInfo& info);
|
||||
};
|
||||
|
||||
|
||||
DeclarationContext::DeclarationContext()
|
||||
: is_initialized_(false), get_count_(0), set_count_(0), has_count_(0) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
|
||||
void DeclarationContext::InitializeIfNeeded() {
|
||||
if (is_initialized_) return;
|
||||
HandleScope scope;
|
||||
Local<FunctionTemplate> function = FunctionTemplate::New();
|
||||
Local<Value> data = Integer::New(reinterpret_cast<intptr_t>(this));
|
||||
GetHolder(function)->SetNamedPropertyHandler(&HandleGet,
|
||||
&HandleSet,
|
||||
&HandleHas,
|
||||
0, 0,
|
||||
data);
|
||||
context_ = Context::New(0, function->InstanceTemplate(), Local<Value>());
|
||||
context_->Enter();
|
||||
is_initialized_ = true;
|
||||
}
|
||||
|
||||
|
||||
void DeclarationContext::Check(const char* source,
|
||||
int get, int set, int has,
|
||||
Expectations expectations,
|
||||
v8::Handle<Value> value) {
|
||||
InitializeIfNeeded();
|
||||
// A retry after a GC may pollute the counts, so perform gc now
|
||||
// to avoid that.
|
||||
v8::internal::Heap::CollectGarbage(0, v8::internal::NEW_SPACE);
|
||||
HandleScope scope;
|
||||
TryCatch catcher;
|
||||
catcher.SetVerbose(true);
|
||||
Local<Value> result = Script::Compile(String::New(source))->Run();
|
||||
CHECK_EQ(get, get_count());
|
||||
CHECK_EQ(set, set_count());
|
||||
CHECK_EQ(has, has_count());
|
||||
if (expectations == EXPECT_RESULT) {
|
||||
CHECK(!catcher.HasCaught());
|
||||
if (!value.IsEmpty()) {
|
||||
CHECK_EQ(value, result);
|
||||
}
|
||||
} else {
|
||||
CHECK(expectations == EXPECT_EXCEPTION);
|
||||
CHECK(catcher.HasCaught());
|
||||
if (!value.IsEmpty()) {
|
||||
CHECK_EQ(value, catcher.Exception());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<Value> DeclarationContext::HandleGet(Local<String> key,
|
||||
const AccessorInfo& info) {
|
||||
DeclarationContext* context = GetInstance(info);
|
||||
context->get_count_++;
|
||||
return context->Get(key);
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<Value> DeclarationContext::HandleSet(Local<String> key,
|
||||
Local<Value> value,
|
||||
const AccessorInfo& info) {
|
||||
DeclarationContext* context = GetInstance(info);
|
||||
context->set_count_++;
|
||||
return context->Set(key, value);
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<Boolean> DeclarationContext::HandleHas(Local<String> key,
|
||||
const AccessorInfo& info) {
|
||||
DeclarationContext* context = GetInstance(info);
|
||||
context->has_count_++;
|
||||
return context->Has(key);
|
||||
}
|
||||
|
||||
|
||||
DeclarationContext* DeclarationContext::GetInstance(const AccessorInfo& info) {
|
||||
Local<Value> data = info.Data();
|
||||
return reinterpret_cast<DeclarationContext*>(Int32::Cast(*data)->Value());
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<Value> DeclarationContext::Get(Local<String> key) {
|
||||
return v8::Handle<Value>();
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<Value> DeclarationContext::Set(Local<String> key,
|
||||
Local<Value> value) {
|
||||
return v8::Handle<Value>();
|
||||
}
|
||||
|
||||
|
||||
v8::Handle<Boolean> DeclarationContext::Has(Local<String> key) {
|
||||
return v8::Handle<Boolean>();
|
||||
}
|
||||
|
||||
|
||||
// Test global declaration of a property the interceptor doesn't know
|
||||
// about and doesn't handle.
|
||||
TEST(Unknown) {
|
||||
HandleScope scope;
|
||||
|
||||
{ DeclarationContext context;
|
||||
context.Check("var x; x",
|
||||
1, // access
|
||||
1, // declaration
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
{ DeclarationContext context;
|
||||
context.Check("var x = 0; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Number::New(0));
|
||||
}
|
||||
|
||||
{ DeclarationContext context;
|
||||
context.Check("function x() { }; x",
|
||||
1, // access
|
||||
1, // declaration
|
||||
0,
|
||||
EXPECT_RESULT);
|
||||
}
|
||||
|
||||
{ DeclarationContext context;
|
||||
context.Check("const x; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
{ DeclarationContext context;
|
||||
context.Check("const x = 0; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class PresentPropertyContext: public DeclarationContext {
|
||||
protected:
|
||||
virtual v8::Handle<Boolean> Has(Local<String> key) {
|
||||
return True();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
TEST(Present) {
|
||||
HandleScope scope;
|
||||
|
||||
{ PresentPropertyContext context;
|
||||
context.Check("var x; x",
|
||||
1, // access
|
||||
0,
|
||||
2, // declaration + initialization
|
||||
EXPECT_EXCEPTION); // x is not defined!
|
||||
}
|
||||
|
||||
{ PresentPropertyContext context;
|
||||
context.Check("var x = 0; x",
|
||||
1, // access
|
||||
1, // initialization
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Number::New(0));
|
||||
}
|
||||
|
||||
{ PresentPropertyContext context;
|
||||
context.Check("function x() { }; x",
|
||||
1, // access
|
||||
1, // declaration
|
||||
0,
|
||||
EXPECT_RESULT);
|
||||
}
|
||||
|
||||
{ PresentPropertyContext context;
|
||||
context.Check("const x; x",
|
||||
0,
|
||||
0,
|
||||
1, // (re-)declaration
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
}
|
||||
|
||||
{ PresentPropertyContext context;
|
||||
context.Check("const x = 0; x",
|
||||
0,
|
||||
0,
|
||||
1, // (re-)declaration
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class AbsentPropertyContext: public DeclarationContext {
|
||||
protected:
|
||||
virtual v8::Handle<Boolean> Has(Local<String> key) {
|
||||
return False();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(Absent) {
|
||||
HandleScope scope;
|
||||
|
||||
{ AbsentPropertyContext context;
|
||||
context.Check("var x; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
{ AbsentPropertyContext context;
|
||||
context.Check("var x = 0; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Number::New(0));
|
||||
}
|
||||
|
||||
{ AbsentPropertyContext context;
|
||||
context.Check("function x() { }; x",
|
||||
1, // access
|
||||
1, // declaration
|
||||
0,
|
||||
EXPECT_RESULT);
|
||||
}
|
||||
|
||||
{ AbsentPropertyContext context;
|
||||
context.Check("const x; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initializetion
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
{ AbsentPropertyContext context;
|
||||
context.Check("const x = 0; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Undefined()); // SB 0 - BUG 1213579
|
||||
}
|
||||
|
||||
{ AbsentPropertyContext context;
|
||||
context.Check("if (false) { var x = 0 }; x",
|
||||
1, // access
|
||||
1, // declaration
|
||||
1, // declaration + initialization
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class AppearingPropertyContext: public DeclarationContext {
|
||||
public:
|
||||
enum State {
|
||||
DECLARE,
|
||||
INITIALIZE_IF_ASSIGN,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
AppearingPropertyContext() : state_(DECLARE) { }
|
||||
|
||||
protected:
|
||||
virtual v8::Handle<Boolean> Has(Local<String> key) {
|
||||
switch (state_) {
|
||||
case DECLARE:
|
||||
// Force declaration by returning that the
|
||||
// property is absent.
|
||||
state_ = INITIALIZE_IF_ASSIGN;
|
||||
return False();
|
||||
case INITIALIZE_IF_ASSIGN:
|
||||
// Return that the property is present so we only get the
|
||||
// setter called when initializing with a value.
|
||||
state_ = UNKNOWN;
|
||||
return True();
|
||||
default:
|
||||
ASSERT(state_ == UNKNOWN);
|
||||
break;
|
||||
}
|
||||
// Do the lookup in the object.
|
||||
return v8::Local<Boolean>();
|
||||
}
|
||||
|
||||
private:
|
||||
State state_;
|
||||
};
|
||||
|
||||
|
||||
TEST(Appearing) {
|
||||
HandleScope scope;
|
||||
|
||||
{ AppearingPropertyContext context;
|
||||
context.Check("var x; x",
|
||||
1, // access
|
||||
1, // declaration
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
{ AppearingPropertyContext context;
|
||||
context.Check("var x = 0; x",
|
||||
1, // access
|
||||
2, // declaration + initialization
|
||||
2, // declaration + initialization
|
||||
EXPECT_RESULT, Number::New(0));
|
||||
}
|
||||
|
||||
{ AppearingPropertyContext context;
|
||||
context.Check("function x() { }; x",
|
||||
1, // access
|
||||
1, // declaration
|
||||
0,
|
||||
EXPECT_RESULT);
|
||||
}
|
||||
|
||||
{ AppearingPropertyContext context;
|
||||
context.Check("const x; x",
|
||||
0,
|
||||
1, // declaration
|
||||
2, // declaration + initialization
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
}
|
||||
|
||||
{ AppearingPropertyContext context;
|
||||
context.Check("const x = 0; x",
|
||||
0,
|
||||
1, // declaration
|
||||
2, // declaration + initialization
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ReappearingPropertyContext: public DeclarationContext {
|
||||
public:
|
||||
enum State {
|
||||
DECLARE,
|
||||
DONT_DECLARE,
|
||||
INITIALIZE,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
ReappearingPropertyContext() : state_(DECLARE) { }
|
||||
|
||||
protected:
|
||||
virtual v8::Handle<Boolean> Has(Local<String> key) {
|
||||
switch (state_) {
|
||||
case DECLARE:
|
||||
// Force the first declaration by returning that
|
||||
// the property is absent.
|
||||
state_ = DONT_DECLARE;
|
||||
return False();
|
||||
case DONT_DECLARE:
|
||||
// Ignore the second declaration by returning
|
||||
// that the property is already there.
|
||||
state_ = INITIALIZE;
|
||||
return True();
|
||||
case INITIALIZE:
|
||||
// Force an initialization by returning that
|
||||
// the property is absent. This will make sure
|
||||
// that the setter is called and it will not
|
||||
// lead to redeclaration conflicts (yet).
|
||||
state_ = UNKNOWN;
|
||||
return False();
|
||||
default:
|
||||
ASSERT(state_ == UNKNOWN);
|
||||
break;
|
||||
}
|
||||
// Do the lookup in the object.
|
||||
return v8::Local<Boolean>();
|
||||
}
|
||||
|
||||
private:
|
||||
State state_;
|
||||
};
|
||||
|
||||
|
||||
TEST(Reappearing) {
|
||||
HandleScope scope;
|
||||
|
||||
{ ReappearingPropertyContext context;
|
||||
context.Check("const x; var x = 0",
|
||||
0,
|
||||
2, // var declaration + const initialization
|
||||
4, // 2 x declaration + 2 x initialization
|
||||
EXPECT_EXCEPTION); // x has already been declared!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ExistsInPrototypeContext: public DeclarationContext {
|
||||
protected:
|
||||
virtual v8::Handle<Boolean> Has(Local<String> key) {
|
||||
// Let it seem that the property exists in the prototype object.
|
||||
return True();
|
||||
}
|
||||
|
||||
// Use the prototype as the holder for the interceptors.
|
||||
virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
|
||||
return function->PrototypeTemplate();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(ExistsInPrototype) {
|
||||
HandleScope scope;
|
||||
|
||||
// Sanity check to make sure that the holder of the interceptor
|
||||
// really is the prototype object.
|
||||
{ ExistsInPrototypeContext context;
|
||||
context.Check("this.x = 87; this.x",
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
EXPECT_RESULT, Number::New(87));
|
||||
}
|
||||
|
||||
{ ExistsInPrototypeContext context;
|
||||
context.Check("var x; x",
|
||||
0,
|
||||
0,
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
{ ExistsInPrototypeContext context;
|
||||
context.Check("var x = 0; x",
|
||||
0,
|
||||
0,
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Number::New(0));
|
||||
}
|
||||
|
||||
{ ExistsInPrototypeContext context;
|
||||
context.Check("const x; x",
|
||||
0,
|
||||
0,
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
|
||||
{ ExistsInPrototypeContext context;
|
||||
context.Check("const x = 0; x",
|
||||
0,
|
||||
0,
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Number::New(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class AbsentInPrototypeContext: public DeclarationContext {
|
||||
protected:
|
||||
virtual v8::Handle<Boolean> Has(Local<String> key) {
|
||||
// Let it seem that the property is absent in the prototype object.
|
||||
return False();
|
||||
}
|
||||
|
||||
// Use the prototype as the holder for the interceptors.
|
||||
virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
|
||||
return function->PrototypeTemplate();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
TEST(AbsentInPrototype) {
|
||||
HandleScope scope;
|
||||
|
||||
{ AbsentInPrototypeContext context;
|
||||
context.Check("if (false) { var x = 0; }; x",
|
||||
0,
|
||||
0,
|
||||
1, // declaration
|
||||
EXPECT_RESULT, Undefined());
|
||||
}
|
||||
}
|
272
test/cctest/test-disasm-arm.cc
Normal file
272
test/cctest/test-disasm-arm.cc
Normal file
@ -0,0 +1,272 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "disasm.h"
|
||||
#include "disassembler.h"
|
||||
#include "macro-assembler.h"
|
||||
#include "serialize.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
|
||||
static v8::Persistent<v8::Context> env;
|
||||
|
||||
static void InitializeVM() {
|
||||
if (env.IsEmpty()) {
|
||||
env = v8::Context::New();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DisassembleAndCompare(byte* pc, const char* compare_string) {
|
||||
disasm::Disassembler disasm;
|
||||
char disasm_buffer[128];
|
||||
|
||||
disasm.InstructionDecode(disasm_buffer, sizeof disasm_buffer, pc);
|
||||
|
||||
if (strcmp(compare_string, disasm_buffer) != 0) {
|
||||
fprintf(stderr,
|
||||
"expected: \n"
|
||||
"%s\n"
|
||||
"disassembled: \n"
|
||||
"%s\n\n",
|
||||
compare_string, disasm_buffer);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#define SETUP() \
|
||||
InitializeVM(); \
|
||||
Serializer::disable(); \
|
||||
v8::HandleScope scope; \
|
||||
byte *buffer = reinterpret_cast<byte*>(malloc(4*1024)); \
|
||||
Assembler assm(buffer, 4*1024); \
|
||||
bool failure = false;
|
||||
|
||||
|
||||
#define COMPARE(asm_, compare_string) \
|
||||
{ \
|
||||
int pc_offset = assm.pc_offset(); \
|
||||
byte *pc = &buffer[pc_offset]; \
|
||||
assm.asm_; \
|
||||
if (!DisassembleAndCompare(pc, compare_string)) failure = true; \
|
||||
}
|
||||
|
||||
|
||||
#define OUTPUT() \
|
||||
if (failure) { \
|
||||
V8_Fatal(__FILE__, __LINE__, "ARM Disassembler tests failed.\n"); \
|
||||
}
|
||||
|
||||
|
||||
TEST(Type0) {
|
||||
SETUP();
|
||||
|
||||
COMPARE(and_(r0, r1, Operand(r2)),
|
||||
"e0010002 and r0, r1, r2");
|
||||
COMPARE(and_(r1, r2, Operand(r3), LeaveCC),
|
||||
"e0021003 and r1, r2, r3");
|
||||
COMPARE(and_(r2, r3, Operand(r4), SetCC),
|
||||
"e0132004 ands r2, r3, r4");
|
||||
COMPARE(and_(r3, r4, Operand(r5), LeaveCC, eq),
|
||||
"00043005 andeq r3, r4, r5");
|
||||
|
||||
COMPARE(eor(r4, r5, Operand(r6, LSL, 0)),
|
||||
"e0254006 eor r4, r5, r6");
|
||||
COMPARE(eor(r4, r5, Operand(r7, LSL, 1), SetCC),
|
||||
"e0354087 eors r4, r5, r7, lsl #1");
|
||||
COMPARE(eor(r4, r5, Operand(r8, LSL, 2), LeaveCC, ne),
|
||||
"10254108 eorne r4, r5, r8, lsl #2");
|
||||
COMPARE(eor(r4, r5, Operand(r9, LSL, 3), SetCC, cs),
|
||||
"20354189 eorcss r4, r5, r9, lsl #3");
|
||||
|
||||
COMPARE(sub(r5, r6, Operand(r10, LSL, 31), LeaveCC, hs),
|
||||
"20465f8a subcs r5, r6, sl, lsl #31");
|
||||
COMPARE(sub(r5, r6, Operand(r10, LSL, 30), SetCC, cc),
|
||||
"30565f0a subccs r5, r6, sl, lsl #30");
|
||||
COMPARE(sub(r5, r6, Operand(r10, LSL, 24), LeaveCC, lo),
|
||||
"30465c0a subcc r5, r6, sl, lsl #24");
|
||||
COMPARE(sub(r5, r6, Operand(r10, LSL, 16), SetCC, mi),
|
||||
"4056580a submis r5, r6, sl, lsl #16");
|
||||
|
||||
COMPARE(rsb(r6, r7, Operand(fp)),
|
||||
"e067600b rsb r6, r7, fp");
|
||||
COMPARE(rsb(r6, r7, Operand(fp, LSR, 1)),
|
||||
"e06760ab rsb r6, r7, fp, lsr #1");
|
||||
COMPARE(rsb(r6, r7, Operand(fp, LSR, 0), SetCC),
|
||||
"e077602b rsbs r6, r7, fp, lsr #32");
|
||||
COMPARE(rsb(r6, r7, Operand(fp, LSR, 31), LeaveCC, pl),
|
||||
"50676fab rsbpl r6, r7, fp, lsr #31");
|
||||
|
||||
COMPARE(add(r7, r8, Operand(ip, ASR, 1)),
|
||||
"e08870cc add r7, r8, ip, asr #1");
|
||||
COMPARE(add(r7, r8, Operand(ip, ASR, 0)),
|
||||
"e088704c add r7, r8, ip, asr #32");
|
||||
COMPARE(add(r7, r8, Operand(ip), SetCC),
|
||||
"e098700c adds r7, r8, ip");
|
||||
COMPARE(add(r7, r8, Operand(ip, ASR, 31), SetCC, vs),
|
||||
"60987fcc addvss r7, r8, ip, asr #31");
|
||||
|
||||
COMPARE(adc(r7, fp, Operand(ip, ASR, 5)),
|
||||
"e0ab72cc adc r7, fp, ip, asr #5");
|
||||
COMPARE(adc(r4, ip, Operand(ip, ASR, 1), LeaveCC, vc),
|
||||
"70ac40cc adcvc r4, ip, ip, asr #1");
|
||||
COMPARE(adc(r5, sp, Operand(ip), SetCC),
|
||||
"e0bd500c adcs r5, sp, ip");
|
||||
COMPARE(adc(r8, lr, Operand(ip, ASR, 31), SetCC, vc),
|
||||
"70be8fcc adcvcs r8, lr, ip, asr #31");
|
||||
|
||||
COMPARE(sbc(r7, r1, Operand(ip, ROR, 1), LeaveCC, hi),
|
||||
"80c170ec sbchi r7, r1, ip, ror #1");
|
||||
COMPARE(sbc(r7, r9, Operand(ip, ROR, 4)),
|
||||
"e0c9726c sbc r7, r9, ip, ror #4");
|
||||
COMPARE(sbc(r7, r10, Operand(ip), SetCC),
|
||||
"e0da700c sbcs r7, sl, ip");
|
||||
COMPARE(sbc(r7, ip, Operand(ip, ROR, 31), SetCC, hi),
|
||||
"80dc7fec sbchis r7, ip, ip, ror #31");
|
||||
|
||||
COMPARE(rsc(r7, r8, Operand(ip, LSL, r0)),
|
||||
"e0e8701c rsc r7, r8, ip, lsl r0");
|
||||
COMPARE(rsc(r7, r8, Operand(ip, LSL, r1)),
|
||||
"e0e8711c rsc r7, r8, ip, lsl r1");
|
||||
COMPARE(rsc(r7, r8, Operand(ip), SetCC),
|
||||
"e0f8700c rscs r7, r8, ip");
|
||||
COMPARE(rsc(r7, r8, Operand(ip, LSL, r3), SetCC, ls),
|
||||
"90f8731c rsclss r7, r8, ip, lsl r3");
|
||||
|
||||
COMPARE(tst(r7, Operand(r5, ASR, ip), ge),
|
||||
"a1170c55 tstge r7, r5, asr ip");
|
||||
COMPARE(tst(r7, Operand(r6, ASR, sp)),
|
||||
"e1170d56 tst r7, r6, asr sp");
|
||||
COMPARE(tst(r7, Operand(r7), ge),
|
||||
"a1170007 tstge r7, r7");
|
||||
COMPARE(tst(r7, Operand(r8, ASR, fp), ge),
|
||||
"a1170b58 tstge r7, r8, asr fp");
|
||||
|
||||
COMPARE(teq(r7, Operand(r5, ROR, r0), lt),
|
||||
"b1370075 teqlt r7, r5, ror r0");
|
||||
COMPARE(teq(r7, Operand(r6, ROR, lr)),
|
||||
"e1370e76 teq r7, r6, ror lr");
|
||||
COMPARE(teq(r7, Operand(r7), lt),
|
||||
"b1370007 teqlt r7, r7");
|
||||
COMPARE(teq(r7, Operand(r8, ROR, r1)),
|
||||
"e1370178 teq r7, r8, ror r1");
|
||||
|
||||
COMPARE(cmp(r7, Operand(r4)),
|
||||
"e1570004 cmp r7, r4");
|
||||
COMPARE(cmp(r7, Operand(r6, LSL, 1), gt),
|
||||
"c1570086 cmpgt r7, r6, lsl #1");
|
||||
COMPARE(cmp(r7, Operand(r8, LSR, 3), gt),
|
||||
"c15701a8 cmpgt r7, r8, lsr #3");
|
||||
COMPARE(cmp(r7, Operand(r8, ASR, 19)),
|
||||
"e15709c8 cmp r7, r8, asr #19");
|
||||
|
||||
COMPARE(cmn(r0, Operand(r4)),
|
||||
"e1700004 cmn r0, r4");
|
||||
COMPARE(cmn(r1, Operand(r6, ROR, 1)),
|
||||
"e17100e6 cmn r1, r6, ror #1");
|
||||
COMPARE(cmn(r2, Operand(r8)),
|
||||
"e1720008 cmn r2, r8");
|
||||
COMPARE(cmn(r3, Operand(fp), le),
|
||||
"d173000b cmnle r3, fp");
|
||||
|
||||
COMPARE(orr(r7, r8, Operand(lr), LeaveCC, al),
|
||||
"e188700e orr r7, r8, lr");
|
||||
COMPARE(orr(r7, r8, Operand(fp)),
|
||||
"e188700b orr r7, r8, fp");
|
||||
COMPARE(orr(r7, r8, Operand(sp), SetCC),
|
||||
"e198700d orrs r7, r8, sp");
|
||||
COMPARE(orr(r7, r8, Operand(ip), SetCC, al),
|
||||
"e198700c orrs r7, r8, ip");
|
||||
|
||||
COMPARE(mov(r0, Operand(r1), LeaveCC, eq),
|
||||
"01a00001 moveq r0, r1");
|
||||
COMPARE(mov(r0, Operand(r2)),
|
||||
"e1a00002 mov r0, r2");
|
||||
COMPARE(mov(r0, Operand(r3), SetCC),
|
||||
"e1b00003 movs r0, r3");
|
||||
COMPARE(mov(r0, Operand(r4), SetCC, pl),
|
||||
"51b00004 movpls r0, r4");
|
||||
|
||||
COMPARE(bic(r0, lr, Operand(r1), LeaveCC, vs),
|
||||
"61ce0001 bicvs r0, lr, r1");
|
||||
COMPARE(bic(r0, r9, Operand(r2), LeaveCC, vc),
|
||||
"71c90002 bicvc r0, r9, r2");
|
||||
COMPARE(bic(r0, r5, Operand(r3), SetCC),
|
||||
"e1d50003 bics r0, r5, r3");
|
||||
COMPARE(bic(r0, r1, Operand(r4), SetCC, pl),
|
||||
"51d10004 bicpls r0, r1, r4");
|
||||
|
||||
COMPARE(mvn(r10, Operand(r1)),
|
||||
"e1e0a001 mvn sl, r1");
|
||||
COMPARE(mvn(r9, Operand(r2)),
|
||||
"e1e09002 mvn r9, r2");
|
||||
COMPARE(mvn(r0, Operand(r3), SetCC),
|
||||
"e1f00003 mvns r0, r3");
|
||||
COMPARE(mvn(r5, Operand(r4), SetCC, cc),
|
||||
"31f05004 mvnccs r5, r4");
|
||||
|
||||
OUTPUT();
|
||||
}
|
||||
|
||||
|
||||
TEST(Type1) {
|
||||
SETUP();
|
||||
|
||||
COMPARE(and_(r0, r1, Operand(0x00000000)),
|
||||
"e2010000 and r0, r1, #0");
|
||||
COMPARE(and_(r1, r2, Operand(0x00000001), LeaveCC),
|
||||
"e2021001 and r1, r2, #1");
|
||||
COMPARE(and_(r2, r3, Operand(0x00000010), SetCC),
|
||||
"e2132010 ands r2, r3, #16");
|
||||
COMPARE(and_(r3, r4, Operand(0x00000100), LeaveCC, eq),
|
||||
"02043c01 andeq r3, r4, #256");
|
||||
COMPARE(and_(r4, r5, Operand(0x00001000), SetCC, ne),
|
||||
"12154a01 andnes r4, r5, #4096");
|
||||
|
||||
COMPARE(eor(r4, r5, Operand(0x00001000)),
|
||||
"e2254a01 eor r4, r5, #4096");
|
||||
COMPARE(eor(r4, r4, Operand(0x00010000), LeaveCC),
|
||||
"e2244801 eor r4, r4, #65536");
|
||||
COMPARE(eor(r4, r3, Operand(0x00100000), SetCC),
|
||||
"e2334601 eors r4, r3, #1048576");
|
||||
COMPARE(eor(r4, r2, Operand(0x01000000), LeaveCC, cs),
|
||||
"22224401 eorcs r4, r2, #16777216");
|
||||
COMPARE(eor(r4, r1, Operand(0x10000000), SetCC, cc),
|
||||
"32314201 eorccs r4, r1, #268435456");
|
||||
|
||||
OUTPUT();
|
||||
}
|
383
test/cctest/test-disasm-ia32.cc
Normal file
383
test/cctest/test-disasm-ia32.cc
Normal file
@ -0,0 +1,383 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "disasm.h"
|
||||
#include "disassembler.h"
|
||||
#include "macro-assembler.h"
|
||||
#include "serialize.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
static v8::Persistent<v8::Context> env;
|
||||
|
||||
static void InitializeVM() {
|
||||
if (env.IsEmpty()) {
|
||||
env = v8::Context::New();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define __ assm.
|
||||
|
||||
|
||||
static void DummyStaticFunction(Object* result) {
|
||||
}
|
||||
|
||||
|
||||
TEST(DisasmIa320) {
|
||||
InitializeVM();
|
||||
Serializer::disable(); // Needed for Probe when running without snapshot.
|
||||
CpuFeatures::Probe();
|
||||
v8::HandleScope scope;
|
||||
v8::internal::byte buffer[1024];
|
||||
Assembler assm(buffer, sizeof buffer);
|
||||
DummyStaticFunction(NULL); // just bloody use it (DELETE; debugging)
|
||||
|
||||
// Short immediate instructions
|
||||
__ adc(eax, 12345678);
|
||||
__ add(Operand(eax), Immediate(12345678));
|
||||
__ or_(eax, 12345678);
|
||||
__ sub(Operand(eax), Immediate(12345678));
|
||||
__ xor_(eax, 12345678);
|
||||
__ and_(eax, 12345678);
|
||||
Handle<FixedArray> foo = Factory::NewFixedArray(10, TENURED);
|
||||
__ cmp(eax, foo);
|
||||
|
||||
// ---- This one caused crash
|
||||
__ mov(ebx, Operand(esp, ecx, times_2, 0)); // [esp+ecx*4]
|
||||
|
||||
// ---- All instructions that I can think of
|
||||
__ add(edx, Operand(ebx));
|
||||
__ add(edx, Operand(12, no_reloc));
|
||||
__ add(edx, Operand(ebx, 0));
|
||||
__ add(edx, Operand(ebx, 16));
|
||||
__ add(edx, Operand(ebx, 1999));
|
||||
__ add(edx, Operand(esp, 0));
|
||||
__ add(edx, Operand(esp, 16));
|
||||
__ add(edx, Operand(esp, 1999));
|
||||
__ nop();
|
||||
__ add(edi, Operand(ebp, ecx, times_4, 0));
|
||||
__ add(edi, Operand(ebp, ecx, times_4, 12));
|
||||
__ add(Operand(ebp, ecx, times_4, 12), Immediate(12));
|
||||
|
||||
__ nop();
|
||||
__ add(Operand(ebx), Immediate(12));
|
||||
__ nop();
|
||||
__ adc(ecx, 12);
|
||||
__ adc(ecx, 1000);
|
||||
__ nop();
|
||||
__ and_(edx, 3);
|
||||
__ and_(edx, Operand(esp, 4));
|
||||
__ cmp(edx, 3);
|
||||
__ cmp(edx, Operand(esp, 4));
|
||||
__ cmp(Operand(ebp, ecx, times_4, 0), Immediate(1000));
|
||||
Handle<FixedArray> foo2 = Factory::NewFixedArray(10, TENURED);
|
||||
__ cmp(ebx, foo2);
|
||||
__ or_(edx, 3);
|
||||
__ xor_(edx, 3);
|
||||
__ nop();
|
||||
{
|
||||
CHECK(CpuFeatures::IsSupported(CpuFeatures::CPUID));
|
||||
CpuFeatures::Scope fscope(CpuFeatures::CPUID);
|
||||
__ cpuid();
|
||||
}
|
||||
{
|
||||
CHECK(CpuFeatures::IsSupported(CpuFeatures::RDTSC));
|
||||
CpuFeatures::Scope fscope(CpuFeatures::RDTSC);
|
||||
__ rdtsc();
|
||||
}
|
||||
__ movsx_b(edx, Operand(ecx));
|
||||
__ movsx_w(edx, Operand(ecx));
|
||||
__ movzx_b(edx, Operand(ecx));
|
||||
__ movzx_w(edx, Operand(ecx));
|
||||
|
||||
__ nop();
|
||||
__ imul(edx, Operand(ecx));
|
||||
__ shld(edx, Operand(ecx));
|
||||
__ shrd(edx, Operand(ecx));
|
||||
__ bts(Operand(edx), ecx);
|
||||
__ bts(Operand(ebx, ecx, times_4, 0), ecx);
|
||||
__ nop();
|
||||
__ pushad();
|
||||
__ popad();
|
||||
__ pushfd();
|
||||
__ popfd();
|
||||
__ push(Immediate(12));
|
||||
__ push(Immediate(23456));
|
||||
__ push(ecx);
|
||||
__ push(esi);
|
||||
__ push(Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
|
||||
__ push(Operand(ebx, ecx, times_4, 0));
|
||||
__ push(Operand(ebx, ecx, times_4, 0));
|
||||
__ push(Operand(ebx, ecx, times_4, 10000));
|
||||
__ pop(edx);
|
||||
__ pop(eax);
|
||||
__ pop(Operand(ebx, ecx, times_4, 0));
|
||||
__ nop();
|
||||
|
||||
__ add(edx, Operand(esp, 16));
|
||||
__ add(edx, Operand(ecx));
|
||||
__ mov_b(edx, Operand(ecx));
|
||||
__ mov_b(Operand(ecx), 6);
|
||||
__ mov_b(Operand(ebx, ecx, times_4, 10000), 6);
|
||||
__ mov_b(Operand(esp, 16), edx);
|
||||
__ mov_w(edx, Operand(esp, 16));
|
||||
__ mov_w(Operand(esp, 16), edx);
|
||||
__ nop();
|
||||
__ movsx_w(edx, Operand(esp, 12));
|
||||
__ movsx_b(edx, Operand(esp, 12));
|
||||
__ movzx_w(edx, Operand(esp, 12));
|
||||
__ movzx_b(edx, Operand(esp, 12));
|
||||
__ nop();
|
||||
__ mov(edx, 1234567);
|
||||
__ mov(edx, Operand(esp, 12));
|
||||
__ mov(Operand(ebx, ecx, times_4, 10000), Immediate(12345));
|
||||
__ mov(Operand(ebx, ecx, times_4, 10000), edx);
|
||||
__ nop();
|
||||
__ dec_b(edx);
|
||||
__ dec(edx);
|
||||
__ cdq();
|
||||
|
||||
__ nop();
|
||||
__ idiv(edx);
|
||||
__ mul(edx);
|
||||
__ neg(edx);
|
||||
__ not_(edx);
|
||||
__ test(Operand(ebx, ecx, times_4, 10000), Immediate(123456));
|
||||
|
||||
__ imul(edx, Operand(ebx, ecx, times_4, 10000));
|
||||
__ imul(edx, ecx, 12);
|
||||
__ imul(edx, ecx, 1000);
|
||||
|
||||
__ inc(edx);
|
||||
__ inc(Operand(ebx, ecx, times_4, 10000));
|
||||
__ push(Operand(ebx, ecx, times_4, 10000));
|
||||
__ pop(Operand(ebx, ecx, times_4, 10000));
|
||||
__ call(Operand(ebx, ecx, times_4, 10000));
|
||||
__ jmp(Operand(ebx, ecx, times_4, 10000));
|
||||
|
||||
__ lea(edx, Operand(ebx, ecx, times_4, 10000));
|
||||
__ or_(edx, 12345);
|
||||
__ or_(edx, Operand(ebx, ecx, times_4, 10000));
|
||||
|
||||
__ nop();
|
||||
|
||||
__ rcl(edx, 1);
|
||||
__ rcl(edx, 7);
|
||||
__ sar(edx, 1);
|
||||
__ sar(edx, 6);
|
||||
__ sar(edx);
|
||||
__ sbb(edx, Operand(ebx, ecx, times_4, 10000));
|
||||
__ shld(edx, Operand(ebx, ecx, times_4, 10000));
|
||||
__ shl(edx, 1);
|
||||
__ shl(edx, 6);
|
||||
__ shl(edx);
|
||||
__ shrd(edx, Operand(ebx, ecx, times_4, 10000));
|
||||
__ shr(edx, 7);
|
||||
__ shr(edx);
|
||||
|
||||
|
||||
// Immediates
|
||||
|
||||
__ adc(edx, 12345);
|
||||
|
||||
__ add(Operand(ebx), Immediate(12));
|
||||
__ add(Operand(edx, ecx, times_4, 10000), Immediate(12));
|
||||
|
||||
__ and_(ebx, 12345);
|
||||
|
||||
__ cmp(ebx, 12345);
|
||||
__ cmp(Operand(ebx), Immediate(12));
|
||||
__ cmp(Operand(edx, ecx, times_4, 10000), Immediate(12));
|
||||
|
||||
__ or_(ebx, 12345);
|
||||
|
||||
__ sub(Operand(ebx), Immediate(12));
|
||||
__ sub(Operand(edx, ecx, times_4, 10000), Immediate(12));
|
||||
|
||||
__ xor_(ebx, 12345);
|
||||
|
||||
__ imul(edx, ecx, 12);
|
||||
__ imul(edx, ecx, 1000);
|
||||
|
||||
|
||||
|
||||
__ sub(edx, Operand(ebx, ecx, times_4, 10000));
|
||||
__ sub(edx, Operand(ebx));
|
||||
|
||||
__ test(edx, Immediate(12345));
|
||||
__ test(edx, Operand(ebx, ecx, times_8, 10000));
|
||||
__ nop();
|
||||
|
||||
__ xor_(edx, 12345);
|
||||
__ xor_(edx, Operand(ebx, ecx, times_8, 10000));
|
||||
__ bts(Operand(ebx, ecx, times_8, 10000), edx);
|
||||
__ hlt();
|
||||
__ int3();
|
||||
__ ret(0);
|
||||
__ ret(8);
|
||||
|
||||
// Calls
|
||||
|
||||
Label L1, L2;
|
||||
__ bind(&L1);
|
||||
__ nop();
|
||||
__ call(&L1);
|
||||
__ call(&L2);
|
||||
__ nop();
|
||||
__ bind(&L2);
|
||||
__ call(Operand(ebx, ecx, times_4, 10000));
|
||||
__ nop();
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
|
||||
__ call(ic, code_target);
|
||||
__ nop();
|
||||
__ call(FUNCTION_ADDR(DummyStaticFunction), runtime_entry);
|
||||
__ nop();
|
||||
|
||||
__ jmp(&L1);
|
||||
__ jmp(Operand(ebx, ecx, times_4, 10000));
|
||||
ExternalReference after_break_target =
|
||||
ExternalReference(Debug_Address::AfterBreakTarget());
|
||||
__ jmp(Operand::StaticVariable(after_break_target));
|
||||
__ jmp(ic, code_target);
|
||||
__ nop();
|
||||
|
||||
|
||||
Label Ljcc;
|
||||
__ nop();
|
||||
// long jumps
|
||||
__ j(overflow, &Ljcc);
|
||||
__ j(no_overflow, &Ljcc);
|
||||
__ j(below, &Ljcc);
|
||||
__ j(above_equal, &Ljcc);
|
||||
__ j(equal, &Ljcc);
|
||||
__ j(not_equal, &Ljcc);
|
||||
__ j(below_equal, &Ljcc);
|
||||
__ j(above, &Ljcc);
|
||||
__ j(sign, &Ljcc);
|
||||
__ j(not_sign, &Ljcc);
|
||||
__ j(parity_even, &Ljcc);
|
||||
__ j(parity_odd, &Ljcc);
|
||||
__ j(less, &Ljcc);
|
||||
__ j(greater_equal, &Ljcc);
|
||||
__ j(less_equal, &Ljcc);
|
||||
__ j(greater, &Ljcc);
|
||||
__ nop();
|
||||
__ bind(&Ljcc);
|
||||
// short jumps
|
||||
__ j(overflow, &Ljcc);
|
||||
__ j(no_overflow, &Ljcc);
|
||||
__ j(below, &Ljcc);
|
||||
__ j(above_equal, &Ljcc);
|
||||
__ j(equal, &Ljcc);
|
||||
__ j(not_equal, &Ljcc);
|
||||
__ j(below_equal, &Ljcc);
|
||||
__ j(above, &Ljcc);
|
||||
__ j(sign, &Ljcc);
|
||||
__ j(not_sign, &Ljcc);
|
||||
__ j(parity_even, &Ljcc);
|
||||
__ j(parity_odd, &Ljcc);
|
||||
__ j(less, &Ljcc);
|
||||
__ j(greater_equal, &Ljcc);
|
||||
__ j(less_equal, &Ljcc);
|
||||
__ j(greater, &Ljcc);
|
||||
|
||||
// checking hints
|
||||
__ j(zero, &Ljcc, taken);
|
||||
__ j(zero, &Ljcc, not_taken);
|
||||
|
||||
// __ mov(Operand::StaticVariable(Top::handler_address()), eax);
|
||||
// 0xD9 instructions
|
||||
__ nop();
|
||||
|
||||
__ fld1();
|
||||
__ fldz();
|
||||
__ fabs();
|
||||
__ fchs();
|
||||
__ fprem();
|
||||
__ fprem1();
|
||||
__ fincstp();
|
||||
__ ftst();
|
||||
__ fxch(3);
|
||||
__ fld_s(Operand(ebx, ecx, times_4, 10000));
|
||||
__ fstp_s(Operand(ebx, ecx, times_4, 10000));
|
||||
__ ffree(3);
|
||||
__ fld_d(Operand(ebx, ecx, times_4, 10000));
|
||||
__ fstp_d(Operand(ebx, ecx, times_4, 10000));
|
||||
__ nop();
|
||||
|
||||
__ fild_s(Operand(ebx, ecx, times_4, 10000));
|
||||
__ fistp_s(Operand(ebx, ecx, times_4, 10000));
|
||||
__ fild_d(Operand(ebx, ecx, times_4, 10000));
|
||||
__ fistp_d(Operand(ebx, ecx, times_4, 10000));
|
||||
__ fnstsw_ax();
|
||||
__ nop();
|
||||
__ fadd(3);
|
||||
__ fsub(3);
|
||||
__ fmul(3);
|
||||
__ fdiv(3);
|
||||
|
||||
__ faddp(3);
|
||||
__ fsubp(3);
|
||||
__ fmulp(3);
|
||||
__ fdivp(3);
|
||||
__ fcompp();
|
||||
__ fwait();
|
||||
__ nop();
|
||||
{
|
||||
CHECK(CpuFeatures::IsSupported(CpuFeatures::SSE2));
|
||||
CpuFeatures::Scope fscope(CpuFeatures::SSE2);
|
||||
__ cvttss2si(edx, Operand(ebx, ecx, times_4, 10000));
|
||||
__ cvtsi2sd(xmm1, Operand(ebx, ecx, times_4, 10000));
|
||||
__ addsd(xmm1, xmm0);
|
||||
__ mulsd(xmm1, xmm0);
|
||||
__ subsd(xmm1, xmm0);
|
||||
__ divsd(xmm1, xmm0);
|
||||
__ movdbl(xmm1, Operand(ebx, ecx, times_4, 10000));
|
||||
__ movdbl(Operand(ebx, ecx, times_4, 10000), xmm1);
|
||||
}
|
||||
__ ret(0);
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
#ifdef DEBUG
|
||||
Code::cast(code)->Print();
|
||||
byte* begin = Code::cast(code)->instruction_start();
|
||||
byte* end = begin + Code::cast(code)->instruction_size();
|
||||
disasm::Disassembler::Disassemble(stdout, begin, end);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef __
|
174
test/cctest/test-flags.cc
Normal file
174
test/cctest/test-flags.cc
Normal file
@ -0,0 +1,174 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
DEFINE_bool(bool_flag, true, "bool_flag");
|
||||
DEFINE_int(int_flag, 13, "int_flag");
|
||||
DEFINE_float(float_flag, 2.5, "float-flag");
|
||||
DEFINE_string(string_flag, "Hello, world!", "string-flag");
|
||||
|
||||
|
||||
// This test must be executed first!
|
||||
TEST(Default) {
|
||||
CHECK(FLAG_bool_flag);
|
||||
CHECK_EQ(13, FLAG_int_flag);
|
||||
CHECK_EQ(2.5, FLAG_float_flag);
|
||||
CHECK_EQ(0, strcmp(FLAG_string_flag, "Hello, world!"));
|
||||
}
|
||||
|
||||
|
||||
static void SetFlagsToDefault() {
|
||||
for (Flag* f = FlagList::list(); f != NULL; f = f->next()) {
|
||||
f->SetToDefault();
|
||||
}
|
||||
TestDefault();
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags1) {
|
||||
FlagList::Print(__FILE__, false);
|
||||
FlagList::Print(NULL, true);
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags2) {
|
||||
SetFlagsToDefault();
|
||||
int argc = 7;
|
||||
const char* argv[] = { "Test2", "-nobool-flag", "notaflag", "--int_flag=77",
|
||||
"-float_flag=.25", "--string_flag", "no way!" };
|
||||
CHECK_EQ(0, FlagList::SetFlagsFromCommandLine(&argc,
|
||||
const_cast<char **>(argv),
|
||||
false));
|
||||
CHECK_EQ(7, argc);
|
||||
CHECK(!FLAG_bool_flag);
|
||||
CHECK_EQ(77, FLAG_int_flag);
|
||||
CHECK_EQ(.25, FLAG_float_flag);
|
||||
CHECK_EQ(0, strcmp(FLAG_string_flag, "no way!"));
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags2b) {
|
||||
SetFlagsToDefault();
|
||||
const char* str =
|
||||
" -nobool-flag notaflag --int_flag=77 -float_flag=.25 "
|
||||
"--string_flag no_way! ";
|
||||
CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
|
||||
CHECK(!FLAG_bool_flag);
|
||||
CHECK_EQ(77, FLAG_int_flag);
|
||||
CHECK_EQ(.25, FLAG_float_flag);
|
||||
CHECK_EQ(0, strcmp(FLAG_string_flag, "no_way!"));
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags3) {
|
||||
SetFlagsToDefault();
|
||||
int argc = 8;
|
||||
const char* argv[] =
|
||||
{ "Test3", "--bool_flag", "notaflag", "--int_flag", "-666",
|
||||
"--float_flag", "-12E10", "-string-flag=foo-bar" };
|
||||
CHECK_EQ(0, FlagList::SetFlagsFromCommandLine(&argc,
|
||||
const_cast<char **>(argv),
|
||||
true));
|
||||
CHECK_EQ(2, argc);
|
||||
CHECK(FLAG_bool_flag);
|
||||
CHECK_EQ(-666, FLAG_int_flag);
|
||||
CHECK_EQ(-12E10, FLAG_float_flag);
|
||||
CHECK_EQ(0, strcmp(FLAG_string_flag, "foo-bar"));
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags3b) {
|
||||
SetFlagsToDefault();
|
||||
const char* str =
|
||||
"--bool_flag notaflag --int_flag -666 --float_flag -12E10 "
|
||||
"-string-flag=foo-bar";
|
||||
CHECK_EQ(0, FlagList::SetFlagsFromString(str, strlen(str)));
|
||||
CHECK(FLAG_bool_flag);
|
||||
CHECK_EQ(-666, FLAG_int_flag);
|
||||
CHECK_EQ(-12E10, FLAG_float_flag);
|
||||
CHECK_EQ(0, strcmp(FLAG_string_flag, "foo-bar"));
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags4) {
|
||||
SetFlagsToDefault();
|
||||
int argc = 3;
|
||||
const char* argv[] = { "Test4", "--bool_flag", "--foo" };
|
||||
CHECK_EQ(2, FlagList::SetFlagsFromCommandLine(&argc,
|
||||
const_cast<char **>(argv),
|
||||
true));
|
||||
CHECK_EQ(3, argc);
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags4b) {
|
||||
SetFlagsToDefault();
|
||||
const char* str = "--bool_flag --foo";
|
||||
CHECK_EQ(2, FlagList::SetFlagsFromString(str, strlen(str)));
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags5) {
|
||||
SetFlagsToDefault();
|
||||
int argc = 2;
|
||||
const char* argv[] = { "Test5", "--int_flag=\"foobar\"" };
|
||||
CHECK_EQ(1, FlagList::SetFlagsFromCommandLine(&argc,
|
||||
const_cast<char **>(argv),
|
||||
true));
|
||||
CHECK_EQ(2, argc);
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags5b) {
|
||||
SetFlagsToDefault();
|
||||
const char* str = " --int_flag=\"foobar\"";
|
||||
CHECK_EQ(1, FlagList::SetFlagsFromString(str, strlen(str)));
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags6) {
|
||||
SetFlagsToDefault();
|
||||
int argc = 4;
|
||||
const char* argv[] = { "Test5", "--int-flag", "0", "--float_flag" };
|
||||
CHECK_EQ(3, FlagList::SetFlagsFromCommandLine(&argc,
|
||||
const_cast<char **>(argv),
|
||||
true));
|
||||
CHECK_EQ(4, argc);
|
||||
}
|
||||
|
||||
|
||||
TEST(Flags6b) {
|
||||
SetFlagsToDefault();
|
||||
const char* str = " --int-flag 0 --float_flag ";
|
||||
CHECK_EQ(3, FlagList::SetFlagsFromString(str, strlen(str)));
|
||||
}
|
123
test/cctest/test-hashmap.cc
Normal file
123
test/cctest/test-hashmap.cc
Normal file
@ -0,0 +1,123 @@
|
||||
// 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.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
#include "hashmap.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
static bool DefaultMatchFun(void* a, void* b) {
|
||||
return a == b;
|
||||
}
|
||||
|
||||
|
||||
class IntSet {
|
||||
public:
|
||||
IntSet() : map_(DefaultMatchFun) {}
|
||||
|
||||
void Insert(int x) {
|
||||
ASSERT(x != 0); // 0 corresponds to (void*)NULL - illegal key value
|
||||
HashMap::Entry* p = map_.Lookup(reinterpret_cast<void*>(x), Hash(x), true);
|
||||
CHECK(p != NULL); // insert is set!
|
||||
CHECK_EQ(reinterpret_cast<void*>(x), p->key);
|
||||
// we don't care about p->value
|
||||
}
|
||||
|
||||
bool Present(int x) {
|
||||
HashMap::Entry* p = map_.Lookup(reinterpret_cast<void*>(x), Hash(x), false);
|
||||
if (p != NULL) {
|
||||
CHECK_EQ(reinterpret_cast<void*>(x), p->key);
|
||||
}
|
||||
return p != NULL;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
map_.Clear();
|
||||
}
|
||||
|
||||
uint32_t occupancy() const {
|
||||
uint32_t count = 0;
|
||||
for (HashMap::Entry* p = map_.Start(); p != NULL; p = map_.Next(p)) {
|
||||
count++;
|
||||
}
|
||||
CHECK_EQ(map_.occupancy(), static_cast<double>(count));
|
||||
return count;
|
||||
}
|
||||
|
||||
private:
|
||||
HashMap map_;
|
||||
static uint32_t Hash(uint32_t key) { return key * 23; }
|
||||
};
|
||||
|
||||
|
||||
TEST(Set) {
|
||||
IntSet set;
|
||||
CHECK_EQ(0, set.occupancy());
|
||||
|
||||
set.Insert(1);
|
||||
set.Insert(2);
|
||||
set.Insert(3);
|
||||
CHECK_EQ(3, set.occupancy());
|
||||
|
||||
set.Insert(2);
|
||||
set.Insert(3);
|
||||
CHECK_EQ(3, set.occupancy());
|
||||
|
||||
CHECK(set.Present(1));
|
||||
CHECK(set.Present(2));
|
||||
CHECK(set.Present(3));
|
||||
CHECK(!set.Present(4));
|
||||
CHECK_EQ(3, set.occupancy());
|
||||
|
||||
set.Clear();
|
||||
CHECK_EQ(0, set.occupancy());
|
||||
|
||||
// Insert a long series of values.
|
||||
const int start = 453;
|
||||
const int factor = 13;
|
||||
const int offset = 7;
|
||||
const uint32_t n = 1000;
|
||||
|
||||
int x = start;
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
CHECK_EQ(i, static_cast<double>(set.occupancy()));
|
||||
set.Insert(x);
|
||||
x = x*factor + offset;
|
||||
}
|
||||
|
||||
// Verify the same sequence of values.
|
||||
x = start;
|
||||
for (uint32_t i = 0; i < n; i++) {
|
||||
CHECK(set.Present(x));
|
||||
x = x*factor + offset;
|
||||
}
|
||||
|
||||
CHECK_EQ(n, static_cast<double>(set.occupancy()));
|
||||
}
|
782
test/cctest/test-heap.cc
Normal file
782
test/cctest/test-heap.cc
Normal file
@ -0,0 +1,782 @@
|
||||
// Copyright 2006-2008 Google, Inc. All Rights Reserved.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "execution.h"
|
||||
#include "factory.h"
|
||||
#include "macro-assembler.h"
|
||||
#include "global-handles.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
static v8::Persistent<v8::Context> env;
|
||||
|
||||
static void InitializeVM() {
|
||||
if (env.IsEmpty()) env = v8::Context::New();
|
||||
v8::HandleScope scope;
|
||||
env->Enter();
|
||||
}
|
||||
|
||||
|
||||
static void CheckMap(Map* map, int type, int instance_size) {
|
||||
CHECK(map->IsHeapObject());
|
||||
#ifdef DEBUG
|
||||
CHECK(Heap::Contains(map));
|
||||
#endif
|
||||
CHECK_EQ(Heap::meta_map(), map->map());
|
||||
CHECK_EQ(type, map->instance_type());
|
||||
CHECK_EQ(instance_size, map->instance_size());
|
||||
}
|
||||
|
||||
|
||||
TEST(HeapMaps) {
|
||||
InitializeVM();
|
||||
CheckMap(Heap::meta_map(), MAP_TYPE, Map::kSize);
|
||||
CheckMap(Heap::heap_number_map(), HEAP_NUMBER_TYPE, HeapNumber::kSize);
|
||||
CheckMap(Heap::fixed_array_map(), FIXED_ARRAY_TYPE, Array::kHeaderSize);
|
||||
CheckMap(Heap::long_string_map(), LONG_STRING_TYPE,
|
||||
TwoByteString::kHeaderSize);
|
||||
}
|
||||
|
||||
|
||||
static void CheckOddball(Object* obj, const char* string) {
|
||||
CHECK(obj->IsOddball());
|
||||
bool exc;
|
||||
Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
|
||||
CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
|
||||
}
|
||||
|
||||
|
||||
static void CheckSmi(int value, const char* string) {
|
||||
bool exc;
|
||||
Object* print_string =
|
||||
*Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
|
||||
CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
|
||||
}
|
||||
|
||||
|
||||
static void CheckNumber(double value, const char* string) {
|
||||
Object* obj = Heap::NumberFromDouble(value);
|
||||
CHECK(obj->IsNumber());
|
||||
bool exc;
|
||||
Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
|
||||
CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
|
||||
}
|
||||
|
||||
|
||||
static void CheckFindCodeObject() {
|
||||
// Test FindCodeObject
|
||||
#define __ assm.
|
||||
|
||||
Assembler assm(NULL, 0);
|
||||
|
||||
__ nop(); // supported on all architectures
|
||||
|
||||
CodeDesc desc;
|
||||
assm.GetCode(&desc);
|
||||
Object* code = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(code->IsCode());
|
||||
|
||||
HeapObject* obj = HeapObject::cast(code);
|
||||
Address obj_addr = obj->address();
|
||||
|
||||
for (int i = 0; i < obj->Size(); i += kPointerSize) {
|
||||
Object* found = Heap::FindCodeObject(obj_addr + i);
|
||||
CHECK_EQ(code, found);
|
||||
}
|
||||
|
||||
Object* copy = Heap::CreateCode(desc, NULL, Code::ComputeFlags(Code::STUB));
|
||||
CHECK(copy->IsCode());
|
||||
HeapObject* obj_copy = HeapObject::cast(copy);
|
||||
Object* not_right = Heap::FindCodeObject(obj_copy->address() +
|
||||
obj_copy->Size() / 2);
|
||||
CHECK(not_right != code);
|
||||
}
|
||||
|
||||
|
||||
TEST(HeapObjects) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
Object* value = Heap::NumberFromDouble(1.000123);
|
||||
CHECK(value->IsHeapNumber());
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(1.000123, value->Number());
|
||||
|
||||
value = Heap::NumberFromDouble(1.0);
|
||||
CHECK(value->IsSmi());
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(1.0, value->Number());
|
||||
|
||||
value = Heap::NumberFromInt32(1024);
|
||||
CHECK(value->IsSmi());
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(1024.0, value->Number());
|
||||
|
||||
value = Heap::NumberFromInt32(Smi::kMinValue);
|
||||
CHECK(value->IsSmi());
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
|
||||
|
||||
value = Heap::NumberFromInt32(Smi::kMaxValue);
|
||||
CHECK(value->IsSmi());
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
|
||||
|
||||
value = Heap::NumberFromInt32(Smi::kMinValue - 1);
|
||||
CHECK(value->IsHeapNumber());
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
|
||||
|
||||
value = Heap::NumberFromInt32(Smi::kMaxValue + 1);
|
||||
CHECK(value->IsHeapNumber());
|
||||
CHECK(value->IsNumber());
|
||||
CHECK_EQ(static_cast<double>(Smi::kMaxValue + 1), value->Number());
|
||||
|
||||
// nan oddball checks
|
||||
CHECK(Heap::nan_value()->IsNumber());
|
||||
CHECK(isnan(Heap::nan_value()->Number()));
|
||||
|
||||
// infinit oddball checks
|
||||
CHECK(Heap::infinity_value()->IsNumber());
|
||||
CHECK(!isfinite(Heap::infinity_value()->Number()));
|
||||
|
||||
Object* str = Heap::AllocateStringFromAscii(CStrVector("fisk hest "));
|
||||
if (!str->IsFailure()) {
|
||||
String* s = String::cast(str);
|
||||
CHECK(s->IsString());
|
||||
CHECK_EQ(10, s->length());
|
||||
} else {
|
||||
CHECK(false);
|
||||
}
|
||||
|
||||
String* object_symbol = String::cast(Heap::Object_symbol());
|
||||
CHECK(Top::context()->global()->HasLocalProperty(object_symbol));
|
||||
|
||||
// Check ToString for oddballs
|
||||
CheckOddball(Heap::true_value(), "true");
|
||||
CheckOddball(Heap::false_value(), "false");
|
||||
CheckOddball(Heap::null_value(), "null");
|
||||
CheckOddball(Heap::undefined_value(), "undefined");
|
||||
|
||||
// Check ToString for Smis
|
||||
CheckSmi(0, "0");
|
||||
CheckSmi(42, "42");
|
||||
CheckSmi(-42, "-42");
|
||||
|
||||
// Check ToString for Numbers
|
||||
CheckNumber(1.1, "1.1");
|
||||
|
||||
CheckFindCodeObject();
|
||||
}
|
||||
|
||||
|
||||
TEST(Tagging) {
|
||||
InitializeVM();
|
||||
CHECK(Smi::FromInt(42)->IsSmi());
|
||||
CHECK(Failure::RetryAfterGC(12, NEW_SPACE)->IsFailure());
|
||||
CHECK_EQ(12, Failure::RetryAfterGC(12, NEW_SPACE)->requested());
|
||||
CHECK_EQ(NEW_SPACE, Failure::RetryAfterGC(12, NEW_SPACE)->allocation_space());
|
||||
CHECK_EQ(OLD_SPACE, Failure::RetryAfterGC(12, OLD_SPACE)->allocation_space());
|
||||
CHECK(Failure::Exception()->IsFailure());
|
||||
CHECK(Smi::FromInt(Smi::kMinValue)->IsSmi());
|
||||
CHECK(Smi::FromInt(Smi::kMaxValue)->IsSmi());
|
||||
}
|
||||
|
||||
|
||||
TEST(GarbageCollection) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
// check GC when heap is empty
|
||||
int free_bytes = Heap::MaxHeapObjectSize();
|
||||
CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
|
||||
|
||||
// allocate a function and keep it in global object's property
|
||||
String* func_name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
|
||||
SharedFunctionInfo* function_share =
|
||||
SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name));
|
||||
JSFunction* function =
|
||||
JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
|
||||
function_share,
|
||||
Heap::undefined_value()));
|
||||
Map* initial_map =
|
||||
Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
|
||||
function->set_initial_map(initial_map);
|
||||
Top::context()->global()->SetProperty(func_name, function, NONE);
|
||||
|
||||
// allocate an object, but it is unrooted
|
||||
String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
|
||||
String* prop_namex = String::cast(Heap::LookupAsciiSymbol("theSlotx"));
|
||||
JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
|
||||
obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
|
||||
obj->SetProperty(prop_namex, Smi::FromInt(24), NONE);
|
||||
|
||||
CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
|
||||
CHECK_EQ(Smi::FromInt(24), obj->GetProperty(prop_namex));
|
||||
|
||||
CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
|
||||
|
||||
// function should be alive, func_name might be invalid after GC
|
||||
func_name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
|
||||
CHECK(Top::context()->global()->HasLocalProperty(func_name));
|
||||
// check function is retained
|
||||
Object* func_value = Top::context()->global()->GetProperty(func_name);
|
||||
CHECK(func_value->IsJSFunction());
|
||||
// old function pointer may not be valid
|
||||
function = JSFunction::cast(func_value);
|
||||
|
||||
// allocate another object, make it reachable from global
|
||||
obj = JSObject::cast(Heap::AllocateJSObject(function));
|
||||
String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
|
||||
Top::context()->global()->SetProperty(obj_name, obj, NONE);
|
||||
// set property
|
||||
prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
|
||||
obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
|
||||
|
||||
// after gc, it should survive
|
||||
CHECK(Heap::CollectGarbage(free_bytes, NEW_SPACE));
|
||||
|
||||
obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
|
||||
CHECK(Top::context()->global()->HasLocalProperty(obj_name));
|
||||
CHECK(Top::context()->global()->GetProperty(obj_name)->IsJSObject());
|
||||
obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name));
|
||||
prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
|
||||
CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
|
||||
}
|
||||
|
||||
|
||||
static void VerifyStringAllocation(const char* string) {
|
||||
String* s = String::cast(Heap::AllocateStringFromUtf8(CStrVector(string)));
|
||||
CHECK_EQ(static_cast<int>(strlen(string)), s->length());
|
||||
for (int index = 0; index < s->length(); index++) {
|
||||
CHECK_EQ(static_cast<uint16_t>(string[index]), s->Get(index)); }
|
||||
}
|
||||
|
||||
|
||||
TEST(String) {
|
||||
InitializeVM();
|
||||
|
||||
VerifyStringAllocation("a");
|
||||
VerifyStringAllocation("ab");
|
||||
VerifyStringAllocation("abc");
|
||||
VerifyStringAllocation("abcd");
|
||||
VerifyStringAllocation("fiskerdrengen er paa havet");
|
||||
}
|
||||
|
||||
|
||||
TEST(LocalHandles) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope scope;
|
||||
const char* name = "Kasper the spunky";
|
||||
Handle<String> string = Factory::NewStringFromAscii(CStrVector(name));
|
||||
CHECK_EQ(static_cast<int>(strlen(name)), string->length());
|
||||
}
|
||||
|
||||
|
||||
TEST(GlobalHandles) {
|
||||
InitializeVM();
|
||||
|
||||
Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
|
||||
Object* u = Heap::AllocateHeapNumber(1.12344);
|
||||
|
||||
Handle<Object> h1 = GlobalHandles::Create(i);
|
||||
Handle<Object> h2 = GlobalHandles::Create(u);
|
||||
Handle<Object> h3 = GlobalHandles::Create(i);
|
||||
Handle<Object> h4 = GlobalHandles::Create(u);
|
||||
|
||||
// after gc, it should survive
|
||||
CHECK(Heap::CollectGarbage(0, NEW_SPACE));
|
||||
|
||||
CHECK((*h1)->IsString());
|
||||
CHECK((*h2)->IsHeapNumber());
|
||||
CHECK((*h3)->IsString());
|
||||
CHECK((*h4)->IsHeapNumber());
|
||||
|
||||
CHECK_EQ(*h3, *h1);
|
||||
GlobalHandles::Destroy(h1.location());
|
||||
GlobalHandles::Destroy(h3.location());
|
||||
|
||||
CHECK_EQ(*h4, *h2);
|
||||
GlobalHandles::Destroy(h2.location());
|
||||
GlobalHandles::Destroy(h4.location());
|
||||
}
|
||||
|
||||
|
||||
static bool WeakPointerCleared = false;
|
||||
|
||||
static void TestWeakGlobalHandleCallback(v8::Persistent<v8::Object> handle,
|
||||
void* id) {
|
||||
USE(handle);
|
||||
if (1234 == reinterpret_cast<int>(id)) WeakPointerCleared = true;
|
||||
}
|
||||
|
||||
|
||||
TEST(WeakGlobalHandlesScavenge) {
|
||||
InitializeVM();
|
||||
|
||||
WeakPointerCleared = false;
|
||||
|
||||
Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
|
||||
Object* u = Heap::AllocateHeapNumber(1.12344);
|
||||
|
||||
Handle<Object> h1 = GlobalHandles::Create(i);
|
||||
Handle<Object> h2 = GlobalHandles::Create(u);
|
||||
|
||||
GlobalHandles::MakeWeak(h2.location(),
|
||||
reinterpret_cast<void*>(1234),
|
||||
&TestWeakGlobalHandleCallback);
|
||||
|
||||
// Scavenge treats weak pointers as normal roots.
|
||||
Heap::PerformScavenge();
|
||||
|
||||
CHECK((*h1)->IsString());
|
||||
CHECK((*h2)->IsHeapNumber());
|
||||
|
||||
CHECK(!WeakPointerCleared);
|
||||
CHECK(!GlobalHandles::IsNearDeath(h2.location()));
|
||||
CHECK(!GlobalHandles::IsNearDeath(h1.location()));
|
||||
|
||||
GlobalHandles::Destroy(h1.location());
|
||||
GlobalHandles::Destroy(h2.location());
|
||||
}
|
||||
|
||||
|
||||
TEST(WeakGlobalHandlesMark) {
|
||||
InitializeVM();
|
||||
|
||||
WeakPointerCleared = false;
|
||||
|
||||
Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
|
||||
Object* u = Heap::AllocateHeapNumber(1.12344);
|
||||
|
||||
Handle<Object> h1 = GlobalHandles::Create(i);
|
||||
Handle<Object> h2 = GlobalHandles::Create(u);
|
||||
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
CHECK(Heap::CollectGarbage(0, NEW_SPACE));
|
||||
// Make sure the object is promoted.
|
||||
|
||||
GlobalHandles::MakeWeak(h2.location(),
|
||||
reinterpret_cast<void*>(1234),
|
||||
&TestWeakGlobalHandleCallback);
|
||||
CHECK(!GlobalHandles::IsNearDeath(h1.location()));
|
||||
CHECK(!GlobalHandles::IsNearDeath(h2.location()));
|
||||
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
CHECK((*h1)->IsString());
|
||||
|
||||
CHECK(WeakPointerCleared);
|
||||
CHECK(!GlobalHandles::IsNearDeath(h1.location()));
|
||||
CHECK(GlobalHandles::IsNearDeath(h2.location()));
|
||||
|
||||
GlobalHandles::Destroy(h1.location());
|
||||
GlobalHandles::Destroy(h2.location());
|
||||
}
|
||||
|
||||
static void TestDeleteWeakGlobalHandleCallback(
|
||||
v8::Persistent<v8::Object> handle,
|
||||
void* id) {
|
||||
if (1234 == reinterpret_cast<int>(id)) WeakPointerCleared = true;
|
||||
handle.Dispose();
|
||||
}
|
||||
|
||||
TEST(DeleteWeakGlobalHandle) {
|
||||
InitializeVM();
|
||||
|
||||
WeakPointerCleared = false;
|
||||
|
||||
Object* i = Heap::AllocateStringFromAscii(CStrVector("fisk"));
|
||||
Handle<Object> h = GlobalHandles::Create(i);
|
||||
|
||||
GlobalHandles::MakeWeak(h.location(),
|
||||
reinterpret_cast<void*>(1234),
|
||||
&TestDeleteWeakGlobalHandleCallback);
|
||||
|
||||
// Scanvenge does not recognize weak reference.
|
||||
Heap::PerformScavenge();
|
||||
|
||||
CHECK(!WeakPointerCleared);
|
||||
|
||||
// Mark-compact treats weak reference properly.
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
CHECK(WeakPointerCleared);
|
||||
}
|
||||
|
||||
static const char* not_so_random_string_table[] = {
|
||||
"abstract",
|
||||
"boolean",
|
||||
"break",
|
||||
"byte",
|
||||
"case",
|
||||
"catch",
|
||||
"char",
|
||||
"class",
|
||||
"const",
|
||||
"continue",
|
||||
"debugger",
|
||||
"default",
|
||||
"delete",
|
||||
"do",
|
||||
"double",
|
||||
"else",
|
||||
"enum",
|
||||
"export",
|
||||
"extends",
|
||||
"false",
|
||||
"final",
|
||||
"finally",
|
||||
"float",
|
||||
"for",
|
||||
"function",
|
||||
"goto",
|
||||
"if",
|
||||
"implements",
|
||||
"import",
|
||||
"in",
|
||||
"instanceof",
|
||||
"int",
|
||||
"interface",
|
||||
"long",
|
||||
"native",
|
||||
"new",
|
||||
"null",
|
||||
"package",
|
||||
"private",
|
||||
"protected",
|
||||
"public",
|
||||
"return",
|
||||
"short",
|
||||
"static",
|
||||
"super",
|
||||
"switch",
|
||||
"synchronized",
|
||||
"this",
|
||||
"throw",
|
||||
"throws",
|
||||
"transient",
|
||||
"true",
|
||||
"try",
|
||||
"typeof",
|
||||
"var",
|
||||
"void",
|
||||
"volatile",
|
||||
"while",
|
||||
"with",
|
||||
0
|
||||
};
|
||||
|
||||
|
||||
static void CheckSymbols(const char** strings) {
|
||||
for (const char* string = *strings; *strings != 0; string = *strings++) {
|
||||
Object* a = Heap::LookupAsciiSymbol(string);
|
||||
CHECK(a->IsSymbol());
|
||||
Object* b = Heap::LookupAsciiSymbol(string);
|
||||
CHECK_EQ(b, a);
|
||||
CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(SymbolTable) {
|
||||
InitializeVM();
|
||||
|
||||
CheckSymbols(not_so_random_string_table);
|
||||
CheckSymbols(not_so_random_string_table);
|
||||
}
|
||||
|
||||
|
||||
TEST(FunctionAllocation) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
String* name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
|
||||
SharedFunctionInfo* function_share =
|
||||
SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(name));
|
||||
JSFunction* function =
|
||||
JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
|
||||
function_share,
|
||||
Heap::undefined_value()));
|
||||
Map* initial_map =
|
||||
Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
|
||||
function->set_initial_map(initial_map);
|
||||
|
||||
String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
|
||||
JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
|
||||
obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
|
||||
CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
|
||||
// Check that we can add properties to function objects.
|
||||
function->SetProperty(prop_name, Smi::FromInt(24), NONE);
|
||||
CHECK_EQ(Smi::FromInt(24), function->GetProperty(prop_name));
|
||||
}
|
||||
|
||||
|
||||
TEST(ObjectProperties) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
JSFunction* constructor =
|
||||
JSFunction::cast(
|
||||
Top::context()->global()->GetProperty(String::cast(
|
||||
Heap::Object_symbol())));
|
||||
JSObject* obj = JSObject::cast(Heap::AllocateJSObject(constructor));
|
||||
String* first = String::cast(Heap::LookupAsciiSymbol("first"));
|
||||
String* second = String::cast(Heap::LookupAsciiSymbol("second"));
|
||||
|
||||
// check for empty
|
||||
CHECK(!obj->HasLocalProperty(first));
|
||||
|
||||
// add first
|
||||
obj->SetProperty(first, Smi::FromInt(1), NONE);
|
||||
CHECK(obj->HasLocalProperty(first));
|
||||
|
||||
// delete first
|
||||
CHECK(obj->DeleteProperty(first));
|
||||
CHECK(!obj->HasLocalProperty(first));
|
||||
|
||||
// add first and then second
|
||||
obj->SetProperty(first, Smi::FromInt(1), NONE);
|
||||
obj->SetProperty(second, Smi::FromInt(2), NONE);
|
||||
CHECK(obj->HasLocalProperty(first));
|
||||
CHECK(obj->HasLocalProperty(second));
|
||||
|
||||
// delete first and then second
|
||||
CHECK(obj->DeleteProperty(first));
|
||||
CHECK(obj->HasLocalProperty(second));
|
||||
CHECK(obj->DeleteProperty(second));
|
||||
CHECK(!obj->HasLocalProperty(first));
|
||||
CHECK(!obj->HasLocalProperty(second));
|
||||
|
||||
// add first and then second
|
||||
obj->SetProperty(first, Smi::FromInt(1), NONE);
|
||||
obj->SetProperty(second, Smi::FromInt(2), NONE);
|
||||
CHECK(obj->HasLocalProperty(first));
|
||||
CHECK(obj->HasLocalProperty(second));
|
||||
|
||||
// delete second and then first
|
||||
CHECK(obj->DeleteProperty(second));
|
||||
CHECK(obj->HasLocalProperty(first));
|
||||
CHECK(obj->DeleteProperty(first));
|
||||
CHECK(!obj->HasLocalProperty(first));
|
||||
CHECK(!obj->HasLocalProperty(second));
|
||||
|
||||
// check string and symbol match
|
||||
static const char* string1 = "fisk";
|
||||
String* s1 =
|
||||
String::cast(Heap::AllocateStringFromAscii(CStrVector(string1)));
|
||||
obj->SetProperty(s1, Smi::FromInt(1), NONE);
|
||||
CHECK(obj->HasLocalProperty(String::cast(Heap::LookupAsciiSymbol(string1))));
|
||||
|
||||
// check symbol and string match
|
||||
static const char* string2 = "fugl";
|
||||
String* s2 = String::cast(Heap::LookupAsciiSymbol(string2));
|
||||
obj->SetProperty(s2, Smi::FromInt(1), NONE);
|
||||
CHECK(obj->HasLocalProperty(
|
||||
String::cast(Heap::AllocateStringFromAscii(CStrVector(string2)))));
|
||||
}
|
||||
|
||||
|
||||
TEST(JSObjectMaps) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
String* name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
|
||||
SharedFunctionInfo* function_share =
|
||||
SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(name));
|
||||
JSFunction* function =
|
||||
JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
|
||||
function_share,
|
||||
Heap::undefined_value()));
|
||||
Map* initial_map =
|
||||
Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
|
||||
function->set_initial_map(initial_map);
|
||||
String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
|
||||
JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
|
||||
|
||||
// Set a propery
|
||||
obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
|
||||
CHECK_EQ(Smi::FromInt(23), obj->GetProperty(prop_name));
|
||||
|
||||
// Check the map has changed
|
||||
CHECK(initial_map != obj->map());
|
||||
}
|
||||
|
||||
|
||||
TEST(JSArray) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
String* name = String::cast(Heap::LookupAsciiSymbol("Array"));
|
||||
JSFunction* function =
|
||||
JSFunction::cast(Top::context()->global()->GetProperty(name));
|
||||
|
||||
// Allocate the object.
|
||||
JSArray* array = JSArray::cast(Heap::AllocateJSObject(function));
|
||||
array->Initialize(0);
|
||||
|
||||
// Set array length to 0.
|
||||
array->SetElementsLength(Smi::FromInt(0));
|
||||
CHECK_EQ(Smi::FromInt(0), array->length());
|
||||
CHECK(array->HasFastElements()); // Must be in fast mode.
|
||||
|
||||
// array[length] = name.
|
||||
array->SetElement(0, name);
|
||||
CHECK_EQ(Smi::FromInt(1), array->length());
|
||||
CHECK_EQ(array->GetElement(0), name);
|
||||
|
||||
// Set array length with larger than smi value.
|
||||
Object* length = Heap::NumberFromInt32(Smi::kMaxValue + 1);
|
||||
array->SetElementsLength(length);
|
||||
|
||||
uint32_t int_length = 0;
|
||||
CHECK(Array::IndexFromObject(length, &int_length));
|
||||
CHECK_EQ(length, array->length());
|
||||
CHECK(!array->HasFastElements()); // Must be in slow mode.
|
||||
|
||||
// array[length] = name.
|
||||
array->SetElement(int_length, name);
|
||||
uint32_t new_int_length = 0;
|
||||
CHECK(Array::IndexFromObject(array->length(), &new_int_length));
|
||||
CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
|
||||
CHECK_EQ(array->GetElement(int_length), name);
|
||||
CHECK_EQ(array->GetElement(0), name);
|
||||
}
|
||||
|
||||
|
||||
TEST(JSObjectCopy) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
String* name = String::cast(Heap::Object_symbol());
|
||||
JSFunction* constructor =
|
||||
JSFunction::cast(Top::context()->global()->GetProperty(name));
|
||||
JSObject* obj = JSObject::cast(Heap::AllocateJSObject(constructor));
|
||||
String* first = String::cast(Heap::LookupAsciiSymbol("first"));
|
||||
String* second = String::cast(Heap::LookupAsciiSymbol("second"));
|
||||
|
||||
obj->SetProperty(first, Smi::FromInt(1), NONE);
|
||||
obj->SetProperty(second, Smi::FromInt(2), NONE);
|
||||
|
||||
obj->SetElement(0, first);
|
||||
obj->SetElement(1, second);
|
||||
|
||||
// Make the clone.
|
||||
JSObject* clone = JSObject::cast(obj->Copy());
|
||||
CHECK(clone != obj);
|
||||
|
||||
CHECK_EQ(obj->GetElement(0), clone->GetElement(0));
|
||||
CHECK_EQ(obj->GetElement(1), clone->GetElement(1));
|
||||
|
||||
CHECK_EQ(obj->GetProperty(first), clone->GetProperty(first));
|
||||
CHECK_EQ(obj->GetProperty(second), clone->GetProperty(second));
|
||||
|
||||
// Flip the values.
|
||||
clone->SetProperty(first, Smi::FromInt(2), NONE);
|
||||
clone->SetProperty(second, Smi::FromInt(1), NONE);
|
||||
|
||||
clone->SetElement(0, second);
|
||||
clone->SetElement(1, first);
|
||||
|
||||
CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
|
||||
CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
|
||||
|
||||
CHECK_EQ(obj->GetProperty(second), clone->GetProperty(first));
|
||||
CHECK_EQ(obj->GetProperty(first), clone->GetProperty(second));
|
||||
}
|
||||
|
||||
|
||||
TEST(StringAllocation) {
|
||||
InitializeVM();
|
||||
|
||||
|
||||
const unsigned char chars[] = { 0xe5, 0xa4, 0xa7 };
|
||||
for (int length = 0; length < 100; length++) {
|
||||
v8::HandleScope scope;
|
||||
char* non_ascii = NewArray<char>(3 * length + 1);
|
||||
char* ascii = NewArray<char>(length + 1);
|
||||
non_ascii[3 * length] = 0;
|
||||
ascii[length] = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
ascii[i] = 'a';
|
||||
non_ascii[3 * i] = chars[0];
|
||||
non_ascii[3 * i + 1] = chars[1];
|
||||
non_ascii[3 * i + 2] = chars[2];
|
||||
}
|
||||
Handle<String> non_ascii_sym =
|
||||
Factory::LookupSymbol(Vector<const char>(non_ascii, 3 * length));
|
||||
CHECK_EQ(length, non_ascii_sym->length());
|
||||
Handle<String> ascii_sym =
|
||||
Factory::LookupSymbol(Vector<const char>(ascii, length));
|
||||
CHECK_EQ(length, ascii_sym->length());
|
||||
Handle<String> non_ascii_str =
|
||||
Factory::NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
|
||||
non_ascii_str->Hash();
|
||||
CHECK_EQ(length, non_ascii_str->length());
|
||||
Handle<String> ascii_str =
|
||||
Factory::NewStringFromUtf8(Vector<const char>(ascii, length));
|
||||
ascii_str->Hash();
|
||||
CHECK_EQ(length, ascii_str->length());
|
||||
DeleteArray(non_ascii);
|
||||
DeleteArray(ascii);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ObjectsFoundInHeap(Handle<Object> objs[], int size) {
|
||||
// Count the number of objects found in the heap.
|
||||
int found_count = 0;
|
||||
HeapIterator iterator;
|
||||
while (iterator.has_next()) {
|
||||
HeapObject* obj = iterator.next();
|
||||
CHECK(obj != NULL);
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (*objs[i] == obj) {
|
||||
found_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
CHECK(!iterator.has_next());
|
||||
return found_count;
|
||||
}
|
||||
|
||||
|
||||
TEST(Iteration) {
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
// Array of objects to scan haep for.
|
||||
const int objs_count = 6;
|
||||
Handle<Object> objs[objs_count];
|
||||
int next_objs_index = 0;
|
||||
|
||||
// Allocate a JS array to OLD_SPACE and NEW_SPACE
|
||||
objs[next_objs_index++] = Factory::NewJSArray(10);
|
||||
objs[next_objs_index++] = Factory::NewJSArray(10, TENURED);
|
||||
|
||||
// Allocate a small string to CODE_SPACE and NEW_SPACE
|
||||
objs[next_objs_index++] =
|
||||
Factory::NewStringFromAscii(CStrVector("abcdefghij"));
|
||||
objs[next_objs_index++] =
|
||||
Factory::NewStringFromAscii(CStrVector("abcdefghij"), TENURED);
|
||||
|
||||
// Allocate a large string (for large object space).
|
||||
int large_size = Heap::MaxHeapObjectSize() + 1;
|
||||
char* str = new char[large_size];
|
||||
for (int i = 0; i < large_size - 1; ++i) str[i] = 'a';
|
||||
str[large_size - 1] = '\0';
|
||||
objs[next_objs_index++] =
|
||||
Factory::NewStringFromAscii(CStrVector(str), TENURED);
|
||||
delete[] str;
|
||||
|
||||
// Add a Map object to look for.
|
||||
objs[next_objs_index++] = Handle<Map>(HeapObject::cast(*objs[0])->map());
|
||||
|
||||
CHECK_EQ(objs_count, next_objs_index);
|
||||
CHECK_EQ(objs_count, ObjectsFoundInHeap(objs, objs_count));
|
||||
}
|
40
test/cctest/test-lock.cc
Normal file
40
test/cctest/test-lock.cc
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2006-2008 Google, Inc. All Rights Reserved.
|
||||
//
|
||||
// Tests of the TokenLock class from lock.h
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "cctest.h"
|
||||
|
||||
|
||||
using namespace ::v8::internal;
|
||||
|
||||
|
||||
// Simple test of locking logic
|
||||
TEST(Simple) {
|
||||
Mutex* mutex = OS::CreateMutex();
|
||||
CHECK_EQ(0, mutex->Lock()); // acquire the lock with the right token
|
||||
CHECK_EQ(0, mutex->Unlock()); // can unlock with the right token
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
|
||||
TEST(MultiLock) {
|
||||
Mutex* mutex = OS::CreateMutex();
|
||||
CHECK_EQ(0, mutex->Lock());
|
||||
CHECK_EQ(0, mutex->Unlock());
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
|
||||
TEST(ShallowLock) {
|
||||
Mutex* mutex = OS::CreateMutex();
|
||||
CHECK_EQ(0, mutex->Lock());
|
||||
CHECK_EQ(0, mutex->Unlock());
|
||||
CHECK_EQ(0, mutex->Lock());
|
||||
CHECK_EQ(0, mutex->Unlock());
|
||||
delete mutex;
|
||||
}
|
315
test/cctest/test-mark-compact.cc
Normal file
315
test/cctest/test-mark-compact.cc
Normal file
@ -0,0 +1,315 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "global-handles.h"
|
||||
#include "snapshot.h"
|
||||
#include "top.h"
|
||||
#include "cctest.h"
|
||||
|
||||
namespace v8 { namespace internal {
|
||||
DECLARE_bool(gc_global);
|
||||
DECLARE_bool(always_compact);
|
||||
} }
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
static v8::Persistent<v8::Context> env;
|
||||
|
||||
static void InitializeVM() {
|
||||
if (env.IsEmpty()) env = v8::Context::New();
|
||||
v8::HandleScope scope;
|
||||
env->Enter();
|
||||
}
|
||||
|
||||
|
||||
TEST(MarkingStack) {
|
||||
int mem_size = 20 * kPointerSize;
|
||||
byte* mem = NewArray<byte>(20*kPointerSize);
|
||||
Address low = reinterpret_cast<Address>(mem);
|
||||
Address high = low + mem_size;
|
||||
MarkingStack s;
|
||||
s.Initialize(low, high);
|
||||
|
||||
Address address = NULL;
|
||||
while (!s.is_full()) {
|
||||
s.Push(HeapObject::FromAddress(address));
|
||||
address += kPointerSize;
|
||||
}
|
||||
|
||||
while (!s.is_empty()) {
|
||||
Address value = s.Pop()->address();
|
||||
address -= kPointerSize;
|
||||
CHECK_EQ(address, value);
|
||||
}
|
||||
|
||||
CHECK_EQ(NULL, address);
|
||||
DeleteArray(mem);
|
||||
}
|
||||
|
||||
|
||||
TEST(Promotion) {
|
||||
// Test the situation that some objects in new space are promoted to the
|
||||
// old space
|
||||
|
||||
// Ensure that we get a compacting collection so that objects are promoted
|
||||
// from new space.
|
||||
FLAG_gc_global = true;
|
||||
FLAG_always_compact = true;
|
||||
Snapshot::DisableInternal();
|
||||
Heap::ConfigureHeap(2*256*KB, 4*MB);
|
||||
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
|
||||
// Allocate a fixed array in the new space.
|
||||
int array_size =
|
||||
(Heap::MaxHeapObjectSize() - Array::kHeaderSize) / (kPointerSize * 4);
|
||||
Object* obj = Heap::AllocateFixedArray(array_size);
|
||||
CHECK(!obj->IsFailure());
|
||||
|
||||
Handle<FixedArray> array(FixedArray::cast(obj));
|
||||
|
||||
// Array should be in the new space.
|
||||
CHECK(Heap::InSpace(*array, NEW_SPACE));
|
||||
|
||||
// Call the m-c collector, so array becomes an old object.
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
// Array now sits in the old space
|
||||
CHECK(Heap::InSpace(*array, OLD_SPACE));
|
||||
}
|
||||
|
||||
|
||||
TEST(NoPromotion) {
|
||||
Snapshot::DisableInternal();
|
||||
Heap::ConfigureHeap(2*256*KB, 4*MB);
|
||||
|
||||
// Test the situation that some objects in new space are promoted to
|
||||
// the old space
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
|
||||
// Do a mark compact GC to shrink the heap.
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
// Allocate a big Fixed array in the new space.
|
||||
int size = (Heap::MaxHeapObjectSize() - Array::kHeaderSize) / kPointerSize;
|
||||
Object* obj = Heap::AllocateFixedArray(size);
|
||||
|
||||
Handle<FixedArray> array(FixedArray::cast(obj));
|
||||
|
||||
// Array still stays in the new space.
|
||||
CHECK(Heap::InSpace(*array, NEW_SPACE));
|
||||
|
||||
// Allocate objects in the old space until out of memory.
|
||||
FixedArray* host = *array;
|
||||
while (true) {
|
||||
Object* obj = Heap::AllocateFixedArray(100, TENURED);
|
||||
if (obj->IsFailure()) break;
|
||||
|
||||
host->set(0, obj);
|
||||
host = FixedArray::cast(obj);
|
||||
}
|
||||
|
||||
// Call mark compact GC, and it should pass.
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
// array should not be promoted because the old space is full.
|
||||
CHECK(Heap::InSpace(*array, NEW_SPACE));
|
||||
}
|
||||
|
||||
|
||||
TEST(MarkCompactCollector) {
|
||||
InitializeVM();
|
||||
|
||||
v8::HandleScope sc;
|
||||
// call mark-compact when heap is empty
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
// keep allocating garbage in new space until it fails
|
||||
const int ARRAY_SIZE = 100;
|
||||
Object* array;
|
||||
do {
|
||||
array = Heap::AllocateFixedArray(ARRAY_SIZE);
|
||||
} while (!array->IsFailure());
|
||||
CHECK(Heap::CollectGarbage(0, NEW_SPACE));
|
||||
|
||||
array = Heap::AllocateFixedArray(ARRAY_SIZE);
|
||||
CHECK(!array->IsFailure());
|
||||
|
||||
// keep allocating maps until it fails
|
||||
Object* mapp;
|
||||
do {
|
||||
mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
|
||||
} while (!mapp->IsFailure());
|
||||
CHECK(Heap::CollectGarbage(0, MAP_SPACE));
|
||||
mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
|
||||
CHECK(!mapp->IsFailure());
|
||||
|
||||
// allocate a garbage
|
||||
String* func_name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
|
||||
SharedFunctionInfo* function_share =
|
||||
SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name));
|
||||
JSFunction* function =
|
||||
JSFunction::cast(Heap::AllocateFunction(*Top::function_map(),
|
||||
function_share,
|
||||
Heap::undefined_value()));
|
||||
Map* initial_map =
|
||||
Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize));
|
||||
function->set_initial_map(initial_map);
|
||||
Top::context()->global()->SetProperty(func_name, function, NONE);
|
||||
|
||||
JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function));
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
func_name = String::cast(Heap::LookupAsciiSymbol("theFunction"));
|
||||
CHECK(Top::context()->global()->HasLocalProperty(func_name));
|
||||
Object* func_value = Top::context()->global()->GetProperty(func_name);
|
||||
CHECK(func_value->IsJSFunction());
|
||||
function = JSFunction::cast(func_value);
|
||||
|
||||
obj = JSObject::cast(Heap::AllocateJSObject(function));
|
||||
String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
|
||||
Top::context()->global()->SetProperty(obj_name, obj, NONE);
|
||||
String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
|
||||
obj->SetProperty(prop_name, Smi::FromInt(23), NONE);
|
||||
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
obj_name = String::cast(Heap::LookupAsciiSymbol("theObject"));
|
||||
CHECK(Top::context()->global()->HasLocalProperty(obj_name));
|
||||
CHECK(Top::context()->global()->GetProperty(obj_name)->IsJSObject());
|
||||
obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name));
|
||||
prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot"));
|
||||
CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23));
|
||||
}
|
||||
|
||||
|
||||
static int gc_starts = 0;
|
||||
static int gc_ends = 0;
|
||||
|
||||
static void GCPrologueCallbackFunc() {
|
||||
CHECK(gc_starts == gc_ends);
|
||||
gc_starts++;
|
||||
}
|
||||
|
||||
|
||||
static void GCEpilogueCallbackFunc() {
|
||||
CHECK(gc_starts == gc_ends + 1);
|
||||
gc_ends++;
|
||||
}
|
||||
|
||||
|
||||
TEST(GCCallback) {
|
||||
InitializeVM();
|
||||
|
||||
Heap::SetGlobalGCPrologueCallback(&GCPrologueCallbackFunc);
|
||||
Heap::SetGlobalGCEpilogueCallback(&GCEpilogueCallbackFunc);
|
||||
|
||||
// Scavenge does not call GC callback functions.
|
||||
Heap::PerformScavenge();
|
||||
|
||||
CHECK_EQ(0, gc_starts);
|
||||
CHECK_EQ(gc_ends, gc_starts);
|
||||
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
CHECK_EQ(1, gc_starts);
|
||||
CHECK_EQ(gc_ends, gc_starts);
|
||||
}
|
||||
|
||||
|
||||
static int NumberOfWeakCalls = 0;
|
||||
static void WeakPointerCallback(v8::Persistent<v8::Object> handle, void* id) {
|
||||
NumberOfWeakCalls++;
|
||||
}
|
||||
|
||||
TEST(ObjectGroups) {
|
||||
InitializeVM();
|
||||
|
||||
NumberOfWeakCalls = 0;
|
||||
v8::HandleScope handle_scope;
|
||||
|
||||
Handle<Object> g1s1 =
|
||||
GlobalHandles::Create(Heap::AllocateFixedArray(1));
|
||||
Handle<Object> g1s2 =
|
||||
GlobalHandles::Create(Heap::AllocateFixedArray(1));
|
||||
GlobalHandles::MakeWeak(g1s1.location(),
|
||||
reinterpret_cast<void*>(1234),
|
||||
&WeakPointerCallback);
|
||||
GlobalHandles::MakeWeak(g1s2.location(),
|
||||
reinterpret_cast<void*>(1234),
|
||||
&WeakPointerCallback);
|
||||
|
||||
Handle<Object> g2s1 =
|
||||
GlobalHandles::Create(Heap::AllocateFixedArray(1));
|
||||
Handle<Object> g2s2 =
|
||||
GlobalHandles::Create(Heap::AllocateFixedArray(1));
|
||||
GlobalHandles::MakeWeak(g2s1.location(),
|
||||
reinterpret_cast<void*>(1234),
|
||||
&WeakPointerCallback);
|
||||
GlobalHandles::MakeWeak(g2s2.location(),
|
||||
reinterpret_cast<void*>(1234),
|
||||
&WeakPointerCallback);
|
||||
|
||||
Handle<Object> root = GlobalHandles::Create(*g1s1); // make a root.
|
||||
|
||||
// Connect group 1 and 2, make a cycle.
|
||||
Handle<FixedArray>::cast(g1s2)->set(0, *g2s2);
|
||||
Handle<FixedArray>::cast(g2s1)->set(0, *g1s1);
|
||||
|
||||
GlobalHandles::AddToGroup(reinterpret_cast<void*>(1), g1s1.location());
|
||||
GlobalHandles::AddToGroup(reinterpret_cast<void*>(1), g1s2.location());
|
||||
GlobalHandles::AddToGroup(reinterpret_cast<void*>(2), g2s1.location());
|
||||
GlobalHandles::AddToGroup(reinterpret_cast<void*>(2), g2s2.location());
|
||||
// Do a full GC
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
// All object should be alive.
|
||||
CHECK_EQ(0, NumberOfWeakCalls);
|
||||
|
||||
// Weaken the root.
|
||||
GlobalHandles::MakeWeak(root.location(),
|
||||
reinterpret_cast<void*>(1234),
|
||||
&WeakPointerCallback);
|
||||
|
||||
// Groups are deleted, rebuild groups.
|
||||
GlobalHandles::AddToGroup(reinterpret_cast<void*>(1), g1s1.location());
|
||||
GlobalHandles::AddToGroup(reinterpret_cast<void*>(1), g1s2.location());
|
||||
GlobalHandles::AddToGroup(reinterpret_cast<void*>(2), g2s1.location());
|
||||
GlobalHandles::AddToGroup(reinterpret_cast<void*>(2), g2s2.location());
|
||||
|
||||
CHECK(Heap::CollectGarbage(0, OLD_SPACE));
|
||||
|
||||
// All objects should be gone. 5 global handles in total.
|
||||
CHECK_EQ(5, NumberOfWeakCalls);
|
||||
}
|
80
test/cctest/test-platform-linux.cc
Normal file
80
test/cctest/test-platform-linux.cc
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright 2006-2008 Google, Inc. All Rights Reserved.
|
||||
//
|
||||
// Tests of the TokenLock class from lock.h
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h> // for usleep()
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace ::v8::internal;
|
||||
|
||||
|
||||
static void yield() {
|
||||
usleep(1);
|
||||
}
|
||||
|
||||
static const int kLockCounterLimit = 50;
|
||||
static int busy_lock_counter = 0;
|
||||
|
||||
|
||||
static void LoopIncrement(Mutex* mutex, int rem) {
|
||||
while (true) {
|
||||
int count = 0;
|
||||
int last_count = -1;
|
||||
do {
|
||||
CHECK_EQ(0, mutex->Lock());
|
||||
count = busy_lock_counter;
|
||||
CHECK_EQ(0, mutex->Unlock());
|
||||
yield();
|
||||
} while (count % 2 == rem && count < kLockCounterLimit);
|
||||
if (count >= kLockCounterLimit) break;
|
||||
CHECK_EQ(0, mutex->Lock());
|
||||
CHECK_EQ(count, busy_lock_counter);
|
||||
CHECK(last_count == -1 || count == last_count + 1);
|
||||
busy_lock_counter++;
|
||||
last_count = count;
|
||||
CHECK_EQ(0, mutex->Unlock());
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void* RunTestBusyLock(void* arg) {
|
||||
LoopIncrement(static_cast<Mutex*>(arg), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Runs two threads that repeatedly acquire the lock and conditionally
|
||||
// increment a variable.
|
||||
TEST(BusyLock) {
|
||||
pthread_t other;
|
||||
Mutex* mutex = OS::CreateMutex();
|
||||
int thread_created = pthread_create(&other,
|
||||
NULL,
|
||||
&RunTestBusyLock,
|
||||
mutex);
|
||||
CHECK_EQ(0, thread_created);
|
||||
LoopIncrement(mutex, 1);
|
||||
pthread_join(other, NULL);
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
|
||||
TEST(VirtualMemory) {
|
||||
VirtualMemory* vm = new VirtualMemory(1 * MB);
|
||||
CHECK(vm->IsReserved());
|
||||
void* block_addr = vm->address();
|
||||
size_t block_size = 4 * KB;
|
||||
CHECK(vm->Commit(block_addr, block_size, false));
|
||||
// Check whether we can write to memory.
|
||||
int* addr = static_cast<int*>(block_addr);
|
||||
addr[KB-1] = 2;
|
||||
CHECK(vm->Uncommit(block_addr, block_size));
|
||||
delete vm;
|
||||
}
|
10
test/cctest/test-platform-macos.cc
Normal file
10
test/cctest/test-platform-macos.cc
Normal file
@ -0,0 +1,10 @@
|
||||
// Copyright 2006-2008 Google, Inc. All Rights Reserved.
|
||||
//
|
||||
// Tests of the TokenLock class from lock.h
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace ::v8::internal;
|
80
test/cctest/test-platform-nullos.cc
Normal file
80
test/cctest/test-platform-nullos.cc
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright 2006-2008 Google, Inc. All Rights Reserved.
|
||||
//
|
||||
// Tests of the TokenLock class from lock.h
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h> // for usleep()
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace ::v8::internal;
|
||||
|
||||
|
||||
static void yield() {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
static const int kLockCounterLimit = 50;
|
||||
static int busy_lock_counter = 0;
|
||||
|
||||
|
||||
static void LoopIncrement(Mutex* mutex, int rem) {
|
||||
while (true) {
|
||||
int count = 0;
|
||||
int last_count = -1;
|
||||
do {
|
||||
CHECK_EQ(0, mutex->Lock());
|
||||
count = busy_lock_counter;
|
||||
CHECK_EQ(0, mutex->Unlock());
|
||||
yield();
|
||||
} while (count % 2 == rem && count < kLockCounterLimit);
|
||||
if (count >= kLockCounterLimit) break;
|
||||
CHECK_EQ(0, mutex->Lock());
|
||||
CHECK_EQ(count, busy_lock_counter);
|
||||
CHECK(last_count == -1 || count == last_count + 1);
|
||||
busy_lock_counter++;
|
||||
last_count = count;
|
||||
CHECK_EQ(0, mutex->Unlock());
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void* RunTestBusyLock(void* arg) {
|
||||
LoopIncrement(static_cast<Mutex*>(arg), 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Runs two threads that repeatedly acquire the lock and conditionally
|
||||
// increment a variable.
|
||||
TEST(BusyLock) {
|
||||
pthread_t other;
|
||||
Mutex* mutex = OS::CreateMutex();
|
||||
int thread_created = pthread_create(&other,
|
||||
NULL,
|
||||
&RunTestBusyLock,
|
||||
mutex);
|
||||
CHECK_EQ(0, thread_created);
|
||||
LoopIncrement(mutex, 1);
|
||||
pthread_join(other, NULL);
|
||||
delete mutex;
|
||||
}
|
||||
|
||||
|
||||
TEST(VirtualMemory) {
|
||||
VirtualMemory* vm = new VirtualMemory(1 * MB);
|
||||
CHECK(vm->IsReserved());
|
||||
void* block_addr = vm->address();
|
||||
size_t block_size = 4 * KB;
|
||||
CHECK(vm->Commit(block_addr, block_size, false));
|
||||
// Check whether we can write to memory.
|
||||
int* addr = static_cast<int*>(block_addr);
|
||||
addr[KB-1] = 2;
|
||||
CHECK(vm->Uncommit(block_addr, block_size));
|
||||
delete vm;
|
||||
}
|
26
test/cctest/test-platform-win32.cc
Normal file
26
test/cctest/test-platform-win32.cc
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2006-2008 Google, Inc. All Rights Reserved.
|
||||
//
|
||||
// Tests of the TokenLock class from lock.h
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace ::v8::internal;
|
||||
|
||||
|
||||
TEST(VirtualMemory) {
|
||||
VirtualMemory* vm = new VirtualMemory(1 * MB);
|
||||
CHECK(vm->IsReserved());
|
||||
void* block_addr = vm->address();
|
||||
size_t block_size = 4 * KB;
|
||||
CHECK(vm->Commit(block_addr, block_size, false));
|
||||
// Check whether we can write to memory.
|
||||
int* addr = static_cast<int*>(block_addr);
|
||||
addr[KB-1] = 2;
|
||||
CHECK(vm->Uncommit(block_addr, block_size));
|
||||
delete vm;
|
||||
}
|
280
test/cctest/test-serialize.cc
Normal file
280
test/cctest/test-serialize.cc
Normal file
@ -0,0 +1,280 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <signal.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "sys/stat.h"
|
||||
#include "v8.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "ic-inl.h"
|
||||
#include "runtime.h"
|
||||
#include "serialize.h"
|
||||
#include "scopeinfo.h"
|
||||
#include "snapshot.h"
|
||||
#include "cctest.h"
|
||||
|
||||
namespace v8 { namespace internal {
|
||||
|
||||
#ifdef WIN32
|
||||
DEFINE_string(serialization_file, "C:\\Windows\\Temp\\serdes",
|
||||
"file in which to serialize heap");
|
||||
#else
|
||||
DEFINE_string(serialization_file, "/tmp/serdes",
|
||||
"file in which to serialize heap");
|
||||
#endif
|
||||
DECLARE_bool(debug_serialization);
|
||||
}} // namespace v8::internal
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
|
||||
static int local_counters[256];
|
||||
static int counter_count = 0;
|
||||
static std::map<std::wstring, int> counter_table;
|
||||
|
||||
|
||||
// Callback receiver to track counters in test.
|
||||
static int* counter_function(const wchar_t* name) {
|
||||
std::wstring counter(name);
|
||||
if (counter_table.find(counter) == counter_table.end()) {
|
||||
local_counters[counter_count] = 0;
|
||||
counter_table[counter] = counter_count++;
|
||||
}
|
||||
|
||||
return &local_counters[counter_table[counter]];
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
static Address AddressOf(T id) {
|
||||
return ExternalReference(id).address();
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
static uint32_t Encode(const ExternalReferenceEncoder& encoder, T id) {
|
||||
return encoder.Encode(AddressOf(id));
|
||||
}
|
||||
|
||||
|
||||
static int make_code(TypeCode type, int id) {
|
||||
return static_cast<uint32_t>(type) << kReferenceTypeShift | id;
|
||||
}
|
||||
|
||||
|
||||
static int register_code(int reg) {
|
||||
return Debug::k_register_address << kDebugIdShift | reg;
|
||||
}
|
||||
|
||||
|
||||
TEST(ExternalReferenceEncoder) {
|
||||
StatsTable::SetCounterFunction(counter_function);
|
||||
Heap::Setup(false);
|
||||
ExternalReferenceEncoder encoder;
|
||||
CHECK_EQ(make_code(BUILTIN, Builtins::ArrayCode),
|
||||
Encode(encoder, Builtins::ArrayCode));
|
||||
CHECK_EQ(make_code(RUNTIME_FUNCTION, Runtime::kAbort),
|
||||
Encode(encoder, Runtime::kAbort));
|
||||
CHECK_EQ(make_code(IC_UTILITY, IC::kLoadCallbackProperty),
|
||||
Encode(encoder, IC_Utility(IC::kLoadCallbackProperty)));
|
||||
CHECK_EQ(make_code(DEBUG_ADDRESS, register_code(3)),
|
||||
Encode(encoder, Debug_Address(Debug::k_register_address, 3)));
|
||||
ExternalReference keyed_load_function_prototype =
|
||||
ExternalReference(&Counters::keyed_load_function_prototype);
|
||||
CHECK_EQ(make_code(STATS_COUNTER, Counters::k_keyed_load_function_prototype),
|
||||
encoder.Encode(keyed_load_function_prototype.address()));
|
||||
ExternalReference passed_function =
|
||||
ExternalReference::builtin_passed_function();
|
||||
CHECK_EQ(make_code(UNCLASSIFIED, 1),
|
||||
encoder.Encode(passed_function.address()));
|
||||
ExternalReference the_hole_value_location =
|
||||
ExternalReference::the_hole_value_location();
|
||||
CHECK_EQ(make_code(UNCLASSIFIED, 2),
|
||||
encoder.Encode(the_hole_value_location.address()));
|
||||
ExternalReference stack_guard_limit_address =
|
||||
ExternalReference::address_of_stack_guard_limit();
|
||||
CHECK_EQ(make_code(UNCLASSIFIED, 3),
|
||||
encoder.Encode(stack_guard_limit_address.address()));
|
||||
CHECK_EQ(make_code(UNCLASSIFIED, 4),
|
||||
encoder.Encode(ExternalReference::debug_break().address()));
|
||||
CHECK_EQ(make_code(UNCLASSIFIED, 5),
|
||||
encoder.Encode(ExternalReference::new_space_start().address()));
|
||||
}
|
||||
|
||||
|
||||
TEST(ExternalReferenceDecoder) {
|
||||
StatsTable::SetCounterFunction(counter_function);
|
||||
Heap::Setup(false);
|
||||
ExternalReferenceDecoder decoder;
|
||||
CHECK_EQ(AddressOf(Builtins::ArrayCode),
|
||||
decoder.Decode(make_code(BUILTIN, Builtins::ArrayCode)));
|
||||
CHECK_EQ(AddressOf(Runtime::kAbort),
|
||||
decoder.Decode(make_code(RUNTIME_FUNCTION, Runtime::kAbort)));
|
||||
CHECK_EQ(AddressOf(IC_Utility(IC::kLoadCallbackProperty)),
|
||||
decoder.Decode(make_code(IC_UTILITY, IC::kLoadCallbackProperty)));
|
||||
CHECK_EQ(AddressOf(Debug_Address(Debug::k_register_address, 3)),
|
||||
decoder.Decode(make_code(DEBUG_ADDRESS, register_code(3))));
|
||||
ExternalReference keyed_load_function =
|
||||
ExternalReference(&Counters::keyed_load_function_prototype);
|
||||
CHECK_EQ(keyed_load_function.address(),
|
||||
decoder.Decode(
|
||||
make_code(STATS_COUNTER,
|
||||
Counters::k_keyed_load_function_prototype)));
|
||||
CHECK_EQ(ExternalReference::builtin_passed_function().address(),
|
||||
decoder.Decode(make_code(UNCLASSIFIED, 1)));
|
||||
CHECK_EQ(ExternalReference::the_hole_value_location().address(),
|
||||
decoder.Decode(make_code(UNCLASSIFIED, 2)));
|
||||
CHECK_EQ(ExternalReference::address_of_stack_guard_limit().address(),
|
||||
decoder.Decode(make_code(UNCLASSIFIED, 3)));
|
||||
CHECK_EQ(ExternalReference::debug_break().address(),
|
||||
decoder.Decode(make_code(UNCLASSIFIED, 4)));
|
||||
CHECK_EQ(ExternalReference::new_space_start().address(),
|
||||
decoder.Decode(make_code(UNCLASSIFIED, 5)));
|
||||
}
|
||||
|
||||
|
||||
static void Serialize() {
|
||||
#ifdef DEBUG
|
||||
FLAG_debug_serialization = true;
|
||||
#endif
|
||||
StatsTable::SetCounterFunction(counter_function);
|
||||
|
||||
v8::HandleScope scope;
|
||||
const int kExtensionCount = 5;
|
||||
const char* extension_list[kExtensionCount] =
|
||||
{ "v8/print", "v8/load", "v8/quit", "v8/version", "v8/gc" };
|
||||
v8::ExtensionConfiguration extensions(kExtensionCount, extension_list);
|
||||
v8::Persistent<v8::Context> env = v8::Context::New(&extensions);
|
||||
env->Enter();
|
||||
|
||||
Snapshot::WriteToFile(FLAG_serialization_file);
|
||||
}
|
||||
|
||||
|
||||
// Test that the whole heap can be serialized when running from the
|
||||
// internal snapshot.
|
||||
// (Smoke test.)
|
||||
TEST(SerializeInternal) {
|
||||
Snapshot::Initialize(NULL);
|
||||
Serialize();
|
||||
}
|
||||
|
||||
|
||||
// Test that the whole heap can be serialized when running from a
|
||||
// bootstrapped heap.
|
||||
// (Smoke test.)
|
||||
TEST(Serialize) {
|
||||
Snapshot::DisableInternal();
|
||||
Serialize();
|
||||
}
|
||||
|
||||
|
||||
// Test that the heap isn't destroyed after a serialization.
|
||||
TEST(SerializeNondestructive) {
|
||||
Snapshot::DisableInternal();
|
||||
StatsTable::SetCounterFunction(counter_function);
|
||||
v8::HandleScope scope;
|
||||
v8::Persistent<v8::Context> env = v8::Context::New();
|
||||
v8::Context::Scope context_scope(env);
|
||||
Serializer().Serialize();
|
||||
const char* c_source = "\"abcd\".charAt(2) == 'c'";
|
||||
v8::Local<v8::String> source = v8::String::New(c_source);
|
||||
v8::Local<v8::Script> script = v8::Script::Compile(source);
|
||||
v8::Local<v8::Value> value = script->Run();
|
||||
CHECK(value->BooleanValue());
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Tests that the heap can be deserialized.
|
||||
|
||||
static void Deserialize() {
|
||||
#ifdef DEBUG
|
||||
FLAG_debug_serialization = true;
|
||||
#endif
|
||||
CHECK(Snapshot::Initialize(FLAG_serialization_file));
|
||||
}
|
||||
|
||||
|
||||
static void SanityCheck() {
|
||||
v8::HandleScope scope;
|
||||
#ifdef DEBUG
|
||||
Heap::Verify();
|
||||
#endif
|
||||
CHECK(Top::global()->IsJSObject());
|
||||
CHECK(Top::global_context()->IsContext());
|
||||
CHECK(Top::special_function_table()->IsFixedArray());
|
||||
CHECK(Heap::symbol_table()->IsSymbolTable());
|
||||
CHECK(!Factory::LookupAsciiSymbol("Empty")->IsFailure());
|
||||
}
|
||||
|
||||
|
||||
TEST(Deserialize) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
Deserialize();
|
||||
|
||||
SanityCheck();
|
||||
}
|
||||
|
||||
TEST(DeserializeAndRunScript) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
Deserialize();
|
||||
|
||||
const char* c_source = "\"1234\".length";
|
||||
v8::Local<v8::String> source = v8::String::New(c_source);
|
||||
v8::Local<v8::Script> script = v8::Script::Compile(source);
|
||||
CHECK_EQ(4, script->Run()->Int32Value());
|
||||
}
|
||||
|
||||
|
||||
TEST(DeserializeNatives) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
Deserialize();
|
||||
|
||||
const char* c_source = "\"abcd\".charAt(2) == 'c'";
|
||||
v8::Local<v8::String> source = v8::String::New(c_source);
|
||||
v8::Local<v8::Script> script = v8::Script::Compile(source);
|
||||
v8::Local<v8::Value> value = script->Run();
|
||||
CHECK(value->BooleanValue());
|
||||
}
|
||||
|
||||
|
||||
TEST(DeserializeExtensions) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
Deserialize();
|
||||
const char* c_source = "print(\"abcd\");";
|
||||
v8::Local<v8::String> source = v8::String::New(c_source);
|
||||
v8::Local<v8::Script> script = v8::Script::Compile(source);
|
||||
v8::Local<v8::Value> value = script->Run();
|
||||
CHECK(value->IsUndefined());
|
||||
}
|
254
test/cctest/test-spaces.cc
Normal file
254
test/cctest/test-spaces.cc
Normal file
@ -0,0 +1,254 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
static void VerifyRSet(Address page_start) {
|
||||
#ifdef DEBUG
|
||||
Page::set_rset_state(Page::IN_USE);
|
||||
#endif
|
||||
|
||||
Page* p = Page::FromAddress(page_start);
|
||||
|
||||
p->ClearRSet();
|
||||
|
||||
for (Address addr = p->ObjectAreaStart();
|
||||
addr < p->ObjectAreaEnd();
|
||||
addr += kPointerSize) {
|
||||
CHECK(!Page::IsRSetSet(addr, 0));
|
||||
}
|
||||
|
||||
for (Address addr = p->ObjectAreaStart();
|
||||
addr < p->ObjectAreaEnd();
|
||||
addr += kPointerSize) {
|
||||
Page::SetRSet(addr, 0);
|
||||
}
|
||||
|
||||
for (Address addr = p->ObjectAreaStart();
|
||||
addr < p->ObjectAreaEnd();
|
||||
addr += kPointerSize) {
|
||||
CHECK(Page::IsRSetSet(addr, 0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(Page) {
|
||||
#ifdef DEBUG
|
||||
Page::set_rset_state(Page::NOT_IN_USE);
|
||||
#endif
|
||||
|
||||
byte* mem = NewArray<byte>(2*Page::kPageSize);
|
||||
CHECK(mem != NULL);
|
||||
|
||||
Address start = reinterpret_cast<Address>(mem);
|
||||
Address page_start = RoundUp(start, Page::kPageSize);
|
||||
|
||||
Page* p = Page::FromAddress(page_start);
|
||||
CHECK(p->address() == page_start);
|
||||
CHECK(p->is_valid());
|
||||
|
||||
p->opaque_header = 0;
|
||||
p->is_normal_page = 0x1;
|
||||
CHECK(!p->next_page()->is_valid());
|
||||
|
||||
CHECK(p->ObjectAreaStart() == page_start + Page::kObjectStartOffset);
|
||||
CHECK(p->ObjectAreaEnd() == page_start + Page::kPageSize);
|
||||
|
||||
CHECK(p->Offset(page_start + Page::kObjectStartOffset) ==
|
||||
Page::kObjectStartOffset);
|
||||
CHECK(p->Offset(page_start + Page::kPageSize) == Page::kPageSize);
|
||||
|
||||
CHECK(p->OffsetToAddress(Page::kObjectStartOffset) == p->ObjectAreaStart());
|
||||
CHECK(p->OffsetToAddress(Page::kPageSize) == p->ObjectAreaEnd());
|
||||
|
||||
// test remember set
|
||||
VerifyRSet(page_start);
|
||||
|
||||
DeleteArray(mem);
|
||||
}
|
||||
|
||||
|
||||
TEST(MemoryAllocator) {
|
||||
CHECK(Heap::ConfigureHeapDefault());
|
||||
CHECK(MemoryAllocator::Setup(Heap::MaxCapacity()));
|
||||
|
||||
OldSpace faked_space(Heap::MaxCapacity(), OLD_SPACE, false);
|
||||
int total_pages = 0;
|
||||
int requested = 2;
|
||||
int allocated;
|
||||
// If we request two pages, we should get one or two.
|
||||
Page* first_page =
|
||||
MemoryAllocator::AllocatePages(requested, &allocated, &faked_space);
|
||||
CHECK(first_page->is_valid());
|
||||
CHECK(allocated > 0 && allocated <= 2);
|
||||
total_pages += allocated;
|
||||
|
||||
Page* last_page = first_page;
|
||||
for (Page* p = first_page; p->is_valid(); p = p->next_page()) {
|
||||
CHECK(MemoryAllocator::IsPageInSpace(p, &faked_space));
|
||||
last_page = p;
|
||||
}
|
||||
|
||||
// Again, we should get one or two pages.
|
||||
Page* others =
|
||||
MemoryAllocator::AllocatePages(requested, &allocated, &faked_space);
|
||||
CHECK(others->is_valid());
|
||||
CHECK(allocated > 0 && allocated <= 2);
|
||||
total_pages += allocated;
|
||||
|
||||
MemoryAllocator::SetNextPage(last_page, others);
|
||||
int page_count = 0;
|
||||
for (Page* p = first_page; p->is_valid(); p = p->next_page()) {
|
||||
CHECK(MemoryAllocator::IsPageInSpace(p, &faked_space));
|
||||
page_count++;
|
||||
}
|
||||
CHECK(total_pages == page_count);
|
||||
|
||||
Page* second_page = first_page->next_page();
|
||||
CHECK(second_page->is_valid());
|
||||
|
||||
// Freeing pages at the first chunk starting at or after the second page
|
||||
// should free the entire second chunk. It will return the last page in the
|
||||
// first chunk (if the second page was in the first chunk) or else an
|
||||
// invalid page (if the second page was the start of the second chunk).
|
||||
Page* free_return = MemoryAllocator::FreePages(second_page);
|
||||
CHECK(free_return == last_page || !free_return->is_valid());
|
||||
MemoryAllocator::SetNextPage(first_page, free_return);
|
||||
|
||||
// Freeing pages in the first chunk starting at the first page should free
|
||||
// the first chunk and return an invalid page.
|
||||
Page* invalid_page = MemoryAllocator::FreePages(first_page);
|
||||
CHECK(!invalid_page->is_valid());
|
||||
|
||||
MemoryAllocator::TearDown();
|
||||
}
|
||||
|
||||
|
||||
TEST(NewSpace) {
|
||||
CHECK(Heap::ConfigureHeapDefault());
|
||||
CHECK(MemoryAllocator::Setup(Heap::MaxCapacity()));
|
||||
|
||||
NewSpace* s = new NewSpace(Heap::InitialSemiSpaceSize(),
|
||||
Heap::SemiSpaceSize(),
|
||||
NEW_SPACE,
|
||||
false);
|
||||
CHECK(s != NULL);
|
||||
|
||||
void* chunk =
|
||||
MemoryAllocator::ReserveInitialChunk(2 * Heap::YoungGenerationSize());
|
||||
CHECK(chunk != NULL);
|
||||
Address start = RoundUp(static_cast<Address>(chunk),
|
||||
Heap::YoungGenerationSize());
|
||||
CHECK(s->Setup(start, Heap::YoungGenerationSize()));
|
||||
CHECK(s->HasBeenSetup());
|
||||
|
||||
while (s->Available() >= Page::kMaxHeapObjectSize) {
|
||||
Object* obj = s->AllocateRaw(Page::kMaxHeapObjectSize);
|
||||
CHECK(!obj->IsFailure());
|
||||
CHECK(s->Contains(HeapObject::cast(obj)));
|
||||
}
|
||||
|
||||
s->TearDown();
|
||||
delete s;
|
||||
MemoryAllocator::TearDown();
|
||||
}
|
||||
|
||||
|
||||
TEST(OldSpace) {
|
||||
CHECK(Heap::ConfigureHeapDefault());
|
||||
CHECK(MemoryAllocator::Setup(Heap::MaxCapacity()));
|
||||
|
||||
OldSpace* s = new OldSpace(Heap::OldGenerationSize(), OLD_SPACE, false);
|
||||
CHECK(s != NULL);
|
||||
|
||||
void* chunk =
|
||||
MemoryAllocator::ReserveInitialChunk(2 * Heap::YoungGenerationSize());
|
||||
CHECK(chunk != NULL);
|
||||
Address start = static_cast<Address>(chunk);
|
||||
size_t size = RoundUp(start, Heap::YoungGenerationSize()) - start;
|
||||
|
||||
CHECK(s->Setup(start, size));
|
||||
|
||||
while (s->Available() > 0) {
|
||||
Object* obj = s->AllocateRaw(Page::kMaxHeapObjectSize);
|
||||
CHECK(!obj->IsFailure());
|
||||
}
|
||||
|
||||
s->TearDown();
|
||||
delete s;
|
||||
MemoryAllocator::TearDown();
|
||||
}
|
||||
|
||||
|
||||
TEST(LargeObjectSpace) {
|
||||
CHECK(Heap::ConfigureHeapDefault());
|
||||
MemoryAllocator::Setup(Heap::MaxCapacity());
|
||||
|
||||
LargeObjectSpace* lo = new LargeObjectSpace(LO_SPACE, false);
|
||||
CHECK(lo != NULL);
|
||||
|
||||
CHECK(lo->Setup());
|
||||
|
||||
Map* faked_map = reinterpret_cast<Map*>(HeapObject::FromAddress(0));
|
||||
int lo_size = Page::kPageSize;
|
||||
|
||||
Object* obj = lo->AllocateRaw(lo_size);
|
||||
CHECK(!obj->IsFailure());
|
||||
CHECK(obj->IsHeapObject());
|
||||
|
||||
HeapObject* ho = HeapObject::cast(obj);
|
||||
ho->set_map(faked_map);
|
||||
|
||||
CHECK(lo->Contains(HeapObject::cast(obj)));
|
||||
|
||||
CHECK(lo->FindObject(ho->address()) == obj);
|
||||
|
||||
CHECK(lo->Contains(ho));
|
||||
|
||||
while (true) {
|
||||
int available = lo->Available();
|
||||
obj = lo->AllocateRaw(lo_size);
|
||||
if (obj->IsFailure()) break;
|
||||
HeapObject::cast(obj)->set_map(faked_map);
|
||||
CHECK(lo->Available() < available);
|
||||
};
|
||||
|
||||
CHECK(!lo->IsEmpty());
|
||||
|
||||
obj = lo->AllocateRaw(lo_size);
|
||||
CHECK(obj->IsFailure());
|
||||
|
||||
lo->TearDown();
|
||||
delete lo;
|
||||
|
||||
MemoryAllocator::TearDown();
|
||||
}
|
335
test/cctest/test-strings.cc
Normal file
335
test/cctest/test-strings.cc
Normal file
@ -0,0 +1,335 @@
|
||||
// Copyright 2006-2008 Google, Inc. All Rights Reserved.
|
||||
|
||||
// Check that we can traverse very deep stacks of ConsStrings using
|
||||
// StringInputBuffer. Check that Get(int) works on very deep stacks
|
||||
// of ConsStrings. These operations may not be very fast, but they
|
||||
// should be possible without getting errors due to too deep recursion.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "factory.h"
|
||||
#include "cctest.h"
|
||||
|
||||
unsigned int seed = 123;
|
||||
|
||||
static uint32_t gen() {
|
||||
uint64_t z;
|
||||
z = seed;
|
||||
z *= 279470273;
|
||||
z %= 4294967291U;
|
||||
seed = static_cast<unsigned int>(z);
|
||||
return static_cast<uint32_t>(seed >> 16);
|
||||
}
|
||||
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
static v8::Persistent<v8::Context> env;
|
||||
|
||||
|
||||
static void InitializeVM() {
|
||||
if (env.IsEmpty()) {
|
||||
v8::HandleScope scope;
|
||||
const char* extensions[] = { "v8/print" };
|
||||
v8::ExtensionConfiguration config(1, extensions);
|
||||
env = v8::Context::New(&config);
|
||||
}
|
||||
v8::HandleScope scope;
|
||||
env->Enter();
|
||||
}
|
||||
|
||||
|
||||
static const int NUMBER_OF_BUILDING_BLOCKS = 128;
|
||||
static const int DEEP_DEPTH = 8 * 1024;
|
||||
static const int SUPER_DEEP_DEPTH = 80 * 1024;
|
||||
|
||||
|
||||
static void InitializeBuildingBlocks(
|
||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
|
||||
for (int i = 0; i < NUMBER_OF_BUILDING_BLOCKS; i++) {
|
||||
int len = gen() % 16;
|
||||
if (len > 14) {
|
||||
len += 1234;
|
||||
}
|
||||
switch (gen() % 4) {
|
||||
case 0: {
|
||||
uc16 buf[2000];
|
||||
for (int j = 0; j < len; j++) {
|
||||
buf[j] = gen() % 65536;
|
||||
}
|
||||
building_blocks[i] =
|
||||
Factory::NewStringFromTwoByte(Vector<const uc16>(buf, len));
|
||||
for (int j = 0; j < len; j++) {
|
||||
CHECK_EQ(buf[j], building_blocks[i]->Get(j));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
char buf[2000];
|
||||
for (int j = 0; j < len; j++) {
|
||||
buf[j] = gen() % 128;
|
||||
}
|
||||
building_blocks[i] =
|
||||
Factory::NewStringFromAscii(Vector<const char>(buf, len));
|
||||
for (int j = 0; j < len; j++) {
|
||||
CHECK_EQ(buf[j], building_blocks[i]->Get(j));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
class Resource: public v8::String::ExternalStringResource,
|
||||
public Malloced {
|
||||
public:
|
||||
explicit Resource(Vector<const uc16> string): data_(string.start()) {
|
||||
length_ = string.length();
|
||||
}
|
||||
virtual const uint16_t* data() const { return data_; }
|
||||
virtual size_t length() const { return length_; }
|
||||
|
||||
private:
|
||||
const uc16* data_;
|
||||
size_t length_;
|
||||
};
|
||||
uc16* buf = NewArray<uc16>(len);
|
||||
for (int j = 0; j < len; j++) {
|
||||
buf[j] = gen() % 65536;
|
||||
}
|
||||
Resource* resource = new Resource(Vector<const uc16>(buf, len));
|
||||
building_blocks[i] = Factory::NewExternalStringFromTwoByte(resource);
|
||||
for (int j = 0; j < len; j++) {
|
||||
CHECK_EQ(buf[j], building_blocks[i]->Get(j));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
char* buf = NewArray<char>(len);
|
||||
for (int j = 0; j < len; j++) {
|
||||
buf[j] = gen() % 128;
|
||||
}
|
||||
building_blocks[i] =
|
||||
Factory::NewStringFromAscii(Vector<const char>(buf, len));
|
||||
for (int j = 0; j < len; j++) {
|
||||
CHECK_EQ(buf[j], building_blocks[i]->Get(j));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Handle<String> ConstructLeft(
|
||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
|
||||
int depth) {
|
||||
Handle<String> answer = Factory::NewStringFromAscii(CStrVector(""));
|
||||
for (int i = 0; i < depth; i++) {
|
||||
answer =
|
||||
Factory::NewConsString(answer,
|
||||
building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
static Handle<String> ConstructRight(
|
||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
|
||||
int depth) {
|
||||
Handle<String> answer = Factory::NewStringFromAscii(CStrVector(""));
|
||||
for (int i = depth - 1; i >= 0; i--) {
|
||||
answer =
|
||||
Factory::NewConsString(building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
|
||||
answer);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
|
||||
static Handle<String> ConstructBalancedHelper(
|
||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
|
||||
int from,
|
||||
int to) {
|
||||
ASSERT(to > from);
|
||||
if (to - from == 1) {
|
||||
return building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
|
||||
}
|
||||
if (to - from == 2) {
|
||||
return Factory::NewConsString(
|
||||
building_blocks[from % NUMBER_OF_BUILDING_BLOCKS],
|
||||
building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]);
|
||||
}
|
||||
return Factory::NewConsString(
|
||||
ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2)),
|
||||
ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to));
|
||||
}
|
||||
|
||||
|
||||
static Handle<String> ConstructBalanced(
|
||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
|
||||
return ConstructBalancedHelper(building_blocks, 0, DEEP_DEPTH);
|
||||
}
|
||||
|
||||
|
||||
static StringInputBuffer buffer;
|
||||
|
||||
|
||||
static void Traverse(Handle<String> s1, Handle<String> s2) {
|
||||
int i = 0;
|
||||
buffer.Reset(*s1);
|
||||
StringInputBuffer buffer2(*s2);
|
||||
while (buffer.has_more()) {
|
||||
CHECK(buffer2.has_more());
|
||||
uint16_t c = buffer.GetNext();
|
||||
CHECK_EQ(c, buffer2.GetNext());
|
||||
i++;
|
||||
}
|
||||
CHECK_EQ(s1->length(), i);
|
||||
CHECK_EQ(s2->length(), i);
|
||||
}
|
||||
|
||||
|
||||
static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
|
||||
int i = 0;
|
||||
buffer.Reset(*s1);
|
||||
StringInputBuffer buffer2(*s2);
|
||||
while (buffer.has_more() && i < chars) {
|
||||
CHECK(buffer2.has_more());
|
||||
uint16_t c = buffer.GetNext();
|
||||
CHECK_EQ(c, buffer2.GetNext());
|
||||
i++;
|
||||
}
|
||||
s1->Get(s1->length() - 1);
|
||||
s2->Get(s2->length() - 1);
|
||||
}
|
||||
|
||||
|
||||
TEST(Traverse) {
|
||||
printf("TestTraverse\n");
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
|
||||
InitializeBuildingBlocks(building_blocks);
|
||||
Handle<String> flat = ConstructBalanced(building_blocks);
|
||||
FlattenString(flat);
|
||||
Handle<String> left_asymmetric = ConstructLeft(building_blocks, DEEP_DEPTH);
|
||||
Handle<String> right_asymmetric = ConstructRight(building_blocks, DEEP_DEPTH);
|
||||
Handle<String> symmetric = ConstructBalanced(building_blocks);
|
||||
printf("1\n");
|
||||
Traverse(flat, symmetric);
|
||||
printf("2\n");
|
||||
Traverse(flat, left_asymmetric);
|
||||
printf("3\n");
|
||||
Traverse(flat, right_asymmetric);
|
||||
printf("4\n");
|
||||
Handle<String> left_deep_asymmetric =
|
||||
ConstructLeft(building_blocks, SUPER_DEEP_DEPTH);
|
||||
Handle<String> right_deep_asymmetric =
|
||||
ConstructRight(building_blocks, SUPER_DEEP_DEPTH);
|
||||
printf("5\n");
|
||||
TraverseFirst(left_asymmetric, left_deep_asymmetric, 1050);
|
||||
printf("6\n");
|
||||
TraverseFirst(left_asymmetric, right_deep_asymmetric, 65536);
|
||||
printf("7\n");
|
||||
Handle<String> right_deep_slice =
|
||||
Factory::NewStringSlice(left_deep_asymmetric,
|
||||
left_deep_asymmetric->length() - 1050,
|
||||
left_deep_asymmetric->length() - 50);
|
||||
Handle<String> left_deep_slice =
|
||||
Factory::NewStringSlice(right_deep_asymmetric,
|
||||
right_deep_asymmetric->length() - 1050,
|
||||
right_deep_asymmetric->length() - 50);
|
||||
printf("8\n");
|
||||
Traverse(right_deep_slice, left_deep_slice);
|
||||
printf("9\n");
|
||||
FlattenString(left_asymmetric);
|
||||
printf("10\n");
|
||||
Traverse(flat, left_asymmetric);
|
||||
printf("11\n");
|
||||
FlattenString(right_asymmetric);
|
||||
printf("12\n");
|
||||
Traverse(flat, right_asymmetric);
|
||||
printf("14\n");
|
||||
FlattenString(symmetric);
|
||||
printf("15\n");
|
||||
Traverse(flat, symmetric);
|
||||
printf("16\n");
|
||||
FlattenString(left_deep_asymmetric);
|
||||
printf("18\n");
|
||||
}
|
||||
|
||||
|
||||
static Handle<String> SliceOf(Handle<String> underlying) {
|
||||
int start = gen() % underlying->length();
|
||||
int end = start + gen() % (underlying->length() - start);
|
||||
return Factory::NewStringSlice(underlying, start, end);
|
||||
}
|
||||
|
||||
|
||||
static Handle<String> ConstructSliceTree(
|
||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
|
||||
int from,
|
||||
int to) {
|
||||
ASSERT(to > from);
|
||||
if (to - from <= 1)
|
||||
return SliceOf(building_blocks[from % NUMBER_OF_BUILDING_BLOCKS]);
|
||||
if (to - from == 2) {
|
||||
Handle<String> lhs = building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
|
||||
if (gen() % 2 == 0)
|
||||
lhs = SliceOf(lhs);
|
||||
Handle<String> rhs = building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS];
|
||||
if (gen() % 2 == 0)
|
||||
rhs = SliceOf(rhs);
|
||||
return Factory::NewConsString(lhs, rhs);
|
||||
}
|
||||
Handle<String> branch = Factory::NewConsString(
|
||||
ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2)),
|
||||
ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to));
|
||||
if (gen() % 2 == 0)
|
||||
return branch;
|
||||
return(SliceOf(branch));
|
||||
}
|
||||
|
||||
|
||||
TEST(Slice) {
|
||||
printf("TestSlice\n");
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
|
||||
InitializeBuildingBlocks(building_blocks);
|
||||
|
||||
seed = 42;
|
||||
Handle<String> slice_tree =
|
||||
ConstructSliceTree(building_blocks, 0, DEEP_DEPTH);
|
||||
seed = 42;
|
||||
Handle<String> flat_slice_tree =
|
||||
ConstructSliceTree(building_blocks, 0, DEEP_DEPTH);
|
||||
FlattenString(flat_slice_tree);
|
||||
Traverse(flat_slice_tree, slice_tree);
|
||||
}
|
||||
|
||||
static const int DEEP_ASCII_DEPTH = 100000;
|
||||
|
||||
|
||||
TEST(DeepAscii) {
|
||||
printf("TestDeepAscii\n");
|
||||
InitializeVM();
|
||||
v8::HandleScope scope;
|
||||
|
||||
char* foo = NewArray<char>(DEEP_ASCII_DEPTH);
|
||||
for (int i = 0; i < DEEP_ASCII_DEPTH; i++) {
|
||||
foo[i] = "foo "[i % 4];
|
||||
}
|
||||
Handle<String> string =
|
||||
Factory::NewStringFromAscii(Vector<const char>(foo, DEEP_ASCII_DEPTH));
|
||||
Handle<String> foo_string = Factory::NewStringFromAscii(CStrVector("foo"));
|
||||
for (int i = 0; i < DEEP_ASCII_DEPTH; i += 10) {
|
||||
string = Factory::NewConsString(string, foo_string);
|
||||
}
|
||||
Handle<String> flat_string = Factory::NewConsString(string, foo_string);
|
||||
FlattenString(flat_string);
|
||||
|
||||
for (int i = 0; i < 500; i++) {
|
||||
TraverseFirst(flat_string, string, DEEP_ASCII_DEPTH);
|
||||
}
|
||||
}
|
178
test/cctest/test-utils.cc
Normal file
178
test/cctest/test-utils.cc
Normal file
@ -0,0 +1,178 @@
|
||||
// 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
#include "platform.h"
|
||||
#include "cctest.h"
|
||||
|
||||
using namespace v8::internal;
|
||||
|
||||
|
||||
enum Mode {
|
||||
forward,
|
||||
backward_unsigned
|
||||
};
|
||||
|
||||
|
||||
static v8::internal::byte* Write(v8::internal::byte* p, Mode m, int x) {
|
||||
v8::internal::byte* q = NULL;
|
||||
switch (m) {
|
||||
case forward:
|
||||
q = EncodeInt(p, x);
|
||||
CHECK(q <= p + sizeof(x) + 1);
|
||||
break;
|
||||
case backward_unsigned:
|
||||
q = EncodeUnsignedIntBackward(p, x);
|
||||
CHECK(q >= p - sizeof(x) - 1);
|
||||
break;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
static v8::internal::byte* Read(v8::internal::byte* p, Mode m, int x) {
|
||||
v8::internal::byte* q = NULL;
|
||||
int y;
|
||||
switch (m) {
|
||||
case forward:
|
||||
q = DecodeInt(p, &y);
|
||||
CHECK(q <= p + sizeof(y) + 1);
|
||||
break;
|
||||
case backward_unsigned: {
|
||||
unsigned int uy;
|
||||
q = DecodeUnsignedIntBackward(p, &uy);
|
||||
y = uy;
|
||||
CHECK(q >= p - sizeof(uy) - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
CHECK(y == x);
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
static v8::internal::byte* WriteMany(v8::internal::byte* p, Mode m, int x) {
|
||||
p = Write(p, m, x - 7);
|
||||
p = Write(p, m, x - 1);
|
||||
p = Write(p, m, x);
|
||||
p = Write(p, m, x + 1);
|
||||
p = Write(p, m, x + 2);
|
||||
p = Write(p, m, -x - 5);
|
||||
p = Write(p, m, -x - 1);
|
||||
p = Write(p, m, -x);
|
||||
p = Write(p, m, -x + 1);
|
||||
p = Write(p, m, -x + 3);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
static v8::internal::byte* ReadMany(v8::internal::byte* p, Mode m, int x) {
|
||||
p = Read(p, m, x - 7);
|
||||
p = Read(p, m, x - 1);
|
||||
p = Read(p, m, x);
|
||||
p = Read(p, m, x + 1);
|
||||
p = Read(p, m, x + 2);
|
||||
p = Read(p, m, -x - 5);
|
||||
p = Read(p, m, -x - 1);
|
||||
p = Read(p, m, -x);
|
||||
p = Read(p, m, -x + 1);
|
||||
p = Read(p, m, -x + 3);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
void ProcessValues(int* values, int n, Mode m) {
|
||||
v8::internal::byte buf[4 * KB]; // make this big enough
|
||||
v8::internal::byte* p0 = (m == forward ? buf : buf + ARRAY_SIZE(buf));
|
||||
|
||||
v8::internal::byte* p = p0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
p = WriteMany(p, m, values[i]);
|
||||
}
|
||||
|
||||
v8::internal::byte* q = p0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
q = ReadMany(q, m, values[i]);
|
||||
}
|
||||
|
||||
CHECK(p == q);
|
||||
}
|
||||
|
||||
|
||||
TEST(Utils0) {
|
||||
int values[] = {
|
||||
0, 1, 10, 16, 32, 64, 128, 256, 512, 1024, 1234, 5731,
|
||||
10000, 100000, 1000000, 10000000, 100000000, 1000000000
|
||||
};
|
||||
const int n = ARRAY_SIZE(values);
|
||||
|
||||
ProcessValues(values, n, forward);
|
||||
ProcessValues(values, n, backward_unsigned);
|
||||
}
|
||||
|
||||
|
||||
TEST(Utils1) {
|
||||
CHECK_EQ(-1000000, FastD2I(-1000000.0));
|
||||
CHECK_EQ(-1, FastD2I(-1.0));
|
||||
CHECK_EQ(0, FastD2I(0.0));
|
||||
CHECK_EQ(1, FastD2I(1.0));
|
||||
CHECK_EQ(1000000, FastD2I(1000000.0));
|
||||
|
||||
CHECK_EQ(-1000000, FastD2I(-1000000.123));
|
||||
CHECK_EQ(-1, FastD2I(-1.234));
|
||||
CHECK_EQ(0, FastD2I(0.345));
|
||||
CHECK_EQ(1, FastD2I(1.234));
|
||||
CHECK_EQ(1000000, FastD2I(1000000.123));
|
||||
}
|
||||
|
||||
|
||||
TEST(SNPrintF) {
|
||||
// Make sure that strings that are truncated because of too small
|
||||
// buffers are zero-terminated anyway.
|
||||
const char* s = "the quick lazy .... oh forget it!";
|
||||
int length = strlen(s);
|
||||
for (int i = 1; i < length * 2; i++) {
|
||||
static const char kMarker = static_cast<char>(42);
|
||||
char* buffer = NewArray<char>(i + 1);
|
||||
buffer[i] = kMarker;
|
||||
int n = OS::SNPrintF(buffer, i, "%s", s);
|
||||
CHECK(n <= i);
|
||||
CHECK(n == length || n == -1);
|
||||
CHECK_EQ(0, strncmp(buffer, s, i - 1));
|
||||
CHECK_EQ(kMarker, buffer[i]);
|
||||
if (i <= length) {
|
||||
CHECK_EQ(i - 1, strlen(buffer));
|
||||
} else {
|
||||
CHECK_EQ(length, strlen(buffer));
|
||||
}
|
||||
}
|
||||
}
|
184
test/mjsunit/apply.js
Normal file
184
test/mjsunit/apply.js
Normal file
@ -0,0 +1,184 @@
|
||||
// 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.
|
||||
|
||||
function f0() {
|
||||
return this;
|
||||
}
|
||||
|
||||
function f1(a) {
|
||||
return a;
|
||||
}
|
||||
|
||||
assertTrue(this === f0.apply(), "1-0");
|
||||
|
||||
assertTrue(this === f0.apply(this), "2a");
|
||||
assertTrue(this === f0.apply(this, new Array(1)), "2b");
|
||||
assertTrue(this === f0.apply(this, new Array(2)), "2c");
|
||||
assertTrue(this === f0.apply(this, new Array(4242)), "2c");
|
||||
|
||||
assertTrue(this === f0.apply(null), "3a");
|
||||
assertTrue(this === f0.apply(null, new Array(1)), "3b");
|
||||
assertTrue(this === f0.apply(null, new Array(2)), "3c");
|
||||
assertTrue(this === f0.apply(this, new Array(4242)), "2c");
|
||||
|
||||
assertTrue(this === f0.apply(void 0), "4a");
|
||||
assertTrue(this === f0.apply(void 0, new Array(1)), "4b");
|
||||
assertTrue(this === f0.apply(void 0, new Array(2)), "4c");
|
||||
|
||||
assertTrue(void 0 === f1.apply(), "1-1");
|
||||
|
||||
assertTrue(void 0 === f1.apply(this), "2a");
|
||||
assertTrue(void 0 === f1.apply(this, new Array(1)), "2b");
|
||||
assertTrue(void 0 === f1.apply(this, new Array(2)), "2c");
|
||||
assertTrue(void 0 === f1.apply(this, new Array(4242)), "2c");
|
||||
assertTrue(42 === f1.apply(this, new Array(42, 43)), "2c");
|
||||
assertEquals("foo", f1.apply(this, new Array("foo", "bar", "baz", "boo")), "2c");
|
||||
|
||||
assertTrue(void 0 === f1.apply(null), "3a");
|
||||
assertTrue(void 0 === f1.apply(null, new Array(1)), "3b");
|
||||
assertTrue(void 0 === f1.apply(null, new Array(2)), "3c");
|
||||
assertTrue(void 0 === f1.apply(null, new Array(4242)), "2c");
|
||||
assertTrue(42 === f1.apply(null, new Array(42, 43)), "2c");
|
||||
assertEquals("foo", f1.apply(null, new Array("foo", "bar", "baz", "boo")), "2c");
|
||||
|
||||
assertTrue(void 0 === f1.apply(void 0), "4a");
|
||||
assertTrue(void 0 === f1.apply(void 0, new Array(1)), "4b");
|
||||
assertTrue(void 0 === f1.apply(void 0, new Array(2)), "4c");
|
||||
assertTrue(void 0 === f1.apply(void 0, new Array(4242)), "4c");
|
||||
assertTrue(42 === f1.apply(void 0, new Array(42, 43)), "2c");
|
||||
assertEquals("foo", f1.apply(void 0, new Array("foo", "bar", "baz", "boo")), "2c");
|
||||
|
||||
var arr = new Array(42, "foo", "fish", "horse");
|
||||
function j(a, b, c, d, e, f, g, h, i, j, k, l) {
|
||||
return "" + a + b + c + d + e + f + g + h + i + j + k + l;
|
||||
}
|
||||
|
||||
|
||||
var expect = "42foofishhorse";
|
||||
for (var i = 0; i < 8; i++)
|
||||
expect += "undefined";
|
||||
assertEquals(expect, j.apply(undefined, arr));
|
||||
|
||||
assertThrows("f0.apply(this, 1);");
|
||||
assertThrows("f0.apply(this, 1, 2);");
|
||||
assertThrows("f0.apply(this, 1, new Array(2));");
|
||||
|
||||
function f() {
|
||||
var doo = "";
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
doo += arguments[i];
|
||||
}
|
||||
return doo;
|
||||
}
|
||||
|
||||
assertEquals("42foofishhorse", f.apply(this, arr));
|
||||
|
||||
function s() {
|
||||
var doo = this;
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
doo += arguments[i];
|
||||
}
|
||||
return doo;
|
||||
}
|
||||
|
||||
assertEquals("bar42foofishhorse", s.apply("bar", arr));
|
||||
|
||||
function al() {
|
||||
assertEquals(345, this);
|
||||
return arguments.length + arguments[arguments.length - 1];
|
||||
}
|
||||
|
||||
for (var j = 1; j < 0x40000000; j <<= 1) {
|
||||
try {
|
||||
var a = new Array(j);
|
||||
a[j - 1] = 42;
|
||||
assertEquals(42 + j, al.apply(345, a));
|
||||
} catch (e) {
|
||||
assertTrue(e.toString().indexOf("Function.prototype.apply") != -1);
|
||||
for (; j < 0x40000000; j <<= 1) {
|
||||
var caught = false;
|
||||
try {
|
||||
a = new Array(j);
|
||||
a[j - 1] = 42;
|
||||
al.apply(345, a);
|
||||
assertEquals("Shouldn't get", "here");
|
||||
} catch (e) {
|
||||
assertTrue(e.toString().indexOf("Function.prototype.apply") != -1);
|
||||
caught = true;
|
||||
}
|
||||
assertTrue(caught);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var primes = new Array(0);
|
||||
|
||||
function isPrime(possible_prime) {
|
||||
for (var d = 0; d < primes.length; d++) {
|
||||
var p = primes[d];
|
||||
if (possible_prime % p == 0)
|
||||
return false;
|
||||
if (p * p > possible_prime)
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 2; i < 10000; i++) {
|
||||
if (isPrime(i)) {
|
||||
primes.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals(1229, primes.length);
|
||||
|
||||
var same_primes = Array.prototype.constructor.apply(Array, primes);
|
||||
|
||||
for (var i = 0; i < primes.length; i++)
|
||||
assertEquals(primes[i], same_primes[i]);
|
||||
assertEquals(primes.length, same_primes.length);
|
||||
|
||||
|
||||
Array.prototype["1"] = "sep";
|
||||
|
||||
var holey = new Array(3);
|
||||
holey[0] = "mor";
|
||||
holey[2] = "er";
|
||||
|
||||
assertEquals("morseper", String.prototype.concat.apply("", holey));
|
||||
assertEquals("morseper", String.prototype.concat.apply("", holey, 1));
|
||||
assertEquals("morseper", String.prototype.concat.apply("", holey, 1, 2));
|
||||
assertEquals("morseper", String.prototype.concat.apply("", holey, 1, 2, 3));
|
||||
assertEquals("morseper", String.prototype.concat.apply("", holey, 1, 2, 3, 4));
|
||||
|
||||
primes[0] = "";
|
||||
primes[1] = holey;
|
||||
assertThrows("String.prototype.concat.apply.apply('foo', primes)");
|
||||
assertEquals("morseper", String.prototype.concat.apply.apply(String.prototype.concat, primes));
|
||||
|
||||
delete(Array.prototype["1"]);
|
41
test/mjsunit/arguments-call-apply.js
Normal file
41
test/mjsunit/arguments-call-apply.js
Normal file
@ -0,0 +1,41 @@
|
||||
// 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.
|
||||
|
||||
function sum(a, b, c) {
|
||||
var result = 0;
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
result += arguments[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Try invoking call before sum has been compiled lazily.
|
||||
assertEquals(6, sum.call(this, 1, 2, 3), "lazy call");
|
||||
|
||||
assertEquals(6, sum(1, 2, 3), "normal");
|
||||
assertEquals(6, sum.call(this, 1, 2, 3), "call");
|
||||
assertEquals(6, sum.apply(this, [1, 2, 3]), "apply");
|
52
test/mjsunit/arguments-enum.js
Normal file
52
test/mjsunit/arguments-enum.js
Normal file
@ -0,0 +1,52 @@
|
||||
// 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.
|
||||
|
||||
function countArguments() {
|
||||
var count = 0;
|
||||
for (var prop in arguments)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
function setArgumentCount() {
|
||||
arguments[10] = 5;
|
||||
arguments.x = 4;
|
||||
var count = 0;
|
||||
for (var prop in arguments)
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
assertEquals(0, countArguments());
|
||||
assertEquals(0, countArguments(1));
|
||||
assertEquals(0, countArguments(1, 2));
|
||||
assertEquals(0, countArguments(1, 2, 3, 4, 5));
|
||||
|
||||
assertEquals(0, setArgumentCount());
|
||||
assertEquals(0, setArgumentCount(1));
|
||||
assertEquals(0, setArgumentCount(1, 2));
|
||||
assertEquals(0, setArgumentCount(1, 2, 3, 4, 5));
|
47
test/mjsunit/arguments-indirect.js
Normal file
47
test/mjsunit/arguments-indirect.js
Normal file
@ -0,0 +1,47 @@
|
||||
// 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.
|
||||
|
||||
function f1() {
|
||||
g(f1);
|
||||
}
|
||||
|
||||
function f2(x) {
|
||||
var a = arguments;
|
||||
x++;
|
||||
g(f2);
|
||||
}
|
||||
|
||||
|
||||
function g(f) {
|
||||
assertEquals(3, f.arguments.length);
|
||||
assertEquals(1, f.arguments[0]);
|
||||
assertEquals(2, f.arguments[1]);
|
||||
assertEquals(3, f.arguments[2]);
|
||||
}
|
||||
|
||||
f1(1,2,3);
|
||||
f2(0,2,3);
|
130
test/mjsunit/arguments-opt.js
Normal file
130
test/mjsunit/arguments-opt.js
Normal file
@ -0,0 +1,130 @@
|
||||
// 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.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
function L0() {
|
||||
return %_ArgumentsLength();
|
||||
}
|
||||
|
||||
function L1(a) {
|
||||
return %_ArgumentsLength();
|
||||
}
|
||||
|
||||
function L5(a,b,c,d,e) {
|
||||
return %_ArgumentsLength();
|
||||
}
|
||||
|
||||
|
||||
assertEquals(0, L0());
|
||||
assertEquals(1, L0(1));
|
||||
assertEquals(2, L0(1,2));
|
||||
assertEquals(5, L0(1,2,3,4,5));
|
||||
|
||||
assertEquals(0, L1());
|
||||
assertEquals(1, L1(1));
|
||||
assertEquals(2, L1(1,2));
|
||||
assertEquals(5, L1(1,2,3,4,5));
|
||||
|
||||
assertEquals(0, L5());
|
||||
assertEquals(1, L5(1));
|
||||
assertEquals(2, L5(1,2));
|
||||
assertEquals(5, L5(1,2,3,4,5));
|
||||
|
||||
|
||||
function A(key) {
|
||||
return %_Arguments(key);
|
||||
}
|
||||
|
||||
// Integer access.
|
||||
assertEquals(0, A(0));
|
||||
assertEquals(0, A(0,1));
|
||||
assertEquals(2, A(1,2));
|
||||
assertEquals(2, A(1,2,3,4,5));
|
||||
assertEquals(5, A(4,2,3,4,5));
|
||||
assertTrue(typeof A(1) == 'undefined');
|
||||
assertTrue(typeof A(3,2,1) == 'undefined');
|
||||
|
||||
// Out-of-bounds integer access with and without argument
|
||||
// adaptor frames.
|
||||
assertTrue(typeof(A(-10000)) == 'undefined');
|
||||
assertTrue(typeof(A(-10000, 0)) == 'undefined');
|
||||
assertTrue(typeof(A(-1)) == 'undefined');
|
||||
assertTrue(typeof(A(-1, 0)) == 'undefined');
|
||||
assertTrue(typeof(A(10000)) == 'undefined');
|
||||
assertTrue(typeof(A(10000, 0)) == 'undefined');
|
||||
|
||||
// String access.
|
||||
assertEquals(0, A('0'));
|
||||
assertEquals(0, A('0',1));
|
||||
assertEquals(2, A('1',2));
|
||||
assertEquals(2, A('1',2,3,4,5));
|
||||
assertEquals(5, A('4',2,3,4,5));
|
||||
assertTrue(typeof A('1') == 'undefined');
|
||||
assertTrue(typeof A('3',2,1) == 'undefined');
|
||||
assertEquals(A, A('callee'));
|
||||
assertEquals(1, A('length'));
|
||||
assertEquals(2, A('length',2));
|
||||
assertEquals(5, A('length',2,3,4,5));
|
||||
assertEquals({}.toString, A('toString'));
|
||||
assertEquals({}.isPrototypeOf, A('isPrototypeOf'));
|
||||
assertTrue(typeof A('xxx') == 'undefined');
|
||||
|
||||
// Object access.
|
||||
function O(key) {
|
||||
return { toString: function() { return key; } };
|
||||
}
|
||||
|
||||
assertEquals(0, A(O(0)));
|
||||
assertEquals(0, A(O(0),1));
|
||||
assertEquals(2, A(O(1),2));
|
||||
assertEquals(2, A(O(1),2,3,4,5));
|
||||
assertEquals(5, A(O(4),2,3,4,5));
|
||||
assertTrue(typeof A(O(1)) == 'undefined');
|
||||
assertTrue(typeof A(O(3),2,1) == 'undefined');
|
||||
|
||||
assertEquals(0, A(O('0')));
|
||||
assertEquals(0, A(O('0'),1));
|
||||
assertEquals(2, A(O('1'),2));
|
||||
assertEquals(2, A(O('1'),2,3,4,5));
|
||||
assertEquals(5, A(O('4'),2,3,4,5));
|
||||
assertTrue(typeof A(O('1')) == 'undefined');
|
||||
assertTrue(typeof A(O('3'),2,1) == 'undefined');
|
||||
assertEquals(A, A(O('callee')));
|
||||
assertEquals(1, A(O('length')));
|
||||
assertEquals(2, A(O('length'),2));
|
||||
assertEquals(5, A(O('length'),2,3,4,5));
|
||||
assertEquals({}.toString, A(O('toString')));
|
||||
assertEquals({}.isPrototypeOf, A(O('isPrototypeOf')));
|
||||
assertTrue(typeof A(O('xxx')) == 'undefined');
|
||||
|
||||
// Make sure that out-of-bounds access do lookups in the
|
||||
// prototype chain.
|
||||
Object.prototype[5] = 42;
|
||||
assertEquals(42, A(5));
|
||||
Object.prototype[-5] = 87;
|
||||
assertEquals(87, A(-5));
|
97
test/mjsunit/arguments.js
Normal file
97
test/mjsunit/arguments.js
Normal file
@ -0,0 +1,97 @@
|
||||
// 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.
|
||||
|
||||
function argc0() {
|
||||
return arguments.length;
|
||||
}
|
||||
|
||||
function argc1(i) {
|
||||
return arguments.length;
|
||||
}
|
||||
|
||||
function argc2(i, j) {
|
||||
return arguments.length;
|
||||
}
|
||||
|
||||
assertEquals(0, argc0());
|
||||
assertEquals(1, argc0(1));
|
||||
assertEquals(2, argc0(1, 2));
|
||||
assertEquals(3, argc0(1, 2, 3));
|
||||
assertEquals(0, argc1());
|
||||
assertEquals(1, argc1(1));
|
||||
assertEquals(2, argc1(1, 2));
|
||||
assertEquals(3, argc1(1, 2, 3));
|
||||
assertEquals(0, argc2());
|
||||
assertEquals(1, argc2(1));
|
||||
assertEquals(2, argc2(1, 2));
|
||||
assertEquals(3, argc2(1, 2, 3));
|
||||
|
||||
|
||||
|
||||
var index;
|
||||
|
||||
function argv0() {
|
||||
return arguments[index];
|
||||
}
|
||||
|
||||
function argv1(i) {
|
||||
return arguments[index];
|
||||
}
|
||||
|
||||
function argv2(i, j) {
|
||||
return arguments[index];
|
||||
}
|
||||
|
||||
index = 0;
|
||||
assertEquals(7, argv0(7));
|
||||
assertEquals(7, argv0(7, 8));
|
||||
assertEquals(7, argv0(7, 8, 9));
|
||||
assertEquals(7, argv1(7));
|
||||
assertEquals(7, argv1(7, 8));
|
||||
assertEquals(7, argv1(7, 8, 9));
|
||||
assertEquals(7, argv2(7));
|
||||
assertEquals(7, argv2(7, 8));
|
||||
assertEquals(7, argv2(7, 8, 9));
|
||||
|
||||
index = 1;
|
||||
assertEquals(8, argv0(7, 8));
|
||||
assertEquals(8, argv0(7, 8));
|
||||
assertEquals(8, argv1(7, 8, 9));
|
||||
assertEquals(8, argv1(7, 8, 9));
|
||||
assertEquals(8, argv2(7, 8, 9));
|
||||
assertEquals(8, argv2(7, 8, 9));
|
||||
|
||||
index = 2;
|
||||
assertEquals(9, argv0(7, 8, 9));
|
||||
assertEquals(9, argv1(7, 8, 9));
|
||||
assertEquals(9, argv2(7, 8, 9));
|
||||
|
||||
|
||||
// Test that calling a lazily compiled function with
|
||||
// an unexpected number of arguments works.
|
||||
function f(a) { return arguments.length; };
|
||||
assertEquals(3, f(1, 2, 3));
|
101
test/mjsunit/array-concat.js
Normal file
101
test/mjsunit/array-concat.js
Normal file
@ -0,0 +1,101 @@
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @fileoverview Test concat on small and large arrays
|
||||
*/
|
||||
|
||||
var poses = [140, 4000000000];
|
||||
while (pos = poses.shift()) {
|
||||
var a = new Array(pos);
|
||||
assertEquals(pos, a.length);
|
||||
a.push('foo');
|
||||
assertEquals(pos + 1, a.length);
|
||||
var b = ['bar'];
|
||||
var c = a.concat(b);
|
||||
assertEquals(pos + 2, c.length);
|
||||
assertEquals("undefined", typeof(c[pos - 1]));
|
||||
assertEquals("foo", c[pos]);
|
||||
assertEquals("bar", c[pos + 1]);
|
||||
|
||||
// Can we fool the system by putting a number in a string?
|
||||
var onetwofour = "124";
|
||||
a[onetwofour] = 'doo';
|
||||
assertEquals(a[124], 'doo');
|
||||
c = a.concat(b);
|
||||
assertEquals(c[124], 'doo');
|
||||
|
||||
// If we put a number in the prototype, then the spec says it should be
|
||||
// copied on concat.
|
||||
Array.prototype["123"] = 'baz';
|
||||
assertEquals(a[123], 'baz');
|
||||
|
||||
c = a.concat(b);
|
||||
assertEquals(pos + 2, c.length);
|
||||
assertEquals("baz", c[123]);
|
||||
assertEquals("undefined", typeof(c[pos - 1]));
|
||||
assertEquals("foo", c[pos]);
|
||||
assertEquals("bar", c[pos + 1]);
|
||||
|
||||
// When we take the number off the prototype it disappears from a, but
|
||||
// the concat put it in c itself.
|
||||
Array.prototype["123"] = undefined;
|
||||
assertEquals("undefined", typeof(a[123]));
|
||||
assertEquals("baz", c[123]);
|
||||
|
||||
// Non-numeric properties on the prototype or the array shouldn't get
|
||||
// copied.
|
||||
Array.prototype.moe = 'joe';
|
||||
a.ben = 'jerry';
|
||||
assertEquals(a["moe"], 'joe');
|
||||
assertEquals(a["ben"], 'jerry');
|
||||
c = a.concat(b);
|
||||
// ben was not copied
|
||||
assertEquals("undefined", typeof(c.ben));
|
||||
// moe was not copied, but we can see it through the prototype
|
||||
assertEquals("joe", c.moe);
|
||||
|
||||
// When we take moe off the prototype it disappears from all arrays.
|
||||
Array.prototype.moe = undefined;
|
||||
assertEquals("undefined", typeof(c.moe));
|
||||
|
||||
// Negative indeces don't get concated.
|
||||
a[-1] = 'minus1';
|
||||
assertEquals("minus1", a[-1]);
|
||||
assertEquals("undefined", typeof(a[0xffffffff]));
|
||||
c = a.concat(b);
|
||||
assertEquals("undefined", typeof(c[-1]));
|
||||
assertEquals("undefined", typeof(c[0xffffffff]));
|
||||
assertEquals(c.length, a.length + 1);
|
||||
|
||||
}
|
||||
|
||||
a = [];
|
||||
c = a.concat('Hello');
|
||||
assertEquals(1, c.length);
|
||||
assertEquals("Hello", c[0]);
|
||||
assertEquals("Hello", c.toString());
|
159
test/mjsunit/array-functions-prototype.js
Normal file
159
test/mjsunit/array-functions-prototype.js
Normal file
@ -0,0 +1,159 @@
|
||||
// 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.
|
||||
|
||||
// This file contains a number of tests of array functions and their
|
||||
// interaction with properties in the prototype chain.
|
||||
//
|
||||
// The behavior of SpiderMonkey is slightly different for arrays (see
|
||||
// below). Our behavior is consistent and matches the bahavior of
|
||||
// KJS.
|
||||
|
||||
var proto = { length:3, 0:'zero', 1:'one', 2:'two' }
|
||||
function constructor() {};
|
||||
constructor.prototype = proto;
|
||||
|
||||
// Set elements on the array prototype.
|
||||
Array.prototype[0] = 'zero';
|
||||
Array.prototype[1] = 'one';
|
||||
Array.prototype[2] = 'two';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Helper functions.
|
||||
// ----------------------------------------------------------------------
|
||||
function assertHasOwnProperties(object, limit) {
|
||||
for (var i = 0; i < limit; i++) {
|
||||
assertTrue(object.hasOwnProperty(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// shift.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
function runTest() {
|
||||
var nonArray = new constructor();
|
||||
var array = ['zero', , 'two'];
|
||||
// Shift away the zero.
|
||||
assertEquals('zero', array.shift());
|
||||
assertEquals('zero', Array.prototype.shift.call(nonArray));
|
||||
// Check that the local object has properties 0 and 1 with the right
|
||||
// values.
|
||||
assertEquals(2, array.length);
|
||||
assertEquals(2, nonArray.length);
|
||||
assertHasOwnProperties(array, 2);
|
||||
assertHasOwnProperties(nonArray, 2);
|
||||
// Note: Spidermonkey is inconsistent here. It treats arrays
|
||||
// differently from non-arrays. It only consults the prototype for
|
||||
// non-arrays. Therefore, array[0] is undefined in Spidermonkey and
|
||||
// 'one' in V8 and KJS.
|
||||
assertEquals('one', array[0]);
|
||||
assertEquals('one', nonArray[0]);
|
||||
assertEquals('two', array[1]);
|
||||
assertEquals('two', nonArray[1]);
|
||||
// Get index 2 from the prototype.
|
||||
assertEquals('two', array[2]);
|
||||
assertEquals('two', nonArray[2]);
|
||||
}
|
||||
|
||||
runTest();
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// unshift.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
runTest = function() {
|
||||
var nonArray = new constructor();
|
||||
var array = ['zero', , 'two'];
|
||||
// Unshift a new 'zero'.
|
||||
assertEquals(4, array.unshift('zero'));
|
||||
assertEquals(4, Array.prototype.unshift.call(nonArray, 'zero'));
|
||||
// Check that the local object has properties 0 through 3 with the
|
||||
// right values.
|
||||
assertEquals(4, array.length);
|
||||
assertEquals(4, nonArray.length);
|
||||
assertHasOwnProperties(array, 4);
|
||||
assertHasOwnProperties(nonArray, 4);
|
||||
assertEquals('zero', array[0]);
|
||||
assertEquals('zero', nonArray[0]);
|
||||
assertEquals('zero', array[1]);
|
||||
assertEquals('zero', nonArray[1]);
|
||||
// Again Spidermonkey is inconsistent. array[2] is undefined
|
||||
// instead of 'one'.
|
||||
assertEquals('one', array[2]);
|
||||
assertEquals('one', nonArray[2]);
|
||||
assertEquals('two', array[3]);
|
||||
assertEquals('two', nonArray[3]);
|
||||
}
|
||||
|
||||
runTest();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// splice
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
runTest = function() {
|
||||
var nonArray = new constructor();
|
||||
var array = ['zero', , 'two'];
|
||||
// Delete the first element by splicing in nothing.
|
||||
assertArrayEquals(['zero'], array.splice(0, 1));
|
||||
assertArrayEquals(['zero'], Array.prototype.splice.call(nonArray, 0, 1));
|
||||
// Check that the local object has properties 0 and 1 with the right
|
||||
// values.
|
||||
assertEquals(2, array.length);
|
||||
assertEquals(2, nonArray.length);
|
||||
assertHasOwnProperties(array, 2);
|
||||
assertHasOwnProperties(nonArray, 2);
|
||||
// Again Spidermonkey is inconsistent. array[0] is undefined
|
||||
// instead of 'one'.
|
||||
assertEquals('one', array[0]);
|
||||
assertEquals('one', nonArray[0]);
|
||||
assertEquals('two', array[1]);
|
||||
assertEquals('two', nonArray[1]);
|
||||
// Get index 2 from the prototype.
|
||||
assertEquals('two', array[2]);
|
||||
assertEquals('two', nonArray[2]);
|
||||
};
|
||||
|
||||
runTest();
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// slice
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
runTest = function() {
|
||||
var nonArray = new constructor();
|
||||
var array = ['zero', , 'two'];
|
||||
// Again Spidermonkey is inconsistent. (array.slice(0, 3))[1] is
|
||||
// undefined instead of 'one'.
|
||||
assertArrayEquals(['zero', 'one', 'two'], array.slice(0, 3));
|
||||
assertArrayEquals(['zero', 'one', 'two'], Array.prototype.slice.call(nonArray, 0, 3));
|
||||
};
|
||||
|
||||
runTest();
|
66
test/mjsunit/array-indexing.js
Normal file
66
test/mjsunit/array-indexing.js
Normal file
@ -0,0 +1,66 @@
|
||||
// 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.
|
||||
|
||||
var array = [1,2,3,1,2,3,1,2,3,1,2,3];
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Array.prototype.indexOf.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Negative cases.
|
||||
assertEquals([].indexOf(1), -1);
|
||||
assertEquals(array.indexOf(4), -1);
|
||||
assertEquals(array.indexOf(3, array.length), -1);
|
||||
|
||||
assertEquals(array.indexOf(3), 2);
|
||||
// Negative index out of range.
|
||||
assertEquals(array.indexOf(1, -17), 0);
|
||||
// Negative index in rage.
|
||||
assertEquals(array.indexOf(1, -11), 3);
|
||||
// Index in range.
|
||||
assertEquals(array.indexOf(1, 1), 3);
|
||||
assertEquals(array.indexOf(1, 3), 3);
|
||||
assertEquals(array.indexOf(1, 4), 6);
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Array.prototype.lastIndexOf.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
// Negative cases.
|
||||
assertEquals([].lastIndexOf(1), -1);
|
||||
assertEquals(array.lastIndexOf(1, -17), -1);
|
||||
|
||||
assertEquals(array.lastIndexOf(1), 9);
|
||||
// Index out of range.
|
||||
assertEquals(array.lastIndexOf(1, array.length), 9);
|
||||
// Index in range.
|
||||
assertEquals(array.lastIndexOf(1, 2), 0);
|
||||
assertEquals(array.lastIndexOf(1, 4), 3);
|
||||
assertEquals(array.lastIndexOf(1, 3), 3);
|
||||
// Negative index in range.
|
||||
assertEquals(array.lastIndexOf(1, -11), 0);
|
||||
|
228
test/mjsunit/array-iteration.js
Normal file
228
test/mjsunit/array-iteration.js
Normal file
@ -0,0 +1,228 @@
|
||||
// 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.
|
||||
|
||||
// Tests for non-standard array iteration functions.
|
||||
//
|
||||
// See
|
||||
//
|
||||
// <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array>
|
||||
//
|
||||
// for an explanation of each of the functions.
|
||||
|
||||
//
|
||||
// Array.prototype.filter
|
||||
//
|
||||
(function() {
|
||||
// Simple use.
|
||||
var a = [0,1];
|
||||
assertArrayEquals([0], a.filter(function(n) { return n == 0; }));
|
||||
assertArrayEquals(a, a);
|
||||
|
||||
// Use specified object as this object when calling the function.
|
||||
var o = { value: 42 }
|
||||
a = [1,42,3,42,4];
|
||||
assertArrayEquals([42,42], a.filter(function(n) { return this.value == n }, o))
|
||||
|
||||
// Modify original array.
|
||||
a = [1,42,3,42,4];
|
||||
assertArrayEquals([42,42], a.filter(function(n, index, array) { array[index] = 43; return 42 == n; }));
|
||||
assertArrayEquals([43,43,43,43,43], a);
|
||||
|
||||
// Only loop through initial part of array eventhough elements are
|
||||
// added.
|
||||
a = [1,1];
|
||||
assertArrayEquals([], a.filter(function(n, index, array) { array.push(n+1); return n == 2; }));
|
||||
assertArrayEquals([1,1,2,2], a);
|
||||
|
||||
// Respect holes.
|
||||
a = new Array(20);
|
||||
var count = 0;
|
||||
a[2] = 2;
|
||||
a[15] = 2;
|
||||
a[17] = 4;
|
||||
var a = a.filter(function(n) { count++; return n == 2; });
|
||||
assertEquals(3, count);
|
||||
for (var i in a) assertEquals(2, a[i]);
|
||||
|
||||
})();
|
||||
|
||||
|
||||
//
|
||||
// Array.prototype.forEach
|
||||
//
|
||||
(function() {
|
||||
// Simple use.
|
||||
var a = [0,1];
|
||||
var count = 0;
|
||||
a.forEach(function(n) { count++; });
|
||||
assertEquals(2, count);
|
||||
|
||||
// Use specified object as this object when calling the function.
|
||||
var o = { value: 42 }
|
||||
var result = [];
|
||||
a.forEach(function(n) { result.push(this.value); }, o);
|
||||
assertArrayEquals([42,42], result);
|
||||
|
||||
// Modify original array.
|
||||
a = [0,1];
|
||||
count = 0;
|
||||
a.forEach(function(n, index, array) { array[index] = n + 1; count++; });
|
||||
assertEquals(2, count);
|
||||
assertArrayEquals([1,2], a);
|
||||
|
||||
// Only loop through initial part of array eventhough elements are
|
||||
// added.
|
||||
a = [1,1];
|
||||
count = 0;
|
||||
a.forEach(function(n, index, array) { array.push(n+1); count++; });
|
||||
assertEquals(2, count);
|
||||
assertArrayEquals([1,1,2,2], a);
|
||||
|
||||
// Respect holes.
|
||||
a = new Array(20);
|
||||
count = 0;
|
||||
a[15] = 2;
|
||||
a.forEach(function(n) { count++; });
|
||||
assertEquals(1, count);
|
||||
|
||||
})();
|
||||
|
||||
|
||||
//
|
||||
// Array.prototype.every
|
||||
//
|
||||
(function() {
|
||||
// Simple use.
|
||||
var a = [0,1];
|
||||
assertFalse(a.every(function(n) { return n == 0 }));
|
||||
a = [0,0];
|
||||
assertTrue(a.every(function(n) { return n == 0 }));
|
||||
assertTrue([].every(function(n) { return n == 0}));
|
||||
|
||||
// Use specified object as this object when calling the function.
|
||||
var o = { value: 42 }
|
||||
a = [0];
|
||||
assertFalse(a.every(function(n) { return this.value == n; }, o));
|
||||
a = [42];
|
||||
assertTrue(a.every(function(n) { return this.value == n; }, o));
|
||||
|
||||
// Modify original array.
|
||||
a = [0,1];
|
||||
assertFalse(a.every(function(n, index, array) { array[index] = n + 1; return n == 1;}));
|
||||
assertArrayEquals([1,1], a);
|
||||
|
||||
// Only loop through initial part of array eventhough elements are
|
||||
// added.
|
||||
a = [1,1];
|
||||
assertTrue(a.every(function(n, index, array) { array.push(n + 1); return n == 1;}));
|
||||
assertArrayEquals([1,1,2,2], a);
|
||||
|
||||
// Respect holes.
|
||||
a = new Array(20);
|
||||
var count = 0;
|
||||
a[2] = 2;
|
||||
a[15] = 2;
|
||||
assertTrue(a.every(function(n) { count++; return n == 2; }));
|
||||
assertEquals(2, count);
|
||||
|
||||
})();
|
||||
|
||||
//
|
||||
// Array.prototype.map
|
||||
//
|
||||
(function() {
|
||||
var a = [0,1,2,3,4];
|
||||
|
||||
// Simple use.
|
||||
var result = [1,2,3,4,5];
|
||||
assertArrayEquals(result, a.map(function(n) { return n + 1; }));
|
||||
assertEquals(a, a);
|
||||
|
||||
// Use specified object as this object when calling the function.
|
||||
var o = { delta: 42 }
|
||||
result = [42,43,44,45,46];
|
||||
assertArrayEquals(result, a.map(function(n) { return this.delta + n; }, o));
|
||||
|
||||
// Modify original array.
|
||||
a = [0,1,2,3,4];
|
||||
result = [1,2,3,4,5];
|
||||
assertArrayEquals(result, a.map(function(n, index, array) { array[index] = n + 1; return n + 1;}));
|
||||
assertArrayEquals(result, a);
|
||||
|
||||
// Only loop through initial part of array eventhough elements are
|
||||
// added.
|
||||
a = [0,1,2,3,4];
|
||||
result = [1,2,3,4,5];
|
||||
assertArrayEquals(result, a.map(function(n, index, array) { array.push(n); return n + 1;}));
|
||||
assertArrayEquals([0,1,2,3,4,0,1,2,3,4], a);
|
||||
|
||||
// Respect holes.
|
||||
a = new Array(20);
|
||||
a[15] = 2;
|
||||
a = a.map(function(n) { return 2*n; });
|
||||
for (var i in a) assertEquals(4, a[i]);
|
||||
|
||||
})();
|
||||
|
||||
//
|
||||
// Array.prototype.some
|
||||
//
|
||||
(function() {
|
||||
var a = [0,1,2,3,4];
|
||||
|
||||
// Simple use.
|
||||
assertTrue(a.some(function(n) { return n == 3}));
|
||||
assertFalse(a.some(function(n) { return n == 5}));
|
||||
|
||||
// Use specified object as this object when calling the function.
|
||||
var o = { element: 42 };
|
||||
a = [1,42,3];
|
||||
assertTrue(a.some(function(n) { return this.element == n; }, o));
|
||||
a = [1];
|
||||
assertFalse(a.some(function(n) { return this.element == n; }, o));
|
||||
|
||||
// Modify original array.
|
||||
a = [0,1,2,3];
|
||||
assertTrue(a.some(function(n, index, array) { array[index] = n + 1; return n == 2; }));
|
||||
assertArrayEquals([1,2,3,3], a);
|
||||
|
||||
// Only loop through initial part when elements are added.
|
||||
a = [0,1,2];
|
||||
assertFalse(a.some(function(n, index, array) { array.push(42); return n == 42; }));
|
||||
assertArrayEquals([0,1,2,42,42,42], a);
|
||||
|
||||
// Respect holes.
|
||||
a = new Array(20);
|
||||
var count = 0;
|
||||
a[2] = 42;
|
||||
a[10] = 2;
|
||||
a[15] = 42;
|
||||
assertTrue(a.some(function(n) { count++; return n == 2; }));
|
||||
assertEquals(2, count);
|
||||
|
||||
})();
|
||||
|
45
test/mjsunit/array-join.js
Normal file
45
test/mjsunit/array-join.js
Normal file
@ -0,0 +1,45 @@
|
||||
// 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.
|
||||
|
||||
// Test that array join calls toString on subarrays.
|
||||
var a = [[1,2],3,4,[5,6]];
|
||||
assertEquals('1,2*3*4*5,6', a.join('*'));
|
||||
|
||||
// Create a cycle.
|
||||
a.push(a);
|
||||
assertEquals('1,2*3*4*5,6*', a.join('*'));
|
||||
|
||||
// Replace array.prototype.toString.
|
||||
Array.prototype.toString = function() { return "array"; }
|
||||
assertEquals('array*3*4*array*array', a.join('*'));
|
||||
|
||||
Array.prototype.toString = function() { throw 42; }
|
||||
assertThrows("a.join('*')");
|
||||
|
||||
Array.prototype.toString = function() { return "array"; }
|
||||
assertEquals('array*3*4*array*array', a.join('*'));
|
||||
|
111
test/mjsunit/array-length.js
Normal file
111
test/mjsunit/array-length.js
Normal file
@ -0,0 +1,111 @@
|
||||
// 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.
|
||||
|
||||
var a = [0,1,2,3];
|
||||
a.length = 0;
|
||||
|
||||
assertEquals('undefined', typeof a[0]);
|
||||
assertEquals('undefined', typeof a[1]);
|
||||
assertEquals('undefined', typeof a[2]);
|
||||
assertEquals('undefined', typeof a[3]);
|
||||
|
||||
|
||||
var a = [0,1,2,3];
|
||||
a.length = 2;
|
||||
|
||||
assertEquals(0, a[0]);
|
||||
assertEquals(1, a[1]);
|
||||
assertEquals('undefined', typeof a[2]);
|
||||
assertEquals('undefined', typeof a[3]);
|
||||
|
||||
|
||||
var a = new Array();
|
||||
a[0] = 0;
|
||||
a[1000] = 1000;
|
||||
a[1000000] = 1000000;
|
||||
a[2000000] = 2000000;
|
||||
|
||||
assertEquals(2000001, a.length);
|
||||
a.length = 0;
|
||||
assertEquals(0, a.length);
|
||||
assertEquals('undefined', typeof a[0]);
|
||||
assertEquals('undefined', typeof a[1000]);
|
||||
assertEquals('undefined', typeof a[1000000]);
|
||||
assertEquals('undefined', typeof a[2000000]);
|
||||
|
||||
|
||||
var a = new Array();
|
||||
a[0] = 0;
|
||||
a[1000] = 1000;
|
||||
a[1000000] = 1000000;
|
||||
a[2000000] = 2000000;
|
||||
|
||||
assertEquals(2000001, a.length);
|
||||
a.length = 2000;
|
||||
assertEquals(2000, a.length);
|
||||
assertEquals(0, a[0]);
|
||||
assertEquals(1000, a[1000]);
|
||||
assertEquals('undefined', typeof a[1000000]);
|
||||
assertEquals('undefined', typeof a[2000000]);
|
||||
|
||||
|
||||
var a = new Array();
|
||||
a[Math.pow(2,31)-1] = 0;
|
||||
a[Math.pow(2,30)-1] = 0;
|
||||
assertEquals(Math.pow(2,31), a.length);
|
||||
|
||||
|
||||
var a = new Array();
|
||||
a[0] = 0;
|
||||
a[1000] = 1000;
|
||||
a[Math.pow(2,30)-1] = Math.pow(2,30)-1;
|
||||
a[Math.pow(2,31)-1] = Math.pow(2,31)-1;
|
||||
a[Math.pow(2,32)-2] = Math.pow(2,32)-2;
|
||||
|
||||
assertEquals(Math.pow(2,30)-1, a[Math.pow(2,30)-1]);
|
||||
assertEquals(Math.pow(2,31)-1, a[Math.pow(2,31)-1]);
|
||||
assertEquals(Math.pow(2,32)-2, a[Math.pow(2,32)-2]);
|
||||
|
||||
assertEquals(Math.pow(2,32)-1, a.length);
|
||||
a.length = Math.pow(2,30)+1; // not a smi!
|
||||
assertEquals(Math.pow(2,30)+1, a.length);
|
||||
|
||||
assertEquals(0, a[0]);
|
||||
assertEquals(1000, a[1000]);
|
||||
assertEquals(Math.pow(2,30)-1, a[Math.pow(2,30)-1]);
|
||||
assertEquals('undefined', typeof a[Math.pow(2,31)-1]);
|
||||
assertEquals('undefined', typeof a[Math.pow(2,32)-2], "top");
|
||||
|
||||
|
||||
var a = new Array();
|
||||
a.length = new Number(12);
|
||||
assertEquals(12, a.length);
|
||||
|
||||
|
||||
var o = { length: -23 };
|
||||
Array.prototype.pop.apply(o);
|
||||
assertEquals(4294967272, o.length);
|
66
test/mjsunit/array-sort.js
Normal file
66
test/mjsunit/array-sort.js
Normal file
@ -0,0 +1,66 @@
|
||||
// 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.
|
||||
|
||||
// Test array sort.
|
||||
|
||||
// Test counter-intuitive default number sorting.
|
||||
function TestNumberSort() {
|
||||
var a = [ 200, 45, 7 ];
|
||||
// Default sort calls toString on each element and orders
|
||||
// lexicographically.
|
||||
a.sort();
|
||||
assertArrayEquals([ 200, 45, 7 ], a);
|
||||
// Sort numbers by value using a compare functions.
|
||||
a.sort(function(x, y) { return x - y; });
|
||||
assertArrayEquals([ 7, 45, 200 ], a);
|
||||
}
|
||||
|
||||
TestNumberSort();
|
||||
|
||||
|
||||
// Test lexicographical string sorting.
|
||||
function TestStringSort() {
|
||||
var a = [ "cc", "c", "aa", "a", "bb", "b", "ab", "ac" ];
|
||||
a.sort();
|
||||
assertArrayEquals([ "a", "aa", "ab", "ac", "b", "bb", "c", "cc" ], a);
|
||||
}
|
||||
|
||||
TestStringSort();
|
||||
|
||||
|
||||
// Test object sorting. Calls toString on each element and sorts
|
||||
// lexicographically.
|
||||
function TestObjectSort() {
|
||||
var obj0 = { toString: function() { return "a"; } };
|
||||
var obj1 = { toString: function() { return "b"; } };
|
||||
var obj2 = { toString: function() { return "c"; } };
|
||||
var a = [ obj2, obj0, obj1 ];
|
||||
a.sort();
|
||||
assertArrayEquals([ obj0, obj1, obj2 ], a);
|
||||
}
|
||||
|
||||
TestObjectSort();
|
60
test/mjsunit/array-splice-webkit.js
Normal file
60
test/mjsunit/array-splice-webkit.js
Normal file
@ -0,0 +1,60 @@
|
||||
// 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.
|
||||
|
||||
// Simple splice tests based on webkit layout tests.
|
||||
var arr = ['a','b','c','d'];
|
||||
assertArrayEquals(['a','b','c','d'], arr);
|
||||
assertArrayEquals(['c','d'], arr.splice(2));
|
||||
assertArrayEquals(['a','b'], arr);
|
||||
assertArrayEquals(['a','b'], arr.splice(0));
|
||||
assertArrayEquals([], arr)
|
||||
|
||||
arr = ['a','b','c','d'];
|
||||
assertEquals(undefined, arr.splice())
|
||||
assertArrayEquals(['a','b','c','d'], arr);
|
||||
assertArrayEquals(['a','b','c','d'], arr.splice(undefined))
|
||||
assertArrayEquals([], arr);
|
||||
|
||||
arr = ['a','b','c','d'];
|
||||
assertArrayEquals(['a','b','c','d'], arr.splice(null))
|
||||
assertArrayEquals([], arr);
|
||||
|
||||
arr = ['a','b','c','d'];
|
||||
assertArrayEquals([], arr.splice(100))
|
||||
assertArrayEquals(['a','b','c','d'], arr);
|
||||
assertArrayEquals(['d'], arr.splice(-1))
|
||||
assertArrayEquals(['a','b','c'], arr);
|
||||
|
||||
assertArrayEquals([], arr.splice(2, undefined))
|
||||
assertArrayEquals([], arr.splice(2, null))
|
||||
assertArrayEquals([], arr.splice(2, -1))
|
||||
assertArrayEquals([], arr.splice(2, 0))
|
||||
assertArrayEquals(['a','b','c'], arr);
|
||||
assertArrayEquals(['c'], arr.splice(2, 100))
|
||||
assertArrayEquals(['a','b'], arr);
|
||||
|
||||
|
313
test/mjsunit/array-splice.js
Normal file
313
test/mjsunit/array-splice.js
Normal file
@ -0,0 +1,313 @@
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @fileoverview Test splice, shift, unshift, slice and join on small
|
||||
* and large arrays. Some of these methods are specified such that they
|
||||
* should work on other objects too, so we test that too.
|
||||
*/
|
||||
|
||||
var LARGE = 40000000;
|
||||
var VERYLARGE = 4000000000;
|
||||
|
||||
// Nicer for firefox 1.5. Unless you uncomment the following two lines,
|
||||
// smjs will appear to hang on this file.
|
||||
//var LARGE = 40000;
|
||||
//var VERYLARGE = 40000;
|
||||
|
||||
var fourhundredth = LARGE/400;
|
||||
|
||||
function PseudoArray() {
|
||||
};
|
||||
|
||||
for (var use_real_arrays = 0; use_real_arrays <= 1; use_real_arrays++) {
|
||||
var poses = [0, 140, 40000, VERYLARGE];
|
||||
var the_prototype;
|
||||
var new_function;
|
||||
var push_function;
|
||||
var concat_function;
|
||||
var slice_function;
|
||||
var splice_function;
|
||||
var splice_function_2;
|
||||
var unshift_function;
|
||||
var unshift_function_2;
|
||||
var shift_function;
|
||||
if (use_real_arrays) {
|
||||
new_function = function(length) {
|
||||
return new Array(length);
|
||||
};
|
||||
the_prototype = Array.prototype;
|
||||
push_function = function(array, elt) {
|
||||
return array.push(elt);
|
||||
};
|
||||
concat_function = function(array, other) {
|
||||
return array.concat(other);
|
||||
};
|
||||
slice_function = function(array, start, len) {
|
||||
return array.slice(start, len);
|
||||
};
|
||||
splice_function = function(array, start, len) {
|
||||
return array.splice(start, len);
|
||||
};
|
||||
splice_function_2 = function(array, start, len, elt) {
|
||||
return array.splice(start, len, elt);
|
||||
};
|
||||
unshift_function = function(array, elt) {
|
||||
return array.unshift(elt);
|
||||
};
|
||||
unshift_function_2 = function(array, elt1, elt2) {
|
||||
return array.unshift(elt1, elt2);
|
||||
};
|
||||
shift_function = function(array) {
|
||||
return array.shift();
|
||||
};
|
||||
} else {
|
||||
// Don't run largest size on non-arrays or we'll be here for ever.
|
||||
poses.pop();
|
||||
new_function = function(length) {
|
||||
var obj = new PseudoArray();
|
||||
obj.length = length;
|
||||
return obj;
|
||||
};
|
||||
the_prototype = PseudoArray.prototype;
|
||||
push_function = function(array, elt) {
|
||||
array[array.length] = elt;
|
||||
array.length++;
|
||||
};
|
||||
concat_function = function(array, other) {
|
||||
return Array.prototype.concat.call(array, other);
|
||||
};
|
||||
slice_function = function(array, start, len) {
|
||||
return Array.prototype.slice.call(array, start, len);
|
||||
};
|
||||
splice_function = function(array, start, len) {
|
||||
return Array.prototype.splice.call(array, start, len);
|
||||
};
|
||||
splice_function_2 = function(array, start, len, elt) {
|
||||
return Array.prototype.splice.call(array, start, len, elt);
|
||||
};
|
||||
unshift_function = function(array, elt) {
|
||||
return Array.prototype.unshift.call(array, elt);
|
||||
};
|
||||
unshift_function_2 = function(array, elt1, elt2) {
|
||||
return Array.prototype.unshift.call(array, elt1, elt2);
|
||||
};
|
||||
shift_function = function(array) {
|
||||
return Array.prototype.shift.call(array);
|
||||
};
|
||||
}
|
||||
|
||||
for (var pos_pos = 0; pos_pos < poses.length; pos_pos++) {
|
||||
var pos = poses[pos_pos];
|
||||
if (pos > 100) {
|
||||
var a = new_function(pos);
|
||||
assertEquals(pos, a.length);
|
||||
push_function(a, 'foo');
|
||||
assertEquals(pos + 1, a.length);
|
||||
var b = ['bar'];
|
||||
// Delete a huge number of holes.
|
||||
var c = splice_function(a, 10, pos - 20);
|
||||
assertEquals(pos - 20, c.length);
|
||||
assertEquals(21, a.length);
|
||||
}
|
||||
|
||||
// Add a numeric property to the prototype of the array class. This
|
||||
// allows us to test some borderline stuff relative to the standard.
|
||||
the_prototype["" + (pos + 1)] = 'baz';
|
||||
|
||||
if (use_real_arrays) {
|
||||
// It seems quite clear from ECMAScript spec 15.4.4.5. Just call Get on
|
||||
// every integer in the range.
|
||||
// IE, Safari get this right.
|
||||
// FF, Opera get this wrong.
|
||||
var a = ['zero', ,'two'];
|
||||
if (pos == 0) {
|
||||
assertEquals("zero,baz,two", a.join(","));
|
||||
}
|
||||
|
||||
// Concat only applies to real arrays, unlike most of the other methods.
|
||||
var a = new_function(pos);
|
||||
push_function(a, "con");
|
||||
assertEquals("con", a[pos]);
|
||||
assertEquals(pos + 1, a.length);
|
||||
var b = new_function(0);
|
||||
push_function(b, "cat");
|
||||
assertEquals("cat", b[0]);
|
||||
var ab = concat_function(a, b);
|
||||
assertEquals("con", ab[pos]);
|
||||
assertEquals(pos + 2, ab.length);
|
||||
assertEquals("cat", ab[pos + 1]);
|
||||
var ba = concat_function(b, a);
|
||||
assertEquals("con", ba[pos + 1]);
|
||||
assertEquals(pos + 2, ba.length);
|
||||
assertEquals("cat", ba[0]);
|
||||
|
||||
// Join with '' as separator.
|
||||
var join = a.join('');
|
||||
assertEquals("con", join);
|
||||
join = b.join('');
|
||||
assertEquals("cat", join);
|
||||
join = ab.join('');
|
||||
assertEquals("concat", join);
|
||||
join = ba.join('');
|
||||
assertEquals("catcon", join);
|
||||
|
||||
var sparse = [];
|
||||
sparse[pos + 1000] = 'is ';
|
||||
sparse[pos + 271828] = 'time ';
|
||||
sparse[pos + 31415] = 'the ';
|
||||
sparse[pos + 012260199] = 'all ';
|
||||
sparse[-1] = 'foo';
|
||||
sparse[pos + 22591927] = 'good ';
|
||||
sparse[pos + 1618033] = 'for ';
|
||||
sparse[pos + 91] = ': Now ';
|
||||
sparse[pos + 86720199] = 'men.';
|
||||
sparse.hest = 'fisk';
|
||||
|
||||
assertEquals("baz: Now is the time for all good men.", sparse.join(''));
|
||||
}
|
||||
|
||||
a = new_function(pos);
|
||||
push_function(a, 'zero');
|
||||
push_function(a, void 0);
|
||||
push_function(a, 'two');
|
||||
|
||||
// Splice works differently from join.
|
||||
// IE, Safari get this wrong.
|
||||
// FF, Opera get this right.
|
||||
// 15.4.4.12 line 24 says the object itself has to have the property...
|
||||
var zero = splice_function(a, pos, 1);
|
||||
assertEquals("undefined", typeof(a[pos]));
|
||||
assertEquals("two", a[pos+1], "pos1:" + pos);
|
||||
assertEquals(pos + 2, a.length, "a length");
|
||||
assertEquals(1, zero.length, "zero length");
|
||||
assertEquals("zero", zero[0]);
|
||||
|
||||
// 15.4.4.12 line 41 says the object itself has to have the property...
|
||||
a = new_function(pos);
|
||||
push_function(a, 'zero');
|
||||
push_function(a, void 0);
|
||||
push_function(a, 'two');
|
||||
var nothing = splice_function_2(a, pos, 0, 'minus1');
|
||||
assertEquals("minus1", a[pos]);
|
||||
assertEquals("zero", a[pos+1]);
|
||||
assertEquals("undefined", typeof(a[pos+2]), "toot!");
|
||||
assertEquals("two", a[pos+3], "pos3");
|
||||
assertEquals(pos + 4, a.length);
|
||||
assertEquals(1, zero.length);
|
||||
assertEquals("zero", zero[0]);
|
||||
|
||||
// 15.4.4.12 line 10 says the object itself has to have the property...
|
||||
a = new_function(pos);
|
||||
push_function(a, 'zero');
|
||||
push_function(a, void 0);
|
||||
push_function(a, 'two');
|
||||
var one = splice_function(a, pos + 1, 1);
|
||||
assertEquals("", one.join(","));
|
||||
assertEquals(pos + 2, a.length);
|
||||
assertEquals("zero", a[pos]);
|
||||
assertEquals("two", a[pos+1]);
|
||||
|
||||
// Set things back to the way they were.
|
||||
the_prototype[pos + 1] = undefined;
|
||||
|
||||
// Unshift.
|
||||
var a = new_function(pos);
|
||||
push_function(a, "foo");
|
||||
assertEquals("foo", a[pos]);
|
||||
assertEquals(pos + 1, a.length);
|
||||
unshift_function(a, "bar");
|
||||
assertEquals("foo", a[pos+1]);
|
||||
assertEquals(pos + 2, a.length);
|
||||
assertEquals("bar", a[0]);
|
||||
unshift_function_2(a, "baz", "boo");
|
||||
assertEquals("foo", a[pos+3]);
|
||||
assertEquals(pos + 4, a.length);
|
||||
assertEquals("baz", a[0]);
|
||||
assertEquals("boo", a[1]);
|
||||
assertEquals("bar", a[2]);
|
||||
|
||||
// Shift.
|
||||
var baz = shift_function(a);
|
||||
assertEquals("baz", baz);
|
||||
assertEquals("boo", a[0]);
|
||||
assertEquals(pos + 3, a.length);
|
||||
assertEquals("foo", a[pos + 2]);
|
||||
|
||||
// Slice.
|
||||
var bar = slice_function(a, 1, 0); // don't throw an exception please.
|
||||
bar = slice_function(a, 1, 2);
|
||||
assertEquals("bar", bar[0]);
|
||||
assertEquals(1, bar.length);
|
||||
assertEquals("bar", a[1]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Lets see if performance is reasonable.
|
||||
|
||||
var a = new Array(LARGE + 10);
|
||||
for (var i = 0; i < a.length; i += 1000) {
|
||||
a[i] = i;
|
||||
}
|
||||
|
||||
// Take something near the end of the array.
|
||||
for (var i = 0; i < 100; i++) {
|
||||
var top = a.splice(LARGE, 5);
|
||||
assertEquals(5, top.length);
|
||||
assertEquals(LARGE, top[0]);
|
||||
assertEquals("undefined", typeof(top[1]));
|
||||
assertEquals(LARGE + 5, a.length);
|
||||
a.splice(LARGE, 0, LARGE);
|
||||
a.length = LARGE + 10;
|
||||
}
|
||||
|
||||
var a = new Array(LARGE + 10);
|
||||
for (var i = 0; i < a.length; i += fourhundredth) {
|
||||
a[i] = i;
|
||||
}
|
||||
|
||||
// Take something near the middle of the array.
|
||||
for (var i = 0; i < 10; i++) {
|
||||
var top = a.splice(LARGE >> 1, 5);
|
||||
assertEquals(5, top.length);
|
||||
assertEquals(LARGE >> 1, top[0]);
|
||||
assertEquals("undefined", typeof(top[1]));
|
||||
assertEquals(LARGE + 5, a.length);
|
||||
a.splice(LARGE >> 1, 0, LARGE >> 1, void 0, void 0, void 0, void 0);
|
||||
}
|
||||
|
||||
|
||||
// Test http://b/issue?id=1202711
|
||||
arr = [0];
|
||||
arr.length = 2;
|
||||
Array.prototype[1] = 1;
|
||||
assertEquals(1, arr.pop());
|
||||
assertEquals(0, arr.pop());
|
||||
Array.prototype[1] = undefined;
|
||||
|
||||
|
53
test/mjsunit/array_length.js
Normal file
53
test/mjsunit/array_length.js
Normal file
@ -0,0 +1,53 @@
|
||||
// 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.
|
||||
|
||||
// A reduced test case from Acid3 test 95.
|
||||
// When an object is assigned to an array length field,
|
||||
// it is converted to a number.
|
||||
|
||||
function CheckSetArrayLength(x, expected) {
|
||||
var a = [];
|
||||
a.length = x;
|
||||
|
||||
assertEquals("number", typeof a.length);
|
||||
assertEquals(expected, a.length);
|
||||
}
|
||||
|
||||
CheckSetArrayLength(2147483648, 2147483648);
|
||||
CheckSetArrayLength("2147483648", 2147483648);
|
||||
CheckSetArrayLength(null, 0);
|
||||
CheckSetArrayLength(false, 0);
|
||||
CheckSetArrayLength(true, 1);
|
||||
CheckSetArrayLength({valueOf : function() { return 42; }}, 42);
|
||||
CheckSetArrayLength({toString : function() { return '42'; }}, 42);
|
||||
|
||||
// Test invalid values
|
||||
assertThrows("var y = []; y.length = 'abc';");
|
||||
assertThrows("var y = []; y.length = undefined;");
|
||||
assertThrows("var y = []; y.length = {};");
|
||||
assertThrows("var y = []; y.length = -1;");
|
||||
assertThrows("var y = []; y.length = {valueOf:function() { throw new Error(); }};");
|
45
test/mjsunit/ascii-regexp-subject.js
Normal file
45
test/mjsunit/ascii-regexp-subject.js
Normal file
@ -0,0 +1,45 @@
|
||||
// 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.
|
||||
|
||||
/**
|
||||
* @fileoverview Check that an initial ^ will result in a faster match fail.
|
||||
*/
|
||||
|
||||
|
||||
var s = "foo";
|
||||
var i;
|
||||
|
||||
for (i = 0; i < 18; i++) {
|
||||
s = s + s;
|
||||
}
|
||||
|
||||
var re = /^bar/;
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
re.test(s);
|
||||
re = new RegExp("^bar");
|
||||
}
|
36
test/mjsunit/binary-operation-overwrite.js
Normal file
36
test/mjsunit/binary-operation-overwrite.js
Normal file
@ -0,0 +1,36 @@
|
||||
// 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.
|
||||
|
||||
// Ensure that literals are not overwritten.
|
||||
function f1() { return (1.2, 3.4) + 5.6; }
|
||||
function f2() { return (1, 2) + 3; }
|
||||
function f3() { return (1.2 || 3.4) + 5.6; }
|
||||
function f4() { return (1 || 2) + 3; }
|
||||
assertTrue(f1() === f1());
|
||||
assertTrue(f2() === f2());
|
||||
assertTrue(f3() === f3());
|
||||
assertTrue(f4() === f4());
|
39
test/mjsunit/body-not-visible.js
Normal file
39
test/mjsunit/body-not-visible.js
Normal file
@ -0,0 +1,39 @@
|
||||
// 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 we cannot see the local variables in NewFunction when
|
||||
// compiling functions using new Function().
|
||||
|
||||
var caught = false;
|
||||
try {
|
||||
(new Function("return body;"))();
|
||||
assertTrue(false);
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
assertTrue(e instanceof ReferenceError);
|
||||
}
|
||||
assertTrue(caught);
|
38
test/mjsunit/call-non-function-call.js
Normal file
38
test/mjsunit/call-non-function-call.js
Normal file
@ -0,0 +1,38 @@
|
||||
// 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.
|
||||
|
||||
// Throw exception when invoking Function.prototype.call with a
|
||||
// non-function receiver.
|
||||
var caught = false;
|
||||
try {
|
||||
Function.prototype.call.call({});
|
||||
assertTrue(false);
|
||||
} catch (e) {
|
||||
caught = true;
|
||||
assertTrue(e instanceof TypeError);
|
||||
}
|
||||
assertTrue(caught);
|
54
test/mjsunit/call-non-function.js
Normal file
54
test/mjsunit/call-non-function.js
Normal file
@ -0,0 +1,54 @@
|
||||
// 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.
|
||||
|
||||
function TryCall(x) {
|
||||
var caught = [];
|
||||
try {
|
||||
x();
|
||||
} catch (e) {
|
||||
caught.push(e);
|
||||
}
|
||||
|
||||
try {
|
||||
new x();
|
||||
} catch (e) {
|
||||
caught.push(e);
|
||||
}
|
||||
|
||||
assertTrue(caught[0] instanceof TypeError);
|
||||
assertTrue(caught[1] instanceof TypeError);
|
||||
};
|
||||
|
||||
|
||||
TryCall(this);
|
||||
TryCall(Math);
|
||||
TryCall(true);
|
||||
TryCall(1234);
|
||||
TryCall("hest");
|
||||
|
||||
|
||||
|
87
test/mjsunit/call.js
Normal file
87
test/mjsunit/call.js
Normal file
@ -0,0 +1,87 @@
|
||||
// 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.
|
||||
|
||||
function f0() {
|
||||
return this;
|
||||
}
|
||||
|
||||
assertTrue(this === f0.call(), "1");
|
||||
|
||||
assertTrue(this === f0.call(this), "w");
|
||||
assertTrue(this === f0.call(this, 1), "w");
|
||||
assertTrue(this === f0.call(this, 1, 2), "w");
|
||||
|
||||
assertTrue(this === f0.call(null), "3a");
|
||||
assertTrue(this === f0.call(null, 1), "3b");
|
||||
assertTrue(this === f0.call(null, 1, 2), "3c");
|
||||
|
||||
assertTrue(this === f0.call(void 0), "4a");
|
||||
assertTrue(this === f0.call(void 0, 1), "4b");
|
||||
assertTrue(this === f0.call(void 0, 1, 2), "4c");
|
||||
|
||||
var x = {};
|
||||
assertTrue(x === f0.call(x));
|
||||
assertTrue(x === f0.call(x, 1));
|
||||
assertTrue(x === f0.call(x, 1, 2));
|
||||
|
||||
|
||||
function f1(a) {
|
||||
a = a || 'i';
|
||||
return this[a];
|
||||
}
|
||||
|
||||
assertEquals(1, f1.call({i:1}));
|
||||
assertEquals(42, f1.call({i:42}, 'i'));
|
||||
assertEquals(87, f1.call({j:87}, 'j', 1));
|
||||
assertEquals(99, f1.call({k:99}, 'k', 1, 2));
|
||||
|
||||
|
||||
function f2(a, b) {
|
||||
a = a || 'n';
|
||||
b = b || 2;
|
||||
return this[a] + b;
|
||||
}
|
||||
|
||||
var x = {n: 1};
|
||||
assertEquals(3, f2.call(x));
|
||||
assertEquals(14, f2.call({i:12}, 'i'));
|
||||
assertEquals(42, f2.call(x, 'n', 41));
|
||||
assertEquals(87, f2.call(x, 'n', 86, 1));
|
||||
assertEquals(99, f2.call(x, 'n', 98, 1, 2));
|
||||
|
||||
|
||||
function fn() {
|
||||
return arguments.length;
|
||||
}
|
||||
|
||||
assertEquals(0, fn.call());
|
||||
assertEquals(0, fn.call(this));
|
||||
assertEquals(0, fn.call(null));
|
||||
assertEquals(0, fn.call(void 0));
|
||||
assertEquals(1, fn.call(this, 1));
|
||||
assertEquals(2, fn.call(this, 1, 2));
|
||||
assertEquals(3, fn.call(this, 1, 2, 3));
|
53
test/mjsunit/char-escape.js
Normal file
53
test/mjsunit/char-escape.js
Normal file
@ -0,0 +1,53 @@
|
||||
// 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.
|
||||
|
||||
// Check that character escapes are understood as one char
|
||||
var escapes = ["\b", "\t", "\n", "\v", "\f", "\r", "\"", "\'", "\\", "\x4a", "\u005f"];
|
||||
for (var i = 0; i < escapes.length; i++) {
|
||||
var str = escapes[i];
|
||||
assertEquals(1, str.length);
|
||||
assertEquals(str, str.charAt(0));
|
||||
}
|
||||
|
||||
function code(str) {
|
||||
return str.charCodeAt(0);
|
||||
}
|
||||
|
||||
// Do the single escape chars have the right value?
|
||||
assertEquals(0x08, code("\b"));
|
||||
assertEquals(0x09, code("\t"));
|
||||
assertEquals(0x0A, code("\n"));
|
||||
assertEquals(0x0B, code("\v"));
|
||||
assertEquals(0x0C, code("\f"));
|
||||
assertEquals(0x0D, code("\r"));
|
||||
assertEquals(0x22, code("\""));
|
||||
assertEquals(0x27, code("\'"));
|
||||
assertEquals(0x5c, code("\\"));
|
||||
|
||||
// Do the hex and unicode escape chars have the right value?
|
||||
assertEquals(0x4a, code("\x4a"));
|
||||
assertEquals(0x5f, code("\u005f"));
|
50
test/mjsunit/class-of-builtins.js
Normal file
50
test/mjsunit/class-of-builtins.js
Normal file
@ -0,0 +1,50 @@
|
||||
// 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.
|
||||
|
||||
// The [[Class]] property of (instances of) builtin functions must be
|
||||
// correctly set.
|
||||
var funs = {
|
||||
Object: [ Object ],
|
||||
Function: [ Function ],
|
||||
Array: [ Array ],
|
||||
String: [ String ],
|
||||
Boolean: [ Boolean ],
|
||||
Number: [ Number ],
|
||||
Date: [ Date ],
|
||||
RegExp: [ RegExp ],
|
||||
Error: [ Error, TypeError, RangeError, SyntaxError, ReferenceError, EvalError, URIError ]
|
||||
}
|
||||
for (f in funs) {
|
||||
for (i in funs[f]) {
|
||||
assertEquals("[object " + f + "]",
|
||||
Object.prototype.toString.call(new funs[f][i]),
|
||||
funs[f][i]);
|
||||
assertEquals("[object Function]",
|
||||
Object.prototype.toString.call(funs[f][i]),
|
||||
funs[f][i]);
|
||||
}
|
||||
}
|
37
test/mjsunit/closure.js
Normal file
37
test/mjsunit/closure.js
Normal file
@ -0,0 +1,37 @@
|
||||
// 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.
|
||||
|
||||
// This test is lifted an old bug (ic_context_bug.js).
|
||||
|
||||
function f(n) {
|
||||
return function () { return n; }
|
||||
}
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
var a = f(i);
|
||||
assertEquals(i, a());
|
||||
}
|
44
test/mjsunit/compare-nan.js
Normal file
44
test/mjsunit/compare-nan.js
Normal file
@ -0,0 +1,44 @@
|
||||
// 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.
|
||||
|
||||
var a = [NaN, -1, 0, 1, 1.2, -7.9, true, false, 'foo', '0', 'NaN' ];
|
||||
for (var i in a) {
|
||||
var x = a[i];
|
||||
assertFalse(NaN == x);
|
||||
assertFalse(NaN === x);
|
||||
assertFalse(NaN < x);
|
||||
assertFalse(NaN > x);
|
||||
assertFalse(NaN <= x);
|
||||
assertFalse(NaN >= x);
|
||||
|
||||
assertFalse(x == NaN);
|
||||
assertFalse(x === NaN);
|
||||
assertFalse(x < NaN);
|
||||
assertFalse(x > NaN);
|
||||
assertFalse(x <= NaN);
|
||||
assertFalse(x >= NaN);
|
||||
}
|
220
test/mjsunit/const-redecl.js
Normal file
220
test/mjsunit/const-redecl.js
Normal file
@ -0,0 +1,220 @@
|
||||
// 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.
|
||||
|
||||
// Test for const semantics.
|
||||
|
||||
|
||||
function CheckException(e) {
|
||||
var string = e.toString();
|
||||
var index = string.indexOf(':');
|
||||
assertTrue(index >= 0);
|
||||
var name = string.slice(0, index);
|
||||
assertTrue(string.indexOf("has already been declared") >= 0 ||
|
||||
string.indexOf("redeclaration") >= 0);
|
||||
if (name == 'SyntaxError') return 'TypeError';
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
function TestLocal(s,e) {
|
||||
try {
|
||||
return eval("(function(){" + s + ";return " + e + "})")();
|
||||
} catch (x) {
|
||||
return CheckException(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// NOTE: TestGlobal usually only tests the given string in the context
|
||||
// of a global object in dictionary mode. This is because we use
|
||||
// delete to get rid of any added properties.
|
||||
function TestGlobal(s,e) {
|
||||
// Collect the global properties before the call.
|
||||
var properties = [];
|
||||
for (var key in this) properties.push(key);
|
||||
// Compute the result.
|
||||
var result;
|
||||
try {
|
||||
var code = s + (e ? "; $$$result=" + e : "");
|
||||
if (this.execScript) {
|
||||
execScript(code);
|
||||
} else {
|
||||
this.eval(code);
|
||||
}
|
||||
// Avoid issues if $$$result is not defined by
|
||||
// reading it through this.
|
||||
result = this.$$$result;
|
||||
} catch (x) {
|
||||
result = CheckException(x);
|
||||
}
|
||||
// Get rid of any introduced global properties before
|
||||
// returning the result.
|
||||
for (var key in this) {
|
||||
if (properties.indexOf(key) == -1) delete this[key];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
function TestContext(s,e) {
|
||||
try {
|
||||
// Use a with-statement to force the system to do dynamic
|
||||
// declarations of the introduced variables or constants.
|
||||
with ({}) {
|
||||
return eval(s + ";" + e);
|
||||
}
|
||||
} catch (x) {
|
||||
return CheckException(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function TestAll(expected,s,opt_e) {
|
||||
var e = "";
|
||||
var msg = s;
|
||||
if (opt_e) { e = opt_e; msg += "; " + opt_e; }
|
||||
assertEquals(expected, TestLocal(s,e), "local:'" + msg + "'");
|
||||
assertEquals(expected, TestGlobal(s,e), "global:'" + msg + "'");
|
||||
assertEquals(expected, TestContext(s,e), "context:'" + msg + "'");
|
||||
}
|
||||
|
||||
|
||||
function TestConflict(def0, def1) {
|
||||
// No eval.
|
||||
TestAll("TypeError", def0 +'; ' + def1);
|
||||
// Eval everything.
|
||||
TestAll("TypeError", 'eval("' + def0 + '; ' + def1 + '")');
|
||||
// Eval first definition.
|
||||
TestAll("TypeError", 'eval("' + def0 +'"); ' + def1);
|
||||
// Eval second definition.
|
||||
TestAll("TypeError", def0 + '; eval("' + def1 + '")');
|
||||
// Eval both definitions separately.
|
||||
TestAll("TypeError", 'eval("' + def0 +'"); eval("' + def1 + '")');
|
||||
}
|
||||
|
||||
|
||||
// Test conflicting definitions.
|
||||
TestConflict("const x", "var x");
|
||||
TestConflict("const x = 0", "var x");
|
||||
TestConflict("const x", "var x = 0");
|
||||
TestConflict("const x = 0", "var x = 0");
|
||||
|
||||
TestConflict("var x", "const x");
|
||||
TestConflict("var x = 0", "const x");
|
||||
TestConflict("var x", "const x = 0");
|
||||
TestConflict("var x = 0", "const x = 0");
|
||||
|
||||
TestConflict("const x = undefined", "var x");
|
||||
TestConflict("const x", "var x = undefined");
|
||||
TestConflict("const x = undefined", "var x = undefined");
|
||||
|
||||
TestConflict("var x = undefined", "const x");
|
||||
TestConflict("var x", "const x = undefined");
|
||||
TestConflict("var x = undefined", "const x = undefined");
|
||||
|
||||
TestConflict("const x = undefined", "var x = 0");
|
||||
TestConflict("const x = 0", "var x = undefined");
|
||||
|
||||
TestConflict("var x = undefined", "const x = 0");
|
||||
TestConflict("var x = 0", "const x = undefined");
|
||||
|
||||
TestConflict("const x", "function x() { }");
|
||||
TestConflict("const x = 0", "function x() { }");
|
||||
TestConflict("const x = undefined", "function x() { }");
|
||||
|
||||
TestConflict("function x() { }", "const x");
|
||||
TestConflict("function x() { }", "const x = 0");
|
||||
TestConflict("function x() { }", "const x = undefined");
|
||||
|
||||
TestConflict("const x, y", "var x");
|
||||
TestConflict("const x, y", "var y");
|
||||
TestConflict("const x = 0, y", "var x");
|
||||
TestConflict("const x = 0, y", "var y");
|
||||
TestConflict("const x, y = 0", "var x");
|
||||
TestConflict("const x, y = 0", "var y");
|
||||
TestConflict("const x = 0, y = 0", "var x");
|
||||
TestConflict("const x = 0, y = 0", "var y");
|
||||
|
||||
TestConflict("var x", "const x, y");
|
||||
TestConflict("var y", "const x, y");
|
||||
TestConflict("var x", "const x = 0, y");
|
||||
TestConflict("var y", "const x = 0, y");
|
||||
TestConflict("var x", "const x, y = 0");
|
||||
TestConflict("var y", "const x, y = 0");
|
||||
TestConflict("var x", "const x = 0, y = 0");
|
||||
TestConflict("var y", "const x = 0, y = 0");
|
||||
|
||||
|
||||
// Test that multiple conflicts do not cause issues.
|
||||
TestConflict("var x, y", "const x, y");
|
||||
|
||||
|
||||
// Test that repeated const declarations throw redeclaration errors.
|
||||
TestConflict("const x", "const x");
|
||||
TestConflict("const x = 0", "const x");
|
||||
TestConflict("const x", "const x = 0");
|
||||
TestConflict("const x = 0", "const x = 0");
|
||||
|
||||
TestConflict("const x = undefined", "const x");
|
||||
TestConflict("const x", "const x = undefined");
|
||||
TestConflict("const x = undefined", "const x = undefined");
|
||||
|
||||
TestConflict("const x = undefined", "const x = 0");
|
||||
TestConflict("const x = 0", "const x = undefined");
|
||||
|
||||
TestConflict("const x, y", "const x");
|
||||
TestConflict("const x, y", "const y");
|
||||
TestConflict("const x = 0, y", "const x");
|
||||
TestConflict("const x = 0, y", "const y");
|
||||
TestConflict("const x, y = 0", "const x");
|
||||
TestConflict("const x, y = 0", "const y");
|
||||
TestConflict("const x = 0, y = 0", "const x");
|
||||
TestConflict("const x = 0, y = 0", "const y");
|
||||
|
||||
TestConflict("const x", "const x, y");
|
||||
TestConflict("const y", "const x, y");
|
||||
TestConflict("const x", "const x = 0, y");
|
||||
TestConflict("const y", "const x = 0, y");
|
||||
TestConflict("const x", "const x, y = 0");
|
||||
TestConflict("const y", "const x, y = 0");
|
||||
TestConflict("const x", "const x = 0, y = 0");
|
||||
TestConflict("const y", "const x = 0, y = 0");
|
||||
|
||||
|
||||
// Test that multiple const conflicts do not cause issues.
|
||||
TestConflict("const x, y", "const x, y");
|
||||
|
||||
|
||||
// Test that const inside loop behaves correctly.
|
||||
var loop = "for (var i = 0; i < 3; i++) { const x = i; }";
|
||||
TestAll(0, loop, "x");
|
||||
TestAll(0, "var a,b,c,d,e,f,g,h; " + loop, "x");
|
||||
|
||||
|
||||
// Test that const inside with behaves correctly.
|
||||
TestAll(87, "with ({x:42}) { const x = 87; }", "x");
|
||||
TestAll(undefined, "with ({x:42}) { const x; }", "x");
|
68
test/mjsunit/const.js
Normal file
68
test/mjsunit/const.js
Normal file
@ -0,0 +1,68 @@
|
||||
// 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.
|
||||
|
||||
// Test const properties and pre/postfix operation.
|
||||
function f() {
|
||||
const x = 1;
|
||||
x++;
|
||||
assertEquals(1, x);
|
||||
x--;
|
||||
assertEquals(1, x);
|
||||
++x;
|
||||
assertEquals(1, x);
|
||||
--x;
|
||||
assertEquals(1, x);
|
||||
assertEquals(1, x++);
|
||||
assertEquals(1, x--);
|
||||
assertEquals(2, ++x);
|
||||
assertEquals(0, --x);
|
||||
}
|
||||
|
||||
f();
|
||||
|
||||
// Test that the value is read eventhough assignment is disallowed.
|
||||
// Spidermonkey does not do this, but it seems like the right thing to
|
||||
// do so that 'o++' is equivalent to 'o = o + 1'.
|
||||
var valueOfCount = 0;
|
||||
|
||||
function g() {
|
||||
const o = { valueOf: function() { valueOfCount++; return 42; } }
|
||||
assertEquals(42, o);
|
||||
assertEquals(0, valueOfCount);
|
||||
o++;
|
||||
assertEquals(42, o);
|
||||
assertEquals(1, valueOfCount);
|
||||
++o;
|
||||
assertEquals(42, o);
|
||||
assertEquals(2, valueOfCount);
|
||||
o--;
|
||||
assertEquals(42, o);
|
||||
assertEquals(3, valueOfCount);
|
||||
--o;
|
||||
assertEquals(42, o);
|
||||
assertEquals(4, valueOfCount);
|
||||
}
|
65
test/mjsunit/cyclic-array-to-string.js
Normal file
65
test/mjsunit/cyclic-array-to-string.js
Normal file
@ -0,0 +1,65 @@
|
||||
// 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.
|
||||
|
||||
// Test printing of cyclic arrays.
|
||||
|
||||
var a1 = [1,2];
|
||||
assertEquals("1,2", a1.toString());
|
||||
assertEquals("1,2", a1.toLocaleString());
|
||||
assertEquals("1,2", a1.join());
|
||||
a1.push(a1);
|
||||
assertEquals("1,2,", a1.toString());
|
||||
assertEquals("1,2,", a1.toLocaleString());
|
||||
assertEquals("1,2,", a1.join());
|
||||
a1.push(1);
|
||||
assertEquals("1,2,,1", a1.toString());
|
||||
assertEquals("1,2,,1", a1.toLocaleString());
|
||||
assertEquals("1,2,,1", a1.join());
|
||||
a1.push(a1);
|
||||
assertEquals("1,2,,1,", a1.toString());
|
||||
assertEquals("1,2,,1,", a1.toLocaleString());
|
||||
assertEquals("1,2,,1,", a1.join());
|
||||
|
||||
a1 = [1,2];
|
||||
var a2 = [3,4];
|
||||
a1.push(a2);
|
||||
a1.push(a2);
|
||||
assertEquals("1,2,3,4,3,4", a1.toString());
|
||||
assertEquals("1,2,3,4,3,4", a1.toLocaleString());
|
||||
assertEquals("1,2,3,4,3,4", a1.join());
|
||||
a2.push(a1);
|
||||
assertEquals("1,2,3,4,,3,4,", a1.toString());
|
||||
assertEquals("1,2,3,4,,3,4,", a1.toLocaleString());
|
||||
assertEquals("1,2,3,4,,3,4,", a1.join());
|
||||
|
||||
a1 = [];
|
||||
a2 = [a1];
|
||||
a1.push(a2);
|
||||
assertEquals("", a1.toString());
|
||||
assertEquals("", a1.toLocaleString());
|
||||
assertEquals("", a1.join());
|
||||
|
265
test/mjsunit/date-parse.js
Normal file
265
test/mjsunit/date-parse.js
Normal file
@ -0,0 +1,265 @@
|
||||
// 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.
|
||||
|
||||
// Test that we can parse dates in all the different formats that we
|
||||
// have to support.
|
||||
//
|
||||
// These formats are all supported by KJS but a lot of them are not
|
||||
// supported by Spidermonkey.
|
||||
|
||||
function testDateParse(string) {
|
||||
var d = Date.parse(string);
|
||||
assertEquals(946713600000, d, string);
|
||||
};
|
||||
|
||||
|
||||
// For local time we just test that parsing returns non-NaN positive
|
||||
// number of milliseconds to make it timezone independent.
|
||||
function testDateParseLocalTime(string) {
|
||||
var d = Date.parse(string);
|
||||
assertTrue(d > 0 && !isNaN(d));
|
||||
};
|
||||
|
||||
|
||||
function testDateParseMisc(array) {
|
||||
assertTrue(array.length == 2);
|
||||
var string = array[0];
|
||||
var expected = array[1];
|
||||
var d = Date.parse(string);
|
||||
assertEquals(expected, d, string);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Test all the formats in UT timezone.
|
||||
//
|
||||
var testCasesUT = [
|
||||
'Sat, 01-Jan-2000 08:00:00 UT',
|
||||
'Sat, 01 Jan 2000 08:00:00 UT',
|
||||
'Jan 01 2000 08:00:00 UT',
|
||||
'Jan 01 08:00:00 UT 2000',
|
||||
'Saturday, 01-Jan-00 08:00:00 UT',
|
||||
'01 Jan 00 08:00 +0000',
|
||||
// Ignore weekdays.
|
||||
'Mon, 01 Jan 2000 08:00:00 UT',
|
||||
'Tue, 01 Jan 2000 08:00:00 UT',
|
||||
// Ignore prefix that is not part of a date.
|
||||
'[Saturday] Jan 01 08:00:00 UT 2000',
|
||||
'Ignore all of this stuff because it is annoying 01 Jan 2000 08:00:00 UT',
|
||||
'[Saturday] Jan 01 2000 08:00:00 UT',
|
||||
'All of this stuff is really annnoying, so it will be ignored Jan 01 2000 08:00:00 UT',
|
||||
// If the three first letters of the month is a
|
||||
// month name we are happy - ignore the rest.
|
||||
'Sat, 01-Janisamonth-2000 08:00:00 UT',
|
||||
'Sat, 01 Janisamonth 2000 08:00:00 UT',
|
||||
'Janisamonth 01 2000 08:00:00 UT',
|
||||
'Janisamonth 01 08:00:00 UT 2000',
|
||||
'Saturday, 01-Janisamonth-00 08:00:00 UT',
|
||||
'01 Janisamonth 00 08:00 +0000',
|
||||
// Allow missing space between month and day.
|
||||
'Janisamonthandtherestisignored01 2000 08:00:00 UT',
|
||||
'Jan01 2000 08:00:00 UT',
|
||||
// Allow year/month/day format.
|
||||
'Sat, 2000/01/01 08:00:00 UT',
|
||||
// Allow month/day/year format.
|
||||
'Sat, 01/01/2000 08:00:00 UT',
|
||||
// Allow month/day year format.
|
||||
'Sat, 01/01 2000 08:00:00 UT',
|
||||
// Allow comma instead of space after day, month and year.
|
||||
'Sat, 01,Jan,2000,08:00:00 UT',
|
||||
// Seconds are optional.
|
||||
'Sat, 01-Jan-2000 08:00 UT',
|
||||
'Sat, 01 Jan 2000 08:00 UT',
|
||||
'Jan 01 2000 08:00 UT',
|
||||
'Jan 01 08:00 UT 2000',
|
||||
'Saturday, 01-Jan-00 08:00 UT',
|
||||
'01 Jan 00 08:00 +0000',
|
||||
// Allow AM/PM after the time.
|
||||
'Sat, 01-Jan-2000 08:00 AM UT',
|
||||
'Sat, 01 Jan 2000 08:00 AM UT',
|
||||
'Jan 01 2000 08:00 AM UT',
|
||||
'Jan 01 08:00 AM UT 2000',
|
||||
'Saturday, 01-Jan-00 08:00 AM UT',
|
||||
'01 Jan 00 08:00 AM +0000',
|
||||
// White space and stuff in parenthesis is
|
||||
// apparently allowed in most places where white
|
||||
// space is allowed.
|
||||
' Sat, 01-Jan-2000 08:00:00 UT ',
|
||||
' Sat, 01 Jan 2000 08:00:00 UT ',
|
||||
' Saturday, 01-Jan-00 08:00:00 UT ',
|
||||
' 01 Jan 00 08:00 +0000 ',
|
||||
' ()(Sat, 01-Jan-2000) Sat, 01-Jan-2000 08:00:00 UT ',
|
||||
' Sat()(Sat, 01-Jan-2000)01 Jan 2000 08:00:00 UT ',
|
||||
' Sat,(02)01 Jan 2000 08:00:00 UT ',
|
||||
' Sat, 01(02)Jan 2000 08:00:00 UT ',
|
||||
' Sat, 01 Jan 2000 (2001)08:00:00 UT ',
|
||||
' Sat, 01 Jan 2000 (01)08:00:00 UT ',
|
||||
' Sat, 01 Jan 2000 (01:00:00)08:00:00 UT ',
|
||||
' Sat, 01 Jan 2000 08:00:00 (CDT)UT ',
|
||||
' Sat, 01 Jan 2000 08:00:00 UT((((CDT))))',
|
||||
' Saturday, 01-Jan-00 ()(((asfd)))(Sat, 01-Jan-2000)08:00:00 UT ',
|
||||
' 01 Jan 00 08:00 ()(((asdf)))(Sat, 01-Jan-2000)+0000 ',
|
||||
' 01 Jan 00 08:00 +0000()((asfd)(Sat, 01-Jan-2000)) '];
|
||||
|
||||
//
|
||||
// Test that we do the right correction for different time zones.
|
||||
// I'll assume that we can handle the same formats as for UT and only
|
||||
// test a few formats for each of the timezones.
|
||||
//
|
||||
|
||||
// GMT = UT
|
||||
var testCasesGMT = [
|
||||
'Sat, 01-Jan-2000 08:00:00 GMT',
|
||||
'Sat, 01-Jan-2000 08:00:00 GMT+0',
|
||||
'Sat, 01-Jan-2000 08:00:00 GMT+00',
|
||||
'Sat, 01-Jan-2000 08:00:00 GMT+000',
|
||||
'Sat, 01-Jan-2000 08:00:00 GMT+0000',
|
||||
'Sat, 01-Jan-2000 08:00:00 GMT+00:00', // Interestingly, KJS cannot handle this.
|
||||
'Sat, 01 Jan 2000 08:00:00 GMT',
|
||||
'Saturday, 01-Jan-00 08:00:00 GMT',
|
||||
'01 Jan 00 08:00 -0000',
|
||||
'01 Jan 00 08:00 +0000'];
|
||||
|
||||
// EST = UT minus 5 hours.
|
||||
var testCasesEST = [
|
||||
'Sat, 01-Jan-2000 03:00:00 UTC-0500',
|
||||
'Sat, 01-Jan-2000 03:00:00 UTC-05:00', // Interestingly, KJS cannot handle this.
|
||||
'Sat, 01-Jan-2000 03:00:00 EST',
|
||||
'Sat, 01 Jan 2000 03:00:00 EST',
|
||||
'Saturday, 01-Jan-00 03:00:00 EST',
|
||||
'01 Jan 00 03:00 -0500'];
|
||||
|
||||
// EDT = UT minus 4 hours.
|
||||
var testCasesEDT = [
|
||||
'Sat, 01-Jan-2000 04:00:00 EDT',
|
||||
'Sat, 01 Jan 2000 04:00:00 EDT',
|
||||
'Saturday, 01-Jan-00 04:00:00 EDT',
|
||||
'01 Jan 00 04:00 -0400'];
|
||||
|
||||
// CST = UT minus 6 hours.
|
||||
var testCasesCST = [
|
||||
'Sat, 01-Jan-2000 02:00:00 CST',
|
||||
'Sat, 01 Jan 2000 02:00:00 CST',
|
||||
'Saturday, 01-Jan-00 02:00:00 CST',
|
||||
'01 Jan 00 02:00 -0600'];
|
||||
|
||||
// CDT = UT minus 5 hours.
|
||||
var testCasesCDT = [
|
||||
'Sat, 01-Jan-2000 03:00:00 CDT',
|
||||
'Sat, 01 Jan 2000 03:00:00 CDT',
|
||||
'Saturday, 01-Jan-00 03:00:00 CDT',
|
||||
'01 Jan 00 03:00 -0500'];
|
||||
|
||||
// MST = UT minus 7 hours.
|
||||
var testCasesMST = [
|
||||
'Sat, 01-Jan-2000 01:00:00 MST',
|
||||
'Sat, 01 Jan 2000 01:00:00 MST',
|
||||
'Saturday, 01-Jan-00 01:00:00 MST',
|
||||
'01 Jan 00 01:00 -0700'];
|
||||
|
||||
// MDT = UT minus 6 hours.
|
||||
var testCasesMDT = [
|
||||
'Sat, 01-Jan-2000 02:00:00 MDT',
|
||||
'Sat, 01 Jan 2000 02:00:00 MDT',
|
||||
'Saturday, 01-Jan-00 02:00:00 MDT',
|
||||
'01 Jan 00 02:00 -0600'];
|
||||
|
||||
// PST = UT minus 8 hours.
|
||||
var testCasesPST = [
|
||||
'Sat, 01-Jan-2000 00:00:00 PST',
|
||||
'Sat, 01 Jan 2000 00:00:00 PST',
|
||||
'Saturday, 01-Jan-00 00:00:00 PST',
|
||||
'01 Jan 00 00:00 -0800',
|
||||
// Allow missing time.
|
||||
'Sat, 01-Jan-2000 PST'];
|
||||
|
||||
// PDT = UT minus 7 hours.
|
||||
var testCasesPDT = [
|
||||
'Sat, 01-Jan-2000 01:00:00 PDT',
|
||||
'Sat, 01 Jan 2000 01:00:00 PDT',
|
||||
'Saturday, 01-Jan-00 01:00:00 PDT',
|
||||
'01 Jan 00 01:00 -0700'];
|
||||
|
||||
|
||||
// Local time cases.
|
||||
var testCasesLocalTime = [
|
||||
// Allow timezone ommision.
|
||||
'Sat, 01-Jan-2000 08:00:00',
|
||||
'Sat, 01 Jan 2000 08:00:00',
|
||||
'Jan 01 2000 08:00:00',
|
||||
'Jan 01 08:00:00 2000',
|
||||
'Saturday, 01-Jan-00 08:00:00',
|
||||
'01 Jan 00 08:00'];
|
||||
|
||||
|
||||
// Misc. test cases that result in a different time value.
|
||||
var testCasesMisc = [
|
||||
// Special handling for years in the [0, 100) range.
|
||||
['Sat, 01 Jan 0 08:00:00 UT', 946713600000], // year 2000
|
||||
['Sat, 01 Jan 49 08:00:00 UT', 2493100800000], // year 2049
|
||||
['Sat, 01 Jan 50 08:00:00 UT', -631123200000], // year 1950
|
||||
['Sat, 01 Jan 99 08:00:00 UT', 915177600000], // year 1999
|
||||
['Sat, 01 Jan 100 08:00:00 UT', -59011430400000], // year 100
|
||||
// Test PM after time.
|
||||
['Sat, 01-Jan-2000 08:00 PM UT', 946756800000],
|
||||
['Sat, 01 Jan 2000 08:00 PM UT', 946756800000],
|
||||
['Jan 01 2000 08:00 PM UT', 946756800000],
|
||||
['Jan 01 08:00 PM UT 2000', 946756800000],
|
||||
['Saturday, 01-Jan-00 08:00 PM UT', 946756800000],
|
||||
['01 Jan 00 08:00 PM +0000', 946756800000]];
|
||||
|
||||
|
||||
// Run all the tests.
|
||||
testCasesUT.forEach(testDateParse);
|
||||
testCasesGMT.forEach(testDateParse);
|
||||
testCasesEST.forEach(testDateParse);
|
||||
testCasesEDT.forEach(testDateParse);
|
||||
testCasesCST.forEach(testDateParse);
|
||||
testCasesCDT.forEach(testDateParse);
|
||||
testCasesMST.forEach(testDateParse);
|
||||
testCasesMDT.forEach(testDateParse);
|
||||
testCasesPST.forEach(testDateParse);
|
||||
testCasesPDT.forEach(testDateParse);
|
||||
testCasesLocalTime.forEach(testDateParseLocalTime);
|
||||
testCasesMisc.forEach(testDateParseMisc);
|
||||
|
||||
|
||||
// Test that we can parse our own date format.
|
||||
// (Dates from 1970 to ~2070 with 95h steps.)
|
||||
for (var i = 0; i < 24 * 365 * 100; i += 95) {
|
||||
var ms = i * (3600 * 1000);
|
||||
var s = (new Date(ms)).toString();
|
||||
assertEquals(ms, Date.parse(s), s);
|
||||
}
|
||||
|
||||
// Negative tests.
|
||||
var testCasesNegative = [
|
||||
'May 25 2008 1:30 (PM)) UTC',
|
||||
'May 25 2008 1:30( )AM (PM)',
|
||||
'May 25 2008 AAA (GMT)'];
|
||||
|
||||
testCasesNegative.forEach(function (s) { assertTrue(isNaN(Date.parse(s))); });
|
126
test/mjsunit/date.js
Normal file
126
test/mjsunit/date.js
Normal file
@ -0,0 +1,126 @@
|
||||
// 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.
|
||||
|
||||
// Test date construction from other dates.
|
||||
var date0 = new Date(1111);
|
||||
var date1 = new Date(date0);
|
||||
assertEquals(1111, date0.getTime());
|
||||
assertEquals(date0.getTime(), date1.getTime());
|
||||
var date2 = new Date(date0.toString());
|
||||
assertEquals(1000, date2.getTime());
|
||||
|
||||
// Test that dates may contain commas.
|
||||
var date0 = Date.parse("Dec 25 1995 1:30");
|
||||
var date1 = Date.parse("Dec 25, 1995 1:30");
|
||||
var date2 = Date.parse("Dec 25 1995, 1:30");
|
||||
var date3 = Date.parse("Dec 25, 1995, 1:30");
|
||||
assertEquals(date0, date1);
|
||||
assertEquals(date1, date2);
|
||||
assertEquals(date2, date3);
|
||||
|
||||
|
||||
// Tests inspired by js1_5/Date/regress-346363.js
|
||||
|
||||
// Year
|
||||
var a = new Date();
|
||||
a.setFullYear();
|
||||
a.setFullYear(2006);
|
||||
assertEquals(2006, a.getFullYear());
|
||||
|
||||
var b = new Date();
|
||||
b.setUTCFullYear();
|
||||
b.setUTCFullYear(2006);
|
||||
assertEquals(2006, b.getUTCFullYear());
|
||||
|
||||
// Month
|
||||
var c = new Date();
|
||||
c.setMonth();
|
||||
c.setMonth(2);
|
||||
assertTrue(isNaN(c.getMonth()));
|
||||
|
||||
var d = new Date();
|
||||
d.setUTCMonth();
|
||||
d.setUTCMonth(2);
|
||||
assertTrue(isNaN(d.getUTCMonth()));
|
||||
|
||||
// Date
|
||||
var e = new Date();
|
||||
e.setDate();
|
||||
e.setDate(2);
|
||||
assertTrue(isNaN(e.getDate()));
|
||||
|
||||
var f = new Date();
|
||||
f.setUTCDate();
|
||||
f.setUTCDate(2);
|
||||
assertTrue(isNaN(f.getUTCDate()));
|
||||
|
||||
// Hours
|
||||
var g = new Date();
|
||||
g.setHours();
|
||||
g.setHours(2);
|
||||
assertTrue(isNaN(g.getHours()));
|
||||
|
||||
var h = new Date();
|
||||
h.setUTCHours();
|
||||
h.setUTCHours(2);
|
||||
assertTrue(isNaN(h.getUTCHours()));
|
||||
|
||||
// Minutes
|
||||
var g = new Date();
|
||||
g.setMinutes();
|
||||
g.setMinutes(2);
|
||||
assertTrue(isNaN(g.getMinutes()));
|
||||
|
||||
var h = new Date();
|
||||
h.setUTCHours();
|
||||
h.setUTCHours(2);
|
||||
assertTrue(isNaN(h.getUTCHours()));
|
||||
|
||||
|
||||
// Seconds
|
||||
var i = new Date();
|
||||
i.setSeconds();
|
||||
i.setSeconds(2);
|
||||
assertTrue(isNaN(i.getSeconds()));
|
||||
|
||||
var j = new Date();
|
||||
j.setUTCSeconds();
|
||||
j.setUTCSeconds(2);
|
||||
assertTrue(isNaN(j.getUTCSeconds()));
|
||||
|
||||
|
||||
// Milliseconds
|
||||
var k = new Date();
|
||||
k.setMilliseconds();
|
||||
k.setMilliseconds(2);
|
||||
assertTrue(isNaN(k.getMilliseconds()));
|
||||
|
||||
var l = new Date();
|
||||
l.setUTCMilliseconds();
|
||||
l.setUTCMilliseconds(2);
|
||||
assertTrue(isNaN(l.getUTCMilliseconds()));
|
||||
|
122
test/mjsunit/debug-backtrace-text.js
Normal file
122
test/mjsunit/debug-backtrace-text.js
Normal file
@ -0,0 +1,122 @@
|
||||
// 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.
|
||||
|
||||
// Flags: --expose-debug-as debug
|
||||
|
||||
// The functions used for testing backtraces.
|
||||
function Point(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
};
|
||||
|
||||
Point.prototype.distanceTo = function(p) {
|
||||
debugger;
|
||||
return Math.sqrt(Math.pow(Math.abs(this.x - p.x), 2) + Math.pow(Math.abs(this.y - p.y), 2))
|
||||
}
|
||||
|
||||
p1 = new Point(1,1);
|
||||
p2 = new Point(2,2);
|
||||
|
||||
p1.distanceTo = function(p) {
|
||||
return p.distanceTo(this);
|
||||
}
|
||||
|
||||
function distance(p, q) {
|
||||
return p.distanceTo(q);
|
||||
}
|
||||
|
||||
function createPoint(x, y) {
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
a=[1,2,distance];
|
||||
|
||||
// Get the Debug object exposed from the debug context global object.
|
||||
Debug = debug.Debug
|
||||
|
||||
testConstructor = false; // Flag to control which part of the test is run.
|
||||
listenerCalled = false;
|
||||
exception = false;
|
||||
|
||||
function safeEval(code) {
|
||||
try {
|
||||
return eval('(' + code + ')');
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function listener(event, exec_state, event_data, data) {
|
||||
try {
|
||||
if (event == Debug.DebugEvent.Break)
|
||||
{
|
||||
if (!testConstructor) {
|
||||
// The expected backtrace is
|
||||
// 0: Call distance on Point where distance is a property on the prototype
|
||||
// 1: Call distance on Point where distance is a direct property
|
||||
// 2: Call on function an array element 2
|
||||
// 3: [anonymous]
|
||||
assertEquals("#<a Point>.distanceTo(p=#<a Point>)", exec_state.frame(0).invocationText());
|
||||
assertEquals("#<a Point>.distanceTo(p=#<a Point>)", exec_state.frame(1).invocationText());
|
||||
assertEquals("#<an Array>[2](aka distance)(p=#<a Point>, q=#<a Point>)", exec_state.frame(2).invocationText());
|
||||
assertEquals("[anonymous]()", exec_state.frame(3).invocationText());
|
||||
listenerCalled = true;
|
||||
} else {
|
||||
// The expected backtrace is
|
||||
// 0: Call Point constructor
|
||||
// 1: Call on global function createPoint
|
||||
// 2: [anonymous]
|
||||
assertEquals("new Point(x=0, y=0)", exec_state.frame(0).invocationText());
|
||||
assertEquals("createPoint(x=0, y=0)", exec_state.frame(1).invocationText());
|
||||
assertEquals("[anonymous]()", exec_state.frame(2).invocationText());
|
||||
listenerCalled = true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
exception = e
|
||||
};
|
||||
};
|
||||
|
||||
// Add the debug event listener.
|
||||
Debug.addListener(listener);
|
||||
|
||||
// Set a break point and call to invoke the debug event listener.
|
||||
a[2](p1, p2)
|
||||
|
||||
// Make sure that the debug event listener vas invoked.
|
||||
assertTrue(listenerCalled);
|
||||
assertFalse(exception, "exception in listener")
|
||||
|
||||
// Set a break point and call to invoke the debug event listener.
|
||||
listenerCalled = false;
|
||||
testConstructor = true;
|
||||
Debug.setBreakPoint(Point, 0, 0);
|
||||
createPoint(0, 0);
|
||||
|
||||
// Make sure that the debug event listener vas invoked (again).
|
||||
assertTrue(listenerCalled);
|
||||
assertFalse(exception, "exception in listener")
|
194
test/mjsunit/debug-backtrace.js
Normal file
194
test/mjsunit/debug-backtrace.js
Normal file
@ -0,0 +1,194 @@
|
||||
// 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.
|
||||
|
||||
// Flags: --expose-debug-as debug
|
||||
// The functions used for testing backtraces. They are at the top to make the
|
||||
// testing of source line/column easier.
|
||||
function f(x, y) {
|
||||
a=1;
|
||||
};
|
||||
|
||||
function g() {
|
||||
new f(1);
|
||||
};
|
||||
|
||||
|
||||
// Get the Debug object exposed from the debug context global object.
|
||||
Debug = debug.Debug
|
||||
|
||||
listenerCalled = false;
|
||||
exception = false;
|
||||
|
||||
function safeEval(code) {
|
||||
try {
|
||||
return eval('(' + code + ')');
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function listener(event, exec_state, event_data, data) {
|
||||
try {
|
||||
if (event == Debug.DebugEvent.Break)
|
||||
{
|
||||
// The expected backtrace is
|
||||
// 0: f
|
||||
// 1: g
|
||||
// 2: [anonymous]
|
||||
|
||||
// Get the debug command processor.
|
||||
var dcp = exec_state.debugCommandProcessor();
|
||||
|
||||
// Get the backtrace.
|
||||
var json;
|
||||
json = '{"seq":0,"type":"request","command":"backtrace"}'
|
||||
var backtrace = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals(0, backtrace.fromFrame);
|
||||
assertEquals(3, backtrace.toFrame);
|
||||
assertEquals(3, backtrace.totalFrames);
|
||||
var frames = backtrace.frames;
|
||||
assertEquals(3, frames.length);
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assertEquals('frame', frames[i].type);
|
||||
}
|
||||
assertEquals(0, frames[0].index);
|
||||
assertEquals("f", frames[0].func.name);
|
||||
assertEquals(1, frames[1].index);
|
||||
assertEquals("g", frames[1].func.name);
|
||||
assertEquals(2, frames[2].index);
|
||||
assertEquals("", frames[2].func.name);
|
||||
|
||||
// Get backtrace with two frames.
|
||||
json = '{"seq":0,"type":"request","command":"backtrace","arguments":{"fromFrame":1,"toFrame":3}}'
|
||||
var backtrace = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals(1, backtrace.fromFrame);
|
||||
assertEquals(3, backtrace.toFrame);
|
||||
assertEquals(3, backtrace.totalFrames);
|
||||
var frames = backtrace.frames;
|
||||
assertEquals(2, frames.length);
|
||||
for (var i = 0; i < frames.length; i++) {
|
||||
assertEquals('frame', frames[i].type);
|
||||
}
|
||||
assertEquals(1, frames[0].index);
|
||||
assertEquals("g", frames[0].func.name);
|
||||
assertEquals(2, frames[1].index);
|
||||
assertEquals("", frames[1].func.name);
|
||||
|
||||
// Get the individual frames.
|
||||
var frame;
|
||||
json = '{"seq":0,"type":"request","command":"frame"}'
|
||||
frame = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals(0, frame.index);
|
||||
assertEquals("f", frame.func.name);
|
||||
assertTrue(frame.constructCall);
|
||||
assertEquals(31, frame.line);
|
||||
assertEquals(3, frame.column);
|
||||
assertEquals(2, frame.arguments.length);
|
||||
assertEquals('x', frame.arguments[0].name);
|
||||
assertEquals('number', frame.arguments[0].value.type);
|
||||
assertEquals(1, frame.arguments[0].value.value);
|
||||
assertEquals('y', frame.arguments[1].name);
|
||||
assertEquals('undefined', frame.arguments[1].value.type);
|
||||
|
||||
json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":0}}'
|
||||
frame = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals(0, frame.index);
|
||||
assertEquals("f", frame.func.name);
|
||||
assertEquals(31, frame.line);
|
||||
assertEquals(3, frame.column);
|
||||
assertEquals(2, frame.arguments.length);
|
||||
assertEquals('x', frame.arguments[0].name);
|
||||
assertEquals('number', frame.arguments[0].value.type);
|
||||
assertEquals(1, frame.arguments[0].value.value);
|
||||
assertEquals('y', frame.arguments[1].name);
|
||||
assertEquals('undefined', frame.arguments[1].value.type);
|
||||
|
||||
json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":1}}'
|
||||
frame = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals(1, frame.index);
|
||||
assertEquals("g", frame.func.name);
|
||||
assertFalse(frame.constructCall);
|
||||
assertEquals(35, frame.line);
|
||||
assertEquals(2, frame.column);
|
||||
assertEquals(0, frame.arguments.length);
|
||||
|
||||
json = '{"seq":0,"type":"request","command":"frame","arguments":{"number":2}}'
|
||||
frame = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals(2, frame.index);
|
||||
assertEquals("", frame.func.name);
|
||||
|
||||
// Source slices for the individual frames (they all refer to this script).
|
||||
json = '{"seq":0,"type":"request","command":"source",' +
|
||||
'"arguments":{"frame":0,"fromLine":30,"toLine":32}}'
|
||||
source = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals("function f(x, y) {", source.source.substring(0, 18));
|
||||
assertEquals(30, source.fromLine);
|
||||
assertEquals(32, source.toLine);
|
||||
|
||||
json = '{"seq":0,"type":"request","command":"source",' +
|
||||
'"arguments":{"frame":1,"fromLine":31,"toLine":32}}'
|
||||
source = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals(" a=1;", source.source.substring(0, 6));
|
||||
assertEquals(31, source.fromLine);
|
||||
assertEquals(32, source.toLine);
|
||||
|
||||
json = '{"seq":0,"type":"request","command":"source",' +
|
||||
'"arguments":{"frame":2,"fromLine":35,"toLine":36}}'
|
||||
source = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals(" new f(1);", source.source.substring(0, 11));
|
||||
assertEquals(35, source.fromLine);
|
||||
assertEquals(36, source.toLine);
|
||||
|
||||
// Test line interval way beyond this script will result in an error.
|
||||
json = '{"seq":0,"type":"request","command":"source",' +
|
||||
'"arguments":{"frame":0,"fromLine":10000,"toLine":20000}}'
|
||||
response = safeEval(dcp.processDebugJSONRequest(json));
|
||||
assertFalse(response.success);
|
||||
|
||||
// Test without arguments.
|
||||
json = '{"seq":0,"type":"request","command":"source"}'
|
||||
source = safeEval(dcp.processDebugJSONRequest(json)).body;
|
||||
assertEquals(Debug.findScript(f).source, source.source);
|
||||
|
||||
listenerCalled = true;
|
||||
}
|
||||
} catch (e) {
|
||||
exception = e
|
||||
};
|
||||
};
|
||||
|
||||
// Add the debug event listener.
|
||||
Debug.addListener(listener);
|
||||
|
||||
// Set a break point and call to invoke the debug event listener.
|
||||
Debug.setBreakPoint(f, 0, 0);
|
||||
g();
|
||||
|
||||
// Make sure that the debug event listener vas invoked.
|
||||
assertFalse(exception, "exception in listener");
|
||||
assertTrue(listenerCalled);
|
||||
|
120
test/mjsunit/debug-breakpoints.js
Normal file
120
test/mjsunit/debug-breakpoints.js
Normal file
@ -0,0 +1,120 @@
|
||||
// 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.
|
||||
|
||||
// Flags: --expose-debug-as debug
|
||||
// Get the Debug object exposed from the debug context global object.
|
||||
Debug = debug.Debug
|
||||
|
||||
function f() {a=1;b=2};
|
||||
function g() {
|
||||
a=1;
|
||||
b=2;
|
||||
}
|
||||
|
||||
bp = Debug.setBreakPoint(f, 0, 0);
|
||||
assertEquals("() {[B0]a=1;b=2}", Debug.showBreakPoints(f));
|
||||
Debug.clearBreakPoint(bp);
|
||||
assertEquals("() {a=1;b=2}", Debug.showBreakPoints(f));
|
||||
bp1 = Debug.setBreakPoint(f, 0, 8);
|
||||
assertEquals("() {a=1;[B0]b=2}", Debug.showBreakPoints(f));
|
||||
bp2 = Debug.setBreakPoint(f, 0, 4);
|
||||
assertEquals("() {[B0]a=1;[B1]b=2}", Debug.showBreakPoints(f));
|
||||
bp3 = Debug.setBreakPoint(f, 0, 12);
|
||||
assertEquals("() {[B0]a=1;[B1]b=2}[B2]", Debug.showBreakPoints(f));
|
||||
Debug.clearBreakPoint(bp1);
|
||||
assertEquals("() {[B0]a=1;b=2}[B1]", Debug.showBreakPoints(f));
|
||||
Debug.clearBreakPoint(bp2);
|
||||
assertEquals("() {a=1;b=2}[B0]", Debug.showBreakPoints(f));
|
||||
Debug.clearBreakPoint(bp3);
|
||||
assertEquals("() {a=1;b=2}", Debug.showBreakPoints(f));
|
||||
|
||||
// The following test checks that the Debug.showBreakPoints(g) produces output
|
||||
// like follows when changein breakpoints.
|
||||
//
|
||||
// function g() {
|
||||
// [BX]a=1;
|
||||
// [BX]b=2;
|
||||
// }[BX]
|
||||
|
||||
// Test set and clear breakpoint at the first possible location (line 0,
|
||||
// position 0).
|
||||
bp = Debug.setBreakPoint(g, 0, 0);
|
||||
// function g() {
|
||||
// [B0]a=1;
|
||||
// b=2;
|
||||
// }
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
|
||||
Debug.clearBreakPoint(bp);
|
||||
// function g() {
|
||||
// a=1;
|
||||
// b=2;
|
||||
// }
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
|
||||
|
||||
// Second test set and clear breakpoints on lines 1, 2 and 3 (position = 0).
|
||||
bp1 = Debug.setBreakPoint(g, 2, 0);
|
||||
// function g() {
|
||||
// a=1;
|
||||
// [B0]b=2;
|
||||
// }
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]b=2;") > 0);
|
||||
bp2 = Debug.setBreakPoint(g, 1, 0);
|
||||
// function g() {
|
||||
// [B0]a=1;
|
||||
// [B1]b=2;
|
||||
// }
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B1]b=2;") > 0);
|
||||
bp3 = Debug.setBreakPoint(g, 3, 0);
|
||||
// function g() {
|
||||
// [B0]a=1;
|
||||
// [B1]b=2;
|
||||
// }[B2]
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B1]b=2;") > 0);
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("}[B2]") > 0);
|
||||
Debug.clearBreakPoint(bp1);
|
||||
// function g() {
|
||||
// [B0]a=1;
|
||||
// b=2;
|
||||
// }[B1]
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0);
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("}[B1]") > 0);
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B2]") < 0);
|
||||
Debug.clearBreakPoint(bp2);
|
||||
// function g() {
|
||||
// a=1;
|
||||
// b=2;
|
||||
// }[B0]
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("}[B0]") > 0);
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B1]") < 0);
|
||||
Debug.clearBreakPoint(bp3);
|
||||
// function g() {
|
||||
// a=1;
|
||||
// b=2;
|
||||
// }
|
||||
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user