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:
christian.plesner.hansen 2008-08-22 13:33:59 +00:00
parent 75bc1a2017
commit c42f5829a1
316 changed files with 48186 additions and 672 deletions

View File

@ -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()

View File

@ -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.
*/

View File

@ -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
View 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')

View File

@ -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>

View File

@ -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')

View File

@ -2098,7 +2098,7 @@ bool v8::V8::Initialize() {
const char* v8::V8::GetVersion() {
return "0.2.3";
return "0.2.4 (internal)";
}

View File

@ -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);
}

View File

@ -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_;

View File

@ -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);

View File

@ -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) \

View File

@ -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);

View File

@ -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);
}

View File

@ -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(),

View File

@ -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(),

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);

View File

@ -202,7 +202,7 @@ class RelocInfo;
class Deserializer;
class MessageLocation;
class ObjectGroup;
struct TickSample;
class TickSample;
class VirtualMemory;
class Mutex;

View File

@ -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.

View File

@ -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);
}

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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>

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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 ||

View File

@ -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;
};

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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++) {

View File

@ -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);

View File

@ -237,7 +237,7 @@ namespace v8 { namespace internal {
\
/* Literals */ \
F(MaterializeRegExpLiteral, 4)\
F(CreateArrayLiteral, 1) \
F(CreateArrayLiteral, 2) \
F(CreateObjectLiteralBoilerplate, 3) \
F(CloneObjectLiteralBoilerplate, 1) \
\

View File

@ -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;

View File

@ -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()) {

View File

@ -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;

View File

@ -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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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 __

View 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
View 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);
}
}

View 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);
}

View 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

File diff suppressed because it is too large Load Diff

594
test/cctest/test-decls.cc Normal file
View 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());
}
}

View 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();
}

View 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
View 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
View 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
View 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
View 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;
}

View 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);
}

View 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;
}

View 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;

View 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;
}

View 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;
}

View 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
View 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
View 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
View 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
View 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"]);

View 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");

View 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));

View 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);

View 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
View 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));

View 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());

View 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();

View 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);

View 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);
})();

View 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('*'));

View 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);

View 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();

View 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);

View 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;

View 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(); }};");

View 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");
}

View 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());

View 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);

View 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);

View 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
View 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));

View 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"));

View 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
View 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());
}

View 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);
}

View 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
View 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);
}

View 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
View 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
View 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()));

View 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")

View 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);

View 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