Browse Source

Merge branch 'V8-3.4'

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
fea524e145
  1. 39
      deps/v8/ChangeLog
  2. 14
      deps/v8/SConstruct
  3. 124
      deps/v8/include/v8.h
  4. 2
      deps/v8/preparser/preparser-process.cc
  5. 7
      deps/v8/samples/shell.cc
  6. 19
      deps/v8/src/SConscript
  7. 181
      deps/v8/src/api.cc
  8. 7
      deps/v8/src/arm/assembler-arm.cc
  9. 14
      deps/v8/src/arm/assembler-arm.h
  10. 1
      deps/v8/src/arm/code-stubs-arm.cc
  11. 35
      deps/v8/src/arm/lithium-arm.cc
  12. 40
      deps/v8/src/arm/lithium-arm.h
  13. 93
      deps/v8/src/arm/lithium-codegen-arm.cc
  14. 14
      deps/v8/src/arm/macro-assembler-arm.cc
  15. 190
      deps/v8/src/arm/stub-cache-arm.cc
  16. 6
      deps/v8/src/array.js
  17. 15
      deps/v8/src/assembler.cc
  18. 6
      deps/v8/src/assembler.h
  19. 56
      deps/v8/src/ast-inl.h
  20. 68
      deps/v8/src/ast.cc
  21. 213
      deps/v8/src/ast.h
  22. 1
      deps/v8/src/bootstrapper.cc
  23. 4
      deps/v8/src/builtins.cc
  24. 5
      deps/v8/src/code-stubs.cc
  25. 2
      deps/v8/src/compiler.cc
  26. 9
      deps/v8/src/compiler.h
  27. 2
      deps/v8/src/contexts.h
  28. 7
      deps/v8/src/conversions-inl.h
  29. 232
      deps/v8/src/d8.cc
  30. 27
      deps/v8/src/d8.gyp
  31. 111
      deps/v8/src/d8.h
  32. 14
      deps/v8/src/debug.cc
  33. 7
      deps/v8/src/factory.cc
  34. 3
      deps/v8/src/factory.h
  35. 1
      deps/v8/src/frames.cc
  36. 1
      deps/v8/src/full-codegen.cc
  37. 4
      deps/v8/src/globals.h
  38. 33
      deps/v8/src/heap.cc
  39. 5
      deps/v8/src/heap.h
  40. 22
      deps/v8/src/hydrogen-instructions.cc
  41. 101
      deps/v8/src/hydrogen-instructions.h
  42. 86
      deps/v8/src/hydrogen.cc
  43. 1
      deps/v8/src/ia32/code-stubs-ia32.cc
  44. 69
      deps/v8/src/ia32/lithium-codegen-ia32.cc
  45. 7
      deps/v8/src/ia32/lithium-codegen-ia32.h
  46. 35
      deps/v8/src/ia32/lithium-ia32.cc
  47. 41
      deps/v8/src/ia32/lithium-ia32.h
  48. 3
      deps/v8/src/ia32/macro-assembler-ia32.cc
  49. 157
      deps/v8/src/ia32/stub-cache-ia32.cc
  50. 8
      deps/v8/src/jsregexp.cc
  51. 19
      deps/v8/src/messages.js
  52. 7
      deps/v8/src/mips/assembler-mips.cc
  53. 14
      deps/v8/src/mips/assembler-mips.h
  54. 1
      deps/v8/src/mips/code-stubs-mips.cc
  55. 5
      deps/v8/src/mips/macro-assembler-mips.cc
  56. 189
      deps/v8/src/mips/stub-cache-mips.cc
  57. 41
      deps/v8/src/mirror-debugger.js
  58. 2
      deps/v8/src/natives.h
  59. 3
      deps/v8/src/objects-debug.cc
  60. 37
      deps/v8/src/objects-inl.h
  61. 255
      deps/v8/src/objects.cc
  62. 72
      deps/v8/src/objects.h
  63. 186
      deps/v8/src/parser.cc
  64. 5
      deps/v8/src/parser.h
  65. 1
      deps/v8/src/platform-linux.cc
  66. 5
      deps/v8/src/platform-nullos.cc
  67. 9
      deps/v8/src/platform-posix.cc
  68. 6
      deps/v8/src/platform-win32.cc
  69. 4
      deps/v8/src/platform.h
  70. 16
      deps/v8/src/rewriter.cc
  71. 273
      deps/v8/src/runtime.cc
  72. 7
      deps/v8/src/runtime.h
  73. 3
      deps/v8/src/runtime.js
  74. 89
      deps/v8/src/scopes.cc
  75. 6
      deps/v8/src/scopes.h
  76. 57
      deps/v8/src/spaces.cc
  77. 3
      deps/v8/src/spaces.h
  78. 5
      deps/v8/src/stub-cache.h
  79. 18
      deps/v8/src/v8.cc
  80. 3
      deps/v8/src/v8.h
  81. 10
      deps/v8/src/v8globals.h
  82. 43
      deps/v8/src/v8natives.js
  83. 4
      deps/v8/src/version.cc
  84. 2
      deps/v8/src/x64/assembler-x64.h
  85. 2
      deps/v8/src/x64/code-stubs-x64.cc
  86. 14
      deps/v8/src/x64/deoptimizer-x64.cc
  87. 2
      deps/v8/src/x64/full-codegen-x64.cc
  88. 66
      deps/v8/src/x64/lithium-codegen-x64.cc
  89. 5
      deps/v8/src/x64/lithium-codegen-x64.h
  90. 35
      deps/v8/src/x64/lithium-x64.cc
  91. 40
      deps/v8/src/x64/lithium-x64.h
  92. 3
      deps/v8/src/x64/macro-assembler-x64.cc
  93. 2
      deps/v8/src/x64/regexp-macro-assembler-x64.cc
  94. 140
      deps/v8/src/x64/stub-cache-x64.cc
  95. 2
      deps/v8/src/zone.h
  96. 24
      deps/v8/test/cctest/SConscript
  97. 41
      deps/v8/test/cctest/cctest.gyp
  98. 22
      deps/v8/test/cctest/log-eq-of-logging-and-traversal.js
  99. 110
      deps/v8/test/cctest/test-api.cc
  100. 2
      deps/v8/test/cctest/test-ast.cc

39
deps/v8/ChangeLog

@ -1,3 +1,42 @@
2011-07-20: Version 3.4.14
Fix the debugger for strict-mode functions. (Chromium issue 89236)
Add GetPropertyAttribute method for Object in the API. (Patch by Peter Varga)
Fix -Wunused-but-set-variable for gcc-4.6 on x64. (Issue 1291)
2011-07-18: Version 3.4.13
Improved debugger support to allow inspection of optimized frames (issue
1140).
Fixed a bug in prototype transitions cache clearing introduced by r8165.
Fixed shortcutting bug in HInferRepresentation. Patch by Andy Wingo.
Fixed a memory leak in sample/shell.cc (dispose semaphores).
Simplified HClampToUint8. Patch by Andy Wingo.
Exposed APIs for detecting boxed primitives, native errors. Patch by
Luke Zarko.
Added map check for COW elements to crankshaft array handling code
(issue 1560).
Sample shell and (a light version of) D8 links against a shared library
now.
Fixed bug in array filter and reduce functions (issue 1559).
Avoid TLS load in AstNode constructor.
Introduced a random entropy source which can optionally be provided at
initialization. (Chromium issue 89462).
2011-07-13: Version 3.4.12
Added --prof profiling option to d8 shell.

14
deps/v8/SConstruct

@ -404,6 +404,7 @@ CCTEST_EXTRA_FLAGS = {
},
'os:linux': {
'LIBS': ['pthread'],
'CCFLAGS': ['-Wno-unused-but-set-variable'],
},
'os:macos': {
'LIBS': ['pthread'],
@ -773,6 +774,13 @@ PREPARSER_FLAGS = {
D8_FLAGS = {
'all': {
'library:shared': {
'CPPDEFINES': ['V8_SHARED'],
'LIBS': ['v8'],
'LIBPATH': ['.']
},
},
'gcc': {
'all': {
'CCFLAGS': ['$DIALECTFLAGS', '$WARNINGFLAGS'],
@ -1370,7 +1378,11 @@ def BuildSpecific(env, mode, env_overrides, tools):
d8_env = Environment(tools=tools)
d8_env.Replace(**context.flags['d8'])
context.ApplyEnvOverrides(d8_env)
shell = d8_env.Program('d8' + suffix, object_files + shell_files)
if context.options['library'] == 'static':
shell = d8_env.Program('d8' + suffix, object_files + shell_files)
else:
shell = d8_env.Program('d8' + suffix, shell_files)
d8_env.Depends(shell, library)
context.d8_targets.append(shell)
for sample in context.samples:

124
deps/v8/include/v8.h

@ -80,9 +80,11 @@ namespace v8 {
class Context;
class String;
class StringObject;
class Value;
class Utils;
class Number;
class NumberObject;
class Object;
class Array;
class Int32;
@ -90,6 +92,7 @@ class Uint32;
class External;
class Primitive;
class Boolean;
class BooleanObject;
class Integer;
class Function;
class Date;
@ -928,6 +931,26 @@ class Value : public Data {
*/
V8EXPORT bool IsDate() const;
/**
* Returns true if this value is a Boolean object.
*/
V8EXPORT bool IsBooleanObject() const;
/**
* Returns true if this value is a Number object.
*/
V8EXPORT bool IsNumberObject() const;
/**
* Returns true if this value is a String object.
*/
V8EXPORT bool IsStringObject() const;
/**
* Returns true if this value is a NativeError.
*/
V8EXPORT bool IsNativeError() const;
/**
* Returns true if this value is a RegExp.
*/
@ -1435,6 +1458,13 @@ class Object : public Value {
V8EXPORT Local<Value> Get(uint32_t index);
/**
* Gets the property attributes of a property which can be None or
* any combination of ReadOnly, DontEnum and DontDelete. Returns
* None when the property doesn't exist.
*/
V8EXPORT PropertyAttribute GetPropertyAttributes(Handle<Value> key);
// TODO(1245389): Replace the type-specific versions of these
// functions with generic ones that accept a Handle<Value> key.
V8EXPORT bool Has(Handle<String> key);
@ -1744,6 +1774,63 @@ class Date : public Object {
};
/**
* A Number object (ECMA-262, 4.3.21).
*/
class NumberObject : public Object {
public:
V8EXPORT static Local<Value> New(double value);
/**
* Returns the Number held by the object.
*/
V8EXPORT double NumberValue() const;
static inline NumberObject* Cast(v8::Value* obj);
private:
V8EXPORT static void CheckCast(v8::Value* obj);
};
/**
* A Boolean object (ECMA-262, 4.3.15).
*/
class BooleanObject : public Object {
public:
V8EXPORT static Local<Value> New(bool value);
/**
* Returns the Boolean held by the object.
*/
V8EXPORT bool BooleanValue() const;
static inline BooleanObject* Cast(v8::Value* obj);
private:
V8EXPORT static void CheckCast(v8::Value* obj);
};
/**
* A String object (ECMA-262, 4.3.18).
*/
class StringObject : public Object {
public:
V8EXPORT static Local<Value> New(Handle<String> value);
/**
* Returns the String held by the object.
*/
V8EXPORT Local<String> StringValue() const;
static inline StringObject* Cast(v8::Value* obj);
private:
V8EXPORT static void CheckCast(v8::Value* obj);
};
/**
* An instance of the built-in RegExp constructor (ECMA-262, 15.10).
*/
@ -2721,6 +2808,13 @@ class V8EXPORT StartupDataDecompressor { // NOLINT
char** raw_data;
};
/**
* EntropySource is used as a callback function when v8 needs a source
* of entropy.
*/
typedef bool (*EntropySource)(unsigned char* buffer, size_t length);
/**
* Container class for static utility functions.
*/
@ -2945,6 +3039,12 @@ class V8EXPORT V8 {
*/
static bool Initialize();
/**
* Allows the host application to provide a callback which can be used
* as a source of entropy for random number generators.
*/
static void SetEntropySource(EntropySource source);
/**
* Adjusts the amount of registered external memory. Used to give
* V8 an indication of the amount of externally allocated memory
@ -4010,6 +4110,30 @@ Date* Date::Cast(v8::Value* value) {
}
StringObject* StringObject::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
#endif
return static_cast<StringObject*>(value);
}
NumberObject* NumberObject::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
#endif
return static_cast<NumberObject*>(value);
}
BooleanObject* BooleanObject::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);
#endif
return static_cast<BooleanObject*>(value);
}
RegExp* RegExp::Cast(v8::Value* value) {
#ifdef V8_ENABLE_CHECKS
CheckCast(value);

2
deps/v8/preparser/preparser-process.cc

@ -208,7 +208,7 @@ void fail(v8::PreParserData* data, const char* message, ...) {
fflush(stderr);
}
exit(EXIT_FAILURE);
};
}
bool IsFlag(const char* arg) {

7
deps/v8/samples/shell.cc

@ -95,6 +95,13 @@ class SourceGroup {
begin_offset_(0),
end_offset_(0) { }
#if !(defined(USING_V8_SHARED) || defined(V8_SHARED))
~SourceGroup() {
delete next_semaphore_;
delete done_semaphore_;
}
#endif // USING_V8_SHARED
void Begin(char** argv, int offset) {
argv_ = const_cast<const char**>(argv);
begin_offset_ = offset;

19
deps/v8/src/SConscript

@ -243,7 +243,14 @@ PREPARSER_SOURCES = {
}
D8_FILES = {
D8_LIGHT_FILES = {
'all': [
'd8.cc'
]
}
D8_FULL_FILES = {
'all': [
'd8.cc', 'd8-debug.cc'
],
@ -323,11 +330,15 @@ def ConfigureObjectFiles():
# Build the standard platform-independent source files.
source_files = context.GetRelevantSources(SOURCES)
d8_files = context.GetRelevantSources(D8_FILES)
d8_js = env.JS2C('d8-js.cc', 'd8.js', **{'TYPE': 'D8', 'COMPRESSION': 'off'})
d8_js_obj = context.ConfigureObject(env, d8_js, CPPPATH=['.'])
d8_objs = [context.ConfigureObject(env, [d8_files]), d8_js_obj]
if context.options['library'] == 'shared':
d8_files = context.GetRelevantSources(D8_LIGHT_FILES)
d8_objs = []
else:
d8_files = context.GetRelevantSources(D8_FULL_FILES)
d8_objs = [d8_js_obj]
d8_objs.append(context.ConfigureObject(env, [d8_files]))
# Combine the JavaScript library files into a single C++ file and
# compile it.

181
deps/v8/src/api.cc

@ -2167,6 +2167,65 @@ bool Value::IsDate() const {
}
bool Value::IsStringObject() const {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::Value::IsStringObject()")) return false;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
return obj->HasSpecificClassOf(isolate->heap()->String_symbol());
}
bool Value::IsNumberObject() const {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::Value::IsNumberObject()")) return false;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
return obj->HasSpecificClassOf(isolate->heap()->Number_symbol());
}
static i::Object* LookupBuiltin(i::Isolate* isolate,
const char* builtin_name) {
i::Handle<i::String> symbol =
isolate->factory()->LookupAsciiSymbol(builtin_name);
i::Handle<i::JSBuiltinsObject> builtins = isolate->js_builtins_object();
return builtins->GetPropertyNoExceptionThrown(*symbol);
}
static bool CheckConstructor(i::Isolate* isolate,
i::Handle<i::JSObject> obj,
const char* class_name) {
return obj->map()->constructor() == LookupBuiltin(isolate, class_name);
}
bool Value::IsNativeError() const {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::Value::IsNativeError()")) return false;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
if (obj->IsJSObject()) {
i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
return CheckConstructor(isolate, js_obj, "$Error") ||
CheckConstructor(isolate, js_obj, "$EvalError") ||
CheckConstructor(isolate, js_obj, "$RangeError") ||
CheckConstructor(isolate, js_obj, "$ReferenceError") ||
CheckConstructor(isolate, js_obj, "$SyntaxError") ||
CheckConstructor(isolate, js_obj, "$TypeError") ||
CheckConstructor(isolate, js_obj, "$URIError");
} else {
return false;
}
}
bool Value::IsBooleanObject() const {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::Value::IsBooleanObject()")) return false;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
return obj->HasSpecificClassOf(isolate->heap()->Boolean_symbol());
}
bool Value::IsRegExp() const {
if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsRegExp()")) return false;
i::Handle<i::Object> obj = Utils::OpenHandle(this);
@ -2362,6 +2421,36 @@ void v8::Date::CheckCast(v8::Value* that) {
}
void v8::StringObject::CheckCast(v8::Value* that) {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::StringObject::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_symbol()),
"v8::StringObject::Cast()",
"Could not convert to StringObject");
}
void v8::NumberObject::CheckCast(v8::Value* that) {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::NumberObject::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_symbol()),
"v8::NumberObject::Cast()",
"Could not convert to NumberObject");
}
void v8::BooleanObject::CheckCast(v8::Value* that) {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::BooleanObject::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_symbol()),
"v8::BooleanObject::Cast()",
"Could not convert to BooleanObject");
}
void v8::RegExp::CheckCast(v8::Value* that) {
if (IsDeadCheck(i::Isolate::Current(), "v8::RegExp::Cast()")) return;
i::Handle<i::Object> obj = Utils::OpenHandle(that);
@ -2705,6 +2794,26 @@ Local<Value> v8::Object::Get(uint32_t index) {
}
PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Object::GetPropertyAttribute()",
return static_cast<PropertyAttribute>(NONE));
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::JSObject> self = Utils::OpenHandle(this);
i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
if (!key_obj->IsString()) {
EXCEPTION_PREAMBLE(isolate);
key_obj = i::Execution::ToString(key_obj, &has_pending_exception);
EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
}
i::Handle<i::String> key_string = i::Handle<i::String>::cast(key_obj);
PropertyAttributes result = self->GetPropertyAttribute(*key_string);
if (result == ABSENT) return static_cast<PropertyAttribute>(NONE);
return static_cast<PropertyAttribute>(result);
}
Local<Value> v8::Object::GetPrototype() {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
ON_BAILOUT(isolate, "v8::Object::GetPrototype()",
@ -3844,6 +3953,11 @@ bool v8::V8::Initialize() {
}
void v8::V8::SetEntropySource(EntropySource source) {
i::V8::SetEntropySource(source);
}
bool v8::V8::Dispose() {
i::Isolate* isolate = i::Isolate::Current();
if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
@ -4427,6 +4541,73 @@ Local<v8::Object> v8::Object::New() {
}
Local<v8::Value> v8::NumberObject::New(double value) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::NumberObject::New()");
LOG_API(isolate, "NumberObject::New");
ENTER_V8(isolate);
i::Handle<i::Object> number = isolate->factory()->NewNumber(value);
i::Handle<i::Object> obj = isolate->factory()->ToObject(number);
return Utils::ToLocal(obj);
}
double v8::NumberObject::NumberValue() const {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::NumberObject::NumberValue()")) return 0;
LOG_API(isolate, "NumberObject::NumberValue");
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
return jsvalue->value()->Number();
}
Local<v8::Value> v8::BooleanObject::New(bool value) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::BooleanObject::New()");
LOG_API(isolate, "BooleanObject::New");
ENTER_V8(isolate);
i::Handle<i::Object> boolean(value ? isolate->heap()->true_value()
: isolate->heap()->false_value());
i::Handle<i::Object> obj = isolate->factory()->ToObject(boolean);
return Utils::ToLocal(obj);
}
bool v8::BooleanObject::BooleanValue() const {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::BooleanObject::BooleanValue()")) return 0;
LOG_API(isolate, "BooleanObject::BooleanValue");
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
return jsvalue->value()->IsTrue();
}
Local<v8::Value> v8::StringObject::New(Handle<String> value) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::StringObject::New()");
LOG_API(isolate, "StringObject::New");
ENTER_V8(isolate);
i::Handle<i::Object> obj =
isolate->factory()->ToObject(Utils::OpenHandle(*value));
return Utils::ToLocal(obj);
}
Local<v8::String> v8::StringObject::StringValue() const {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::StringObject::StringValue()")) {
return Local<v8::String>();
}
LOG_API(isolate, "StringObject::StringValue");
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
return Utils::ToLocal(
i::Handle<i::String>(i::String::cast(jsvalue->value())));
}
Local<v8::Value> v8::Date::New(double time) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::Date::New()");

7
deps/v8/src/arm/assembler-arm.cc

@ -326,7 +326,7 @@ Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
no_const_pool_before_ = 0;
first_const_pool_use_ = -1;
last_bound_pos_ = 0;
ast_id_for_reloc_info_ = kNoASTId;
ClearRecordedAstId();
}
@ -2537,9 +2537,8 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
}
ASSERT(buffer_space() >= kMaxRelocSize); // too late to grow buffer here
if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
ASSERT(ast_id_for_reloc_info_ != kNoASTId);
RelocInfo reloc_info_with_ast_id(pc_, rmode, ast_id_for_reloc_info_);
ast_id_for_reloc_info_ = kNoASTId;
RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId());
ClearRecordedAstId();
reloc_info_writer.Write(&reloc_info_with_ast_id);
} else {
reloc_info_writer.Write(&rinfo);

14
deps/v8/src/arm/assembler-arm.h

@ -1178,7 +1178,17 @@ class Assembler : public AssemblerBase {
// Record the AST id of the CallIC being compiled, so that it can be placed
// in the relocation information.
void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; }
void SetRecordedAstId(unsigned ast_id) {
ASSERT(recorded_ast_id_ == kNoASTId);
recorded_ast_id_ = ast_id;
}
unsigned RecordedAstId() {
ASSERT(recorded_ast_id_ != kNoASTId);
return recorded_ast_id_;
}
void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; }
// Record a comment relocation entry that can be used by a disassembler.
// Use --code-comments to enable.
@ -1244,7 +1254,7 @@ class Assembler : public AssemblerBase {
// Relocation for a type-recording IC has the AST id added to it. This
// member variable is a way to pass the information from the call site to
// the relocation info.
unsigned ast_id_for_reloc_info_;
unsigned recorded_ast_id_;
bool emit_debug_code() const { return emit_debug_code_; }

1
deps/v8/src/arm/code-stubs-arm.cc

@ -4722,6 +4722,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ mov(r0, Operand(argc_)); // Setup the number of arguments.
__ mov(r2, Operand(0, RelocInfo::NONE));
__ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
__ SetCallKind(r5, CALL_AS_METHOD);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET);
}

35
deps/v8/src/arm/lithium-arm.cc

@ -372,6 +372,15 @@ void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
}
void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
elements()->PrintTo(stream);
stream->Add("[");
key()->PrintTo(stream);
stream->Add("] <- ");
value()->PrintTo(stream);
}
void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add("[");
@ -1844,6 +1853,18 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
}
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
HLoadKeyedFastDoubleElement* instr) {
ASSERT(instr->representation().IsDouble());
ASSERT(instr->key()->representation().IsInteger32());
LOperand* elements = UseTempRegister(instr->elements());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result =
new LLoadKeyedFastDoubleElement(elements, key);
return AssignEnvironment(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
HLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
@ -1897,6 +1918,20 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
}
LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
HStoreKeyedFastDoubleElement* instr) {
ASSERT(instr->value()->representation().IsDouble());
ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32());
LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* val = UseTempRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
return new LStoreKeyedFastDoubleElement(elements, key, val);
}
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
HStoreKeyedSpecializedArrayElement* instr) {
Representation representation(instr->value()->representation());

40
deps/v8/src/arm/lithium-arm.h

@ -121,6 +121,7 @@ class LCodeGen;
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
V(LoadKeyedFastDoubleElement) \
V(LoadKeyedFastElement) \
V(LoadKeyedGeneric) \
V(LoadKeyedSpecializedArrayElement) \
@ -147,6 +148,7 @@ class LCodeGen;
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
V(StoreKeyedFastDoubleElement) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
V(StoreKeyedSpecializedArrayElement) \
@ -1137,6 +1139,22 @@ class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
};
class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
inputs_[0] = elements;
inputs_[1] = key;
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
"load-keyed-fast-double-element")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
};
class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
@ -1597,6 +1615,28 @@ class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
};
class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedFastDoubleElement(LOperand* elements,
LOperand* key,
LOperand* val) {
inputs_[0] = elements;
inputs_[1] = key;
inputs_[2] = val;
}
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
"store-keyed-fast-double-element")
DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
virtual void PrintDataTo(StringStream* stream);
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
};
class LStoreKeyedGeneric: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedGeneric(LOperand* obj, LOperand* key, LOperand* val) {

93
deps/v8/src/arm/lithium-codegen-arm.cc

@ -2433,6 +2433,48 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
}
void LCodeGen::DoLoadKeyedFastDoubleElement(
LLoadKeyedFastDoubleElement* instr) {
Register elements = ToRegister(instr->elements());
bool key_is_constant = instr->key()->IsConstantOperand();
Register key = no_reg;
DwVfpRegister result = ToDoubleRegister(instr->result());
Register scratch = scratch0();
int shift_size =
ElementsKindToShiftSize(JSObject::FAST_DOUBLE_ELEMENTS);
int constant_key = 0;
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
}
Operand operand = key_is_constant
? Operand(constant_key * (1 << shift_size) +
FixedDoubleArray::kHeaderSize - kHeapObjectTag)
: Operand(key, LSL, shift_size);
__ add(elements, elements, operand);
if (!key_is_constant) {
__ add(elements, elements,
Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
}
if (instr->hydrogen()->RequiresHoleCheck()) {
// TODO(danno): If no hole check is required, there is no need to allocate
// elements into a temporary register, instead scratch can be used.
__ ldr(scratch, MemOperand(elements, sizeof(kHoleNanLower32)));
__ cmp(scratch, Operand(kHoleNanUpper32));
DeoptimizeIf(eq, instr->environment());
}
__ vldr(result, elements, 0);
}
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
LLoadKeyedSpecializedArrayElement* instr) {
Register external_pointer = ToRegister(instr->external_pointer());
@ -2453,9 +2495,10 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
CpuFeatures::Scope scope(VFP3);
DwVfpRegister result(ToDoubleRegister(instr->result()));
Operand operand(key_is_constant ? Operand(constant_key * (1 << shift_size))
: Operand(key, LSL, shift_size));
DwVfpRegister result = ToDoubleRegister(instr->result());
Operand operand = key_is_constant
? Operand(constant_key * (1 << shift_size))
: Operand(key, LSL, shift_size);
__ add(scratch0(), external_pointer, operand);
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
__ vldr(result.low(), scratch0(), 0);
@ -2464,7 +2507,7 @@ void LCodeGen::DoLoadKeyedSpecializedArrayElement(
__ vldr(result, scratch0(), 0);
}
} else {
Register result(ToRegister(instr->result()));
Register result = ToRegister(instr->result());
MemOperand mem_operand(key_is_constant
? MemOperand(external_pointer, constant_key * (1 << shift_size))
: MemOperand(external_pointer, key, LSL, shift_size));
@ -3243,6 +3286,48 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
}
void LCodeGen::DoStoreKeyedFastDoubleElement(
LStoreKeyedFastDoubleElement* instr) {
DwVfpRegister value = ToDoubleRegister(instr->value());
Register elements = ToRegister(instr->elements());
Register key = no_reg;
Register scratch = scratch0();
bool key_is_constant = instr->key()->IsConstantOperand();
int constant_key = 0;
Label not_nan;
// Calculate the effective address of the slot in the array to store the
// double value.
if (key_is_constant) {
constant_key = ToInteger32(LConstantOperand::cast(instr->key()));
if (constant_key & 0xF0000000) {
Abort("array index constant value too big.");
}
} else {
key = ToRegister(instr->key());
}
int shift_size = ElementsKindToShiftSize(JSObject::FAST_DOUBLE_ELEMENTS);
Operand operand = key_is_constant
? Operand(constant_key * (1 << shift_size) +
FixedDoubleArray::kHeaderSize - kHeapObjectTag)
: Operand(key, LSL, shift_size);
__ add(scratch, elements, operand);
if (!key_is_constant) {
__ add(scratch, scratch,
Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
}
// Check for NaN. All NaNs must be canonicalized.
__ VFPCompareAndSetFlags(value, value);
// Only load canonical NaN if the comparison above set the overflow.
__ Vmov(value, FixedDoubleArray::canonical_not_the_hole_nan_as_double(), vs);
__ bind(&not_nan);
__ vstr(value, scratch, 0);
}
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
LStoreKeyedSpecializedArrayElement* instr) {

14
deps/v8/src/arm/macro-assembler-arm.cc

@ -192,13 +192,13 @@ void MacroAssembler::Call(Handle<Code> code,
bind(&start);
ASSERT(RelocInfo::IsCodeTarget(rmode));
if (rmode == RelocInfo::CODE_TARGET && ast_id != kNoASTId) {
ASSERT(ast_id_for_reloc_info_ == kNoASTId);
ast_id_for_reloc_info_ = ast_id;
SetRecordedAstId(ast_id);
rmode = RelocInfo::CODE_TARGET_WITH_ID;
}
// 'code' is always generated ARM code, never THUMB code
Call(reinterpret_cast<Address>(code.location()), rmode, cond);
ASSERT_EQ(CallSize(code, rmode, cond), SizeOfCodeGeneratedSince(&start));
ASSERT_EQ(CallSize(code, rmode, ast_id, cond),
SizeOfCodeGeneratedSince(&start));
}
@ -1862,7 +1862,7 @@ void MacroAssembler::TryGetFunctionPrototype(Register function,
void MacroAssembler::CallStub(CodeStub* stub, Condition cond) {
ASSERT(allow_stub_calls()); // Stub calls are not allowed in some stubs.
Call(stub->GetCode(), RelocInfo::CODE_TARGET, cond);
Call(stub->GetCode(), RelocInfo::CODE_TARGET, kNoASTId, cond);
}
@ -1872,7 +1872,8 @@ MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub, Condition cond) {
{ MaybeObject* maybe_result = stub->TryGetCode();
if (!maybe_result->ToObject(&result)) return maybe_result;
}
Call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET, cond);
Handle<Code> code(Code::cast(result));
Call(code, RelocInfo::CODE_TARGET, kNoASTId, cond);
return result;
}
@ -2548,6 +2549,9 @@ void MacroAssembler::AssertFastElements(Register elements) {
LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
cmp(elements, ip);
b(eq, &ok);
LoadRoot(ip, Heap::kFixedDoubleArrayMapRootIndex);
cmp(elements, ip);
b(eq, &ok);
LoadRoot(ip, Heap::kFixedCOWArrayMapRootIndex);
cmp(elements, ip);
b(eq, &ok);

190
deps/v8/src/arm/stub-cache-arm.cc

@ -4168,6 +4168,77 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
}
void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- lr : return address
// -- r0 : key
// -- r1 : receiver
// -----------------------------------
Label miss_force_generic, slow_allocate_heapnumber;
Register key_reg = r0;
Register receiver_reg = r1;
Register elements_reg = r2;
Register heap_number_reg = r2;
Register indexed_double_offset = r3;
Register scratch = r4;
Register scratch2 = r5;
Register scratch3 = r6;
Register heap_number_map = r7;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
// Check that the key is a smi.
__ JumpIfNotSmi(key_reg, &miss_force_generic);
// Get the elements array.
__ ldr(elements_reg,
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
// Check that the key is within bounds.
__ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
__ cmp(key_reg, Operand(scratch));
__ b(hs, &miss_force_generic);
// Load the upper word of the double in the fixed array and test for NaN.
__ add(indexed_double_offset, elements_reg,
Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
__ ldr(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
__ cmp(scratch, Operand(kHoleNanUpper32));
__ b(&miss_force_generic, eq);
// Non-NaN. Allocate a new heap number and copy the double value into it.
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
__ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
heap_number_map, &slow_allocate_heapnumber);
// Don't need to reload the upper 32 bits of the double, it's already in
// scratch.
__ str(scratch, FieldMemOperand(heap_number_reg,
HeapNumber::kExponentOffset));
__ ldr(scratch, FieldMemOperand(indexed_double_offset,
FixedArray::kHeaderSize));
__ str(scratch, FieldMemOperand(heap_number_reg,
HeapNumber::kMantissaOffset));
__ mov(r0, heap_number_reg);
__ Ret();
__ bind(&slow_allocate_heapnumber);
Handle<Code> slow_ic =
masm->isolate()->builtins()->KeyedLoadIC_Slow();
__ Jump(slow_ic, RelocInfo::CODE_TARGET);
__ bind(&miss_force_generic);
Handle<Code> miss_ic =
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
__ Jump(miss_ic, RelocInfo::CODE_TARGET);
}
void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
@ -4231,6 +4302,125 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
}
void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
// -- r0 : value
// -- r1 : key
// -- r2 : receiver
// -- lr : return address
// -- r3 : scratch
// -- r4 : scratch
// -- r5 : scratch
// -----------------------------------
Label miss_force_generic, smi_value, is_nan, maybe_nan, have_double_value;
Register value_reg = r0;
Register key_reg = r1;
Register receiver_reg = r2;
Register scratch = r3;
Register elements_reg = r4;
Register mantissa_reg = r5;
Register exponent_reg = r6;
Register scratch4 = r7;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
__ JumpIfNotSmi(key_reg, &miss_force_generic);
__ ldr(elements_reg,
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
// Check that the key is within bounds.
if (is_js_array) {
__ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
} else {
__ ldr(scratch,
FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
}
// Compare smis, unsigned compare catches both negative and out-of-bound
// indexes.
__ cmp(key_reg, scratch);
__ b(hs, &miss_force_generic);
// Handle smi values specially.
__ JumpIfSmi(value_reg, &smi_value);
// Ensure that the object is a heap number
__ CheckMap(value_reg,
scratch,
masm->isolate()->factory()->heap_number_map(),
&miss_force_generic,
DONT_DO_SMI_CHECK);
// Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
// in the exponent.
__ mov(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
__ ldr(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
__ cmp(exponent_reg, scratch);
__ b(ge, &maybe_nan);
__ ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
__ bind(&have_double_value);
__ add(scratch, elements_reg,
Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
__ str(mantissa_reg, FieldMemOperand(scratch, FixedDoubleArray::kHeaderSize));
uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
__ str(exponent_reg, FieldMemOperand(scratch, offset));
__ Ret();
__ bind(&maybe_nan);
// Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
// it's an Infinity, and the non-NaN code path applies.
__ b(gt, &is_nan);
__ ldr(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
__ cmp(mantissa_reg, Operand(0));
__ b(eq, &have_double_value);
__ bind(&is_nan);
// Load canonical NaN for storing into the double array.
uint64_t nan_int64 = BitCast<uint64_t>(
FixedDoubleArray::canonical_not_the_hole_nan_as_double());
__ mov(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
__ mov(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
__ jmp(&have_double_value);
__ bind(&smi_value);
__ add(scratch, elements_reg,
Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
__ add(scratch, scratch,
Operand(key_reg, LSL, kDoubleSizeLog2 - kSmiTagSize));
// scratch is now effective address of the double element
FloatingPointHelper::Destination destination;
if (CpuFeatures::IsSupported(VFP3)) {
destination = FloatingPointHelper::kVFPRegisters;
} else {
destination = FloatingPointHelper::kCoreRegisters;
}
__ SmiUntag(value_reg, value_reg);
FloatingPointHelper::ConvertIntToDouble(
masm, value_reg, destination,
d0, mantissa_reg, exponent_reg, // These are: double_dst, dst1, dst2.
scratch4, s2); // These are: scratch2, single_scratch.
if (destination == FloatingPointHelper::kVFPRegisters) {
CpuFeatures::Scope scope(VFP3);
__ vstr(d0, scratch, 0);
} else {
__ str(mantissa_reg, MemOperand(scratch, 0));
__ str(exponent_reg, MemOperand(scratch, Register::kSizeInBytes));
}
__ Ret();
// Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic);
Handle<Code> ic =
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ Jump(ic, RelocInfo::CODE_TARGET);
}
#undef __
} } // namespace v8::internal

6
deps/v8/src/array.js

@ -999,7 +999,7 @@ function ArrayFilter(f, receiver) {
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
var length = this.length;
var length = ToUint32(this.length);
var result = [];
var result_length = 0;
for (var i = 0; i < length; i++) {
@ -1236,7 +1236,7 @@ function ArrayReduce(callback, current) {
}
// Pull out the length so that modifications to the length in the
// loop will not affect the looping.
var length = this.length;
var length = ToUint32(this.length);
var i = 0;
find_initial: if (%_ArgumentsLength() < 2) {
@ -1268,7 +1268,7 @@ function ArrayReduceRight(callback, current) {
if (!IS_FUNCTION(callback)) {
throw MakeTypeError('called_non_callable', [callback]);
}
var i = this.length - 1;
var i = ToUint32(this.length) - 1;
find_initial: if (%_ArgumentsLength() < 2) {
for (; i >= 0; i--) {

15
deps/v8/src/assembler.cc

@ -1,4 +1,4 @@
// Copyright (c) 1994-2006 Sun Microsystems Inc.
// Copyright (c) 2011 Sun Microsystems Inc.
// All Rights Reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -71,7 +71,8 @@ const double DoubleConstant::one_half = 0.5;
const double DoubleConstant::minus_zero = -0.0;
const double DoubleConstant::uint8_max_value = 255;
const double DoubleConstant::zero = 0.0;
const double DoubleConstant::nan = OS::nan_value();
const double DoubleConstant::canonical_non_hole_nan = OS::nan_value();
const double DoubleConstant::the_hole_nan = BitCast<double>(kHoleNanInt64);
const double DoubleConstant::negative_infinity = -V8_INFINITY;
const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
@ -921,9 +922,15 @@ ExternalReference ExternalReference::address_of_negative_infinity() {
}
ExternalReference ExternalReference::address_of_nan() {
ExternalReference ExternalReference::address_of_canonical_non_hole_nan() {
return ExternalReference(reinterpret_cast<void*>(
const_cast<double*>(&DoubleConstant::nan)));
const_cast<double*>(&DoubleConstant::canonical_non_hole_nan)));
}
ExternalReference ExternalReference::address_of_the_hole_nan() {
return ExternalReference(reinterpret_cast<void*>(
const_cast<double*>(&DoubleConstant::the_hole_nan)));
}

6
deps/v8/src/assembler.h

@ -70,7 +70,8 @@ class DoubleConstant: public AllStatic {
static const double zero;
static const double uint8_max_value;
static const double negative_infinity;
static const double nan;
static const double canonical_non_hole_nan;
static const double the_hole_nan;
};
@ -629,7 +630,8 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference address_of_zero();
static ExternalReference address_of_uint8_max_value();
static ExternalReference address_of_negative_infinity();
static ExternalReference address_of_nan();
static ExternalReference address_of_canonical_non_hole_nan();
static ExternalReference address_of_the_hole_nan();
static ExternalReference math_sin_double_function(Isolate* isolate);
static ExternalReference math_cos_double_function(Isolate* isolate);

56
deps/v8/src/ast-inl.h

@ -37,68 +37,76 @@ namespace v8 {
namespace internal {
SwitchStatement::SwitchStatement(ZoneStringList* labels)
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
SwitchStatement::SwitchStatement(Isolate* isolate,
ZoneStringList* labels)
: BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
tag_(NULL), cases_(NULL) {
}
Block::Block(ZoneStringList* labels, int capacity, bool is_initializer_block)
: BreakableStatement(labels, TARGET_FOR_NAMED_ONLY),
Block::Block(Isolate* isolate,
ZoneStringList* labels,
int capacity,
bool is_initializer_block)
: BreakableStatement(isolate, labels, TARGET_FOR_NAMED_ONLY),
statements_(capacity),
is_initializer_block_(is_initializer_block) {
}
BreakableStatement::BreakableStatement(ZoneStringList* labels, Type type)
BreakableStatement::BreakableStatement(Isolate* isolate,
ZoneStringList* labels,
Type type)
: labels_(labels),
type_(type),
entry_id_(GetNextId()),
exit_id_(GetNextId()) {
entry_id_(GetNextId(isolate)),
exit_id_(GetNextId(isolate)) {
ASSERT(labels == NULL || labels->length() > 0);
}
IterationStatement::IterationStatement(ZoneStringList* labels)
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS),
IterationStatement::IterationStatement(Isolate* isolate, ZoneStringList* labels)
: BreakableStatement(isolate, labels, TARGET_FOR_ANONYMOUS),
body_(NULL),
continue_target_(),
osr_entry_id_(GetNextId()) {
osr_entry_id_(GetNextId(isolate)) {
}
DoWhileStatement::DoWhileStatement(ZoneStringList* labels)
: IterationStatement(labels),
DoWhileStatement::DoWhileStatement(Isolate* isolate, ZoneStringList* labels)
: IterationStatement(isolate, labels),
cond_(NULL),
condition_position_(-1),
continue_id_(GetNextId()),
back_edge_id_(GetNextId()) {
continue_id_(GetNextId(isolate)),
back_edge_id_(GetNextId(isolate)) {
}
WhileStatement::WhileStatement(ZoneStringList* labels)
: IterationStatement(labels),
WhileStatement::WhileStatement(Isolate* isolate, ZoneStringList* labels)
: IterationStatement(isolate, labels),
cond_(NULL),
may_have_function_literal_(true),
body_id_(GetNextId()) {
body_id_(GetNextId(isolate)) {
}
ForStatement::ForStatement(ZoneStringList* labels)
: IterationStatement(labels),
ForStatement::ForStatement(Isolate* isolate, ZoneStringList* labels)
: IterationStatement(isolate, labels),
init_(NULL),
cond_(NULL),
next_(NULL),
may_have_function_literal_(true),
loop_variable_(NULL),
continue_id_(GetNextId()),
body_id_(GetNextId()) {
continue_id_(GetNextId(isolate)),
body_id_(GetNextId(isolate)) {
}
ForInStatement::ForInStatement(ZoneStringList* labels)
: IterationStatement(labels), each_(NULL), enumerable_(NULL),
assignment_id_(GetNextId()) {
ForInStatement::ForInStatement(Isolate* isolate, ZoneStringList* labels)
: IterationStatement(isolate, labels),
each_(NULL),
enumerable_(NULL),
assignment_id_(GetNextId(isolate)) {
}

68
deps/v8/src/ast.cc

@ -37,11 +37,11 @@ namespace v8 {
namespace internal {
AstSentinels::AstSentinels()
: this_proxy_(true),
identifier_proxy_(false),
valid_left_hand_side_sentinel_(),
this_property_(&this_proxy_, NULL, 0),
call_sentinel_(NULL, NULL, 0) {
: this_proxy_(Isolate::Current(), true),
identifier_proxy_(Isolate::Current(), false),
valid_left_hand_side_sentinel_(Isolate::Current()),
this_property_(Isolate::Current(), &this_proxy_, NULL, 0),
call_sentinel_(Isolate::Current(), NULL, NULL, 0) {
}
@ -72,8 +72,9 @@ CountOperation* ExpressionStatement::StatementAsCountOperation() {
}
VariableProxy::VariableProxy(Variable* var)
: name_(var->name()),
VariableProxy::VariableProxy(Isolate* isolate, Variable* var)
: Expression(isolate),
name_(var->name()),
var_(NULL), // Will be set by the call to BindTo.
is_this_(var->is_this()),
inside_with_(false),
@ -83,26 +84,29 @@ VariableProxy::VariableProxy(Variable* var)
}
VariableProxy::VariableProxy(Handle<String> name,
VariableProxy::VariableProxy(Isolate* isolate,
Handle<String> name,
bool is_this,
bool inside_with,
int position)
: name_(name),
var_(NULL),
is_this_(is_this),
inside_with_(inside_with),
is_trivial_(false),
position_(position) {
: Expression(isolate),
name_(name),
var_(NULL),
is_this_(is_this),
inside_with_(inside_with),
is_trivial_(false),
position_(position) {
// Names must be canonicalized for fast equality checks.
ASSERT(name->IsSymbol());
}
VariableProxy::VariableProxy(bool is_this)
: var_(NULL),
is_this_(is_this),
inside_with_(false),
is_trivial_(false) {
VariableProxy::VariableProxy(Isolate* isolate, bool is_this)
: Expression(isolate),
var_(NULL),
is_this_(is_this),
inside_with_(false),
is_trivial_(false) {
}
@ -120,17 +124,19 @@ void VariableProxy::BindTo(Variable* var) {
}
Assignment::Assignment(Token::Value op,
Assignment::Assignment(Isolate* isolate,
Token::Value op,
Expression* target,
Expression* value,
int pos)
: op_(op),
: Expression(isolate),
op_(op),
target_(target),
value_(value),
pos_(pos),
binary_operation_(NULL),
compound_load_id_(kNoNumber),
assignment_id_(GetNextId()),
assignment_id_(GetNextId(isolate)),
block_start_(false),
block_end_(false),
is_monomorphic_(false),
@ -138,8 +144,12 @@ Assignment::Assignment(Token::Value op,
ASSERT(Token::IsAssignmentOp(op));
if (is_compound()) {
binary_operation_ =
new BinaryOperation(binary_op(), target, value, pos + 1);
compound_load_id_ = GetNextId();
new(isolate->zone()) BinaryOperation(isolate,
binary_op(),
target,
value,
pos + 1);
compound_load_id_ = GetNextId(isolate);
}
}
@ -186,8 +196,9 @@ ObjectLiteral::Property::Property(Literal* key, Expression* value) {
ObjectLiteral::Property::Property(bool is_getter, FunctionLiteral* value) {
Isolate* isolate = Isolate::Current();
emit_store_ = true;
key_ = new Literal(value->name());
key_ = new(isolate->zone()) Literal(isolate, value->name());
value_ = value;
kind_ = is_getter ? GETTER : SETTER;
}
@ -1190,15 +1201,16 @@ RegExpAlternative::RegExpAlternative(ZoneList<RegExpTree*>* nodes)
}
CaseClause::CaseClause(Expression* label,
CaseClause::CaseClause(Isolate* isolate,
Expression* label,
ZoneList<Statement*>* statements,
int pos)
: label_(label),
statements_(statements),
position_(pos),
compare_type_(NONE),
compare_id_(AstNode::GetNextId()),
entry_id_(AstNode::GetNextId()) {
compare_id_(AstNode::GetNextId(isolate)),
entry_id_(AstNode::GetNextId(isolate)) {
}
} } // namespace v8::internal

213
deps/v8/src/ast.h

@ -134,11 +134,15 @@ class AstNode: public ZoneObject {
static const int kNoNumber = -1;
static const int kFunctionEntryId = 2; // Using 0 could disguise errors.
AstNode() {
Isolate* isolate = Isolate::Current();
// Override ZoneObject's new to count allocated AST nodes.
void* operator new(size_t size, Zone* zone) {
Isolate* isolate = zone->isolate();
isolate->set_ast_node_count(isolate->ast_node_count() + 1);
return zone->New(static_cast<int>(size));
}
AstNode() {}
virtual ~AstNode() { }
virtual void Accept(AstVisitor* v) = 0;
@ -165,14 +169,21 @@ class AstNode: public ZoneObject {
static void ResetIds() { Isolate::Current()->set_ast_node_id(0); }
protected:
static unsigned GetNextId() { return ReserveIdRange(1); }
static unsigned ReserveIdRange(int n) {
Isolate* isolate = Isolate::Current();
static unsigned GetNextId(Isolate* isolate) {
return ReserveIdRange(isolate, 1);
}
static unsigned ReserveIdRange(Isolate* isolate, int n) {
unsigned tmp = isolate->ast_node_id();
isolate->set_ast_node_id(tmp + n);
return tmp;
}
private:
// Hidden to prevent accidental usage. It would have to load the
// current zone from the TLS.
void* operator new(size_t size);
friend class CaseClause; // Generates AST IDs.
};
@ -210,7 +221,9 @@ class Expression: public AstNode {
kTest
};
Expression() : id_(GetNextId()), test_id_(GetNextId()) {}
explicit Expression(Isolate* isolate)
: id_(GetNextId(isolate)),
test_id_(GetNextId(isolate)) {}
virtual int position() const {
UNREACHABLE();
@ -277,6 +290,7 @@ class Expression: public AstNode {
*/
class ValidLeftHandSideSentinel: public Expression {
public:
explicit ValidLeftHandSideSentinel(Isolate* isolate) : Expression(isolate) {}
virtual bool IsValidLeftHandSide() { return true; }
virtual void Accept(AstVisitor* v) { UNREACHABLE(); }
virtual bool IsInlineable() const;
@ -308,7 +322,7 @@ class BreakableStatement: public Statement {
int ExitId() const { return exit_id_; }
protected:
inline BreakableStatement(ZoneStringList* labels, Type type);
BreakableStatement(Isolate* isolate, ZoneStringList* labels, Type type);
private:
ZoneStringList* labels_;
@ -321,7 +335,10 @@ class BreakableStatement: public Statement {
class Block: public BreakableStatement {
public:
inline Block(ZoneStringList* labels, int capacity, bool is_initializer_block);
inline Block(Isolate* isolate,
ZoneStringList* labels,
int capacity,
bool is_initializer_block);
DECLARE_NODE_TYPE(Block)
@ -389,7 +406,7 @@ class IterationStatement: public BreakableStatement {
Label* continue_target() { return &continue_target_; }
protected:
explicit inline IterationStatement(ZoneStringList* labels);
inline IterationStatement(Isolate* isolate, ZoneStringList* labels);
void Initialize(Statement* body) {
body_ = body;
@ -404,7 +421,7 @@ class IterationStatement: public BreakableStatement {
class DoWhileStatement: public IterationStatement {
public:
explicit inline DoWhileStatement(ZoneStringList* labels);
inline DoWhileStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(DoWhileStatement)
@ -437,7 +454,7 @@ class DoWhileStatement: public IterationStatement {
class WhileStatement: public IterationStatement {
public:
explicit inline WhileStatement(ZoneStringList* labels);
inline WhileStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(WhileStatement)
@ -470,7 +487,7 @@ class WhileStatement: public IterationStatement {
class ForStatement: public IterationStatement {
public:
explicit inline ForStatement(ZoneStringList* labels);
inline ForStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(ForStatement)
@ -519,7 +536,7 @@ class ForStatement: public IterationStatement {
class ForInStatement: public IterationStatement {
public:
explicit inline ForInStatement(ZoneStringList* labels);
inline ForInStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(ForInStatement)
@ -636,7 +653,10 @@ class ExitContextStatement: public Statement {
class CaseClause: public ZoneObject {
public:
CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos);
CaseClause(Isolate* isolate,
Expression* label,
ZoneList<Statement*>* statements,
int pos);
bool is_default() const { return label_ == NULL; }
Expression* label() const {
@ -671,7 +691,7 @@ class CaseClause: public ZoneObject {
class SwitchStatement: public BreakableStatement {
public:
explicit inline SwitchStatement(ZoneStringList* labels);
inline SwitchStatement(Isolate* isolate, ZoneStringList* labels);
DECLARE_NODE_TYPE(SwitchStatement)
@ -697,15 +717,16 @@ class SwitchStatement: public BreakableStatement {
// given if-statement has a then- or an else-part containing code.
class IfStatement: public Statement {
public:
IfStatement(Expression* condition,
IfStatement(Isolate* isolate,
Expression* condition,
Statement* then_statement,
Statement* else_statement)
: condition_(condition),
then_statement_(then_statement),
else_statement_(else_statement),
if_id_(GetNextId()),
then_id_(GetNextId()),
else_id_(GetNextId()) {
if_id_(GetNextId(isolate)),
then_id_(GetNextId(isolate)),
else_id_(GetNextId(isolate)) {
}
DECLARE_NODE_TYPE(IfStatement)
@ -834,7 +855,8 @@ class EmptyStatement: public Statement {
class Literal: public Expression {
public:
explicit Literal(Handle<Object> handle) : handle_(handle) { }
Literal(Isolate* isolate, Handle<Object> handle)
: Expression(isolate), handle_(handle) { }
DECLARE_NODE_TYPE(Literal)
@ -887,8 +909,14 @@ class Literal: public Expression {
// Base class for literals that needs space in the corresponding JSFunction.
class MaterializedLiteral: public Expression {
public:
explicit MaterializedLiteral(int literal_index, bool is_simple, int depth)
: literal_index_(literal_index), is_simple_(is_simple), depth_(depth) {}
MaterializedLiteral(Isolate* isolate,
int literal_index,
bool is_simple,
int depth)
: Expression(isolate),
literal_index_(literal_index),
is_simple_(is_simple),
depth_(depth) {}
virtual MaterializedLiteral* AsMaterializedLiteral() { return this; }
@ -944,14 +972,15 @@ class ObjectLiteral: public MaterializedLiteral {
bool emit_store_;
};
ObjectLiteral(Handle<FixedArray> constant_properties,
ObjectLiteral(Isolate* isolate,
Handle<FixedArray> constant_properties,
ZoneList<Property*>* properties,
int literal_index,
bool is_simple,
bool fast_elements,
int depth,
bool has_function)
: MaterializedLiteral(literal_index, is_simple, depth),
: MaterializedLiteral(isolate, literal_index, is_simple, depth),
constant_properties_(constant_properties),
properties_(properties),
fast_elements_(fast_elements),
@ -990,10 +1019,11 @@ class ObjectLiteral: public MaterializedLiteral {
// Node for capturing a regexp literal.
class RegExpLiteral: public MaterializedLiteral {
public:
RegExpLiteral(Handle<String> pattern,
RegExpLiteral(Isolate* isolate,
Handle<String> pattern,
Handle<String> flags,
int literal_index)
: MaterializedLiteral(literal_index, false, 1),
: MaterializedLiteral(isolate, literal_index, false, 1),
pattern_(pattern),
flags_(flags) {}
@ -1011,15 +1041,16 @@ class RegExpLiteral: public MaterializedLiteral {
// for minimizing the work when constructing it at runtime.
class ArrayLiteral: public MaterializedLiteral {
public:
ArrayLiteral(Handle<FixedArray> constant_elements,
ArrayLiteral(Isolate* isolate,
Handle<FixedArray> constant_elements,
ZoneList<Expression*>* values,
int literal_index,
bool is_simple,
int depth)
: MaterializedLiteral(literal_index, is_simple, depth),
: MaterializedLiteral(isolate, literal_index, is_simple, depth),
constant_elements_(constant_elements),
values_(values),
first_element_id_(ReserveIdRange(values->length())) {}
first_element_id_(ReserveIdRange(isolate, values->length())) {}
DECLARE_NODE_TYPE(ArrayLiteral)
@ -1038,7 +1069,7 @@ class ArrayLiteral: public MaterializedLiteral {
class VariableProxy: public Expression {
public:
explicit VariableProxy(Variable* var);
VariableProxy(Isolate* isolate, Variable* var);
DECLARE_NODE_TYPE(VariableProxy)
@ -1085,11 +1116,12 @@ class VariableProxy: public Expression {
bool is_trivial_;
int position_;
VariableProxy(Handle<String> name,
VariableProxy(Isolate* isolate,
Handle<String> name,
bool is_this,
bool inside_with,
int position = RelocInfo::kNoPosition);
explicit VariableProxy(bool is_this);
VariableProxy(Isolate* isolate, bool is_this);
friend class Scope;
};
@ -1100,7 +1132,8 @@ class VariableProxySentinel: public VariableProxy {
virtual bool IsValidLeftHandSide() { return !is_this(); }
private:
explicit VariableProxySentinel(bool is_this) : VariableProxy(is_this) { }
VariableProxySentinel(Isolate* isolate, bool is_this)
: VariableProxy(isolate, is_this) { }
friend class AstSentinels;
};
@ -1130,8 +1163,8 @@ class Slot: public Expression {
LOOKUP
};
Slot(Variable* var, Type type, int index)
: var_(var), type_(type), index_(index) {
Slot(Isolate* isolate, Variable* var, Type type, int index)
: Expression(isolate), var_(var), type_(type), index_(index) {
ASSERT(var != NULL);
}
@ -1162,8 +1195,13 @@ class Property: public Expression {
// properties should use the global object as receiver, not the base object
// of the resolved Reference.
enum Type { NORMAL, SYNTHETIC };
Property(Expression* obj, Expression* key, int pos, Type type = NORMAL)
: obj_(obj),
Property(Isolate* isolate,
Expression* obj,
Expression* key,
int pos,
Type type = NORMAL)
: Expression(isolate),
obj_(obj),
key_(key),
pos_(pos),
type_(type),
@ -1215,14 +1253,18 @@ class Property: public Expression {
class Call: public Expression {
public:
Call(Expression* expression, ZoneList<Expression*>* arguments, int pos)
: expression_(expression),
Call(Isolate* isolate,
Expression* expression,
ZoneList<Expression*>* arguments,
int pos)
: Expression(isolate),
expression_(expression),
arguments_(arguments),
pos_(pos),
is_monomorphic_(false),
check_type_(RECEIVER_MAP_CHECK),
receiver_types_(NULL),
return_id_(GetNextId()) {
return_id_(GetNextId(isolate)) {
}
DECLARE_NODE_TYPE(Call)
@ -1301,8 +1343,14 @@ class AstSentinels {
class CallNew: public Expression {
public:
CallNew(Expression* expression, ZoneList<Expression*>* arguments, int pos)
: expression_(expression), arguments_(arguments), pos_(pos) { }
CallNew(Isolate* isolate,
Expression* expression,
ZoneList<Expression*>* arguments,
int pos)
: Expression(isolate),
expression_(expression),
arguments_(arguments),
pos_(pos) { }
DECLARE_NODE_TYPE(CallNew)
@ -1325,10 +1373,14 @@ class CallNew: public Expression {
// implemented in JavaScript (see "v8natives.js").
class CallRuntime: public Expression {
public:
CallRuntime(Handle<String> name,
CallRuntime(Isolate* isolate,
Handle<String> name,
const Runtime::Function* function,
ZoneList<Expression*>* arguments)
: name_(name), function_(function), arguments_(arguments) { }
: Expression(isolate),
name_(name),
function_(function),
arguments_(arguments) { }
DECLARE_NODE_TYPE(CallRuntime)
@ -1348,8 +1400,11 @@ class CallRuntime: public Expression {
class UnaryOperation: public Expression {
public:
UnaryOperation(Token::Value op, Expression* expression, int pos)
: op_(op), expression_(expression), pos_(pos) {
UnaryOperation(Isolate* isolate,
Token::Value op,
Expression* expression,
int pos)
: Expression(isolate), op_(op), expression_(expression), pos_(pos) {
ASSERT(Token::IsUnaryOp(op));
}
@ -1372,14 +1427,15 @@ class UnaryOperation: public Expression {
class BinaryOperation: public Expression {
public:
BinaryOperation(Token::Value op,
BinaryOperation(Isolate* isolate,
Token::Value op,
Expression* left,
Expression* right,
int pos)
: op_(op), left_(left), right_(right), pos_(pos) {
: Expression(isolate), op_(op), left_(left), right_(right), pos_(pos) {
ASSERT(Token::IsBinaryOp(op));
right_id_ = (op == Token::AND || op == Token::OR)
? static_cast<int>(GetNextId())
? static_cast<int>(GetNextId(isolate))
: AstNode::kNoNumber;
}
@ -1410,13 +1466,18 @@ class BinaryOperation: public Expression {
class CountOperation: public Expression {
public:
CountOperation(Token::Value op, bool is_prefix, Expression* expr, int pos)
: op_(op),
CountOperation(Isolate* isolate,
Token::Value op,
bool is_prefix,
Expression* expr,
int pos)
: Expression(isolate),
op_(op),
is_prefix_(is_prefix),
expression_(expr),
pos_(pos),
assignment_id_(GetNextId()),
count_id_(GetNextId()),
assignment_id_(GetNextId(isolate)),
count_id_(GetNextId(isolate)),
receiver_types_(NULL) { }
DECLARE_NODE_TYPE(CountOperation)
@ -1462,11 +1523,17 @@ class CountOperation: public Expression {
class CompareOperation: public Expression {
public:
CompareOperation(Token::Value op,
CompareOperation(Isolate* isolate,
Token::Value op,
Expression* left,
Expression* right,
int pos)
: op_(op), left_(left), right_(right), pos_(pos), compare_type_(NONE) {
: Expression(isolate),
op_(op),
left_(left),
right_(right),
pos_(pos),
compare_type_(NONE) {
ASSERT(Token::IsCompareOp(op));
}
@ -1501,8 +1568,8 @@ class CompareOperation: public Expression {
class CompareToNull: public Expression {
public:
CompareToNull(bool is_strict, Expression* expression)
: is_strict_(is_strict), expression_(expression) { }
CompareToNull(Isolate* isolate, bool is_strict, Expression* expression)
: Expression(isolate), is_strict_(is_strict), expression_(expression) { }
DECLARE_NODE_TYPE(CompareToNull)
@ -1520,18 +1587,20 @@ class CompareToNull: public Expression {
class Conditional: public Expression {
public:
Conditional(Expression* condition,
Conditional(Isolate* isolate,
Expression* condition,
Expression* then_expression,
Expression* else_expression,
int then_expression_position,
int else_expression_position)
: condition_(condition),
: Expression(isolate),
condition_(condition),
then_expression_(then_expression),
else_expression_(else_expression),
then_expression_position_(then_expression_position),
else_expression_position_(else_expression_position),
then_id_(GetNextId()),
else_id_(GetNextId()) {
then_id_(GetNextId(isolate)),
else_id_(GetNextId(isolate)) {
}
DECLARE_NODE_TYPE(Conditional)
@ -1561,7 +1630,11 @@ class Conditional: public Expression {
class Assignment: public Expression {
public:
Assignment(Token::Value op, Expression* target, Expression* value, int pos);
Assignment(Isolate* isolate,
Token::Value op,
Expression* target,
Expression* value,
int pos);
DECLARE_NODE_TYPE(Assignment)
@ -1621,8 +1694,8 @@ class Assignment: public Expression {
class Throw: public Expression {
public:
Throw(Expression* exception, int pos)
: exception_(exception), pos_(pos) {}
Throw(Isolate* isolate, Expression* exception, int pos)
: Expression(isolate), exception_(exception), pos_(pos) {}
DECLARE_NODE_TYPE(Throw)
@ -1638,7 +1711,8 @@ class Throw: public Expression {
class FunctionLiteral: public Expression {
public:
FunctionLiteral(Handle<String> name,
FunctionLiteral(Isolate* isolate,
Handle<String> name,
Scope* scope,
ZoneList<Statement*>* body,
int materialized_literal_count,
@ -1650,7 +1724,8 @@ class FunctionLiteral: public Expression {
int end_position,
bool is_expression,
bool has_duplicate_parameters)
: name_(name),
: Expression(isolate),
name_(name),
scope_(scope),
body_(body),
materialized_literal_count_(materialized_literal_count),
@ -1729,9 +1804,10 @@ class FunctionLiteral: public Expression {
class SharedFunctionInfoLiteral: public Expression {
public:
explicit SharedFunctionInfoLiteral(
SharedFunctionInfoLiteral(
Isolate* isolate,
Handle<SharedFunctionInfo> shared_function_info)
: shared_function_info_(shared_function_info) { }
: Expression(isolate), shared_function_info_(shared_function_info) { }
DECLARE_NODE_TYPE(SharedFunctionInfoLiteral)
@ -1747,6 +1823,7 @@ class SharedFunctionInfoLiteral: public Expression {
class ThisFunction: public Expression {
public:
explicit ThisFunction(Isolate* isolate) : Expression(isolate) {}
DECLARE_NODE_TYPE(ThisFunction)
virtual bool IsInlineable() const;
};

1
deps/v8/src/bootstrapper.cc

@ -1309,6 +1309,7 @@ void Genesis::InstallNativeFunctions() {
void Genesis::InstallExperimentalNativeFunctions() {
if (FLAG_harmony_proxies) {
INSTALL_NATIVE(JSFunction, "DerivedHasTrap", derived_has_trap);
INSTALL_NATIVE(JSFunction, "DerivedGetTrap", derived_get_trap);
INSTALL_NATIVE(JSFunction, "DerivedSetTrap", derived_set_trap);
}

4
deps/v8/src/builtins.cc

@ -1202,10 +1202,10 @@ MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor(
ASSERT(!CalledAsConstructor(isolate));
Heap* heap = isolate->heap();
Handle<Object> receiver = args.at<Object>(0);
Handle<Object> receiver = args.receiver();
// Get the object called.
JSObject* obj = JSObject::cast(*args.receiver());
JSObject* obj = JSObject::cast(*receiver);
// Get the invocation callback from the function descriptor that was
// used to create the called object.

5
deps/v8/src/code-stubs.cc

@ -250,7 +250,7 @@ void KeyedLoadElementStub::Generate(MacroAssembler* masm) {
KeyedLoadStubCompiler::GenerateLoadFastElement(masm);
break;
case JSObject::FAST_DOUBLE_ELEMENTS:
UNIMPLEMENTED();
KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(masm);
break;
case JSObject::EXTERNAL_BYTE_ELEMENTS:
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
@ -279,7 +279,8 @@ void KeyedStoreElementStub::Generate(MacroAssembler* masm) {
KeyedStoreStubCompiler::GenerateStoreFastElement(masm, is_js_array_);
break;
case JSObject::FAST_DOUBLE_ELEMENTS:
UNIMPLEMENTED();
KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(masm,
is_js_array_);
break;
case JSObject::EXTERNAL_BYTE_ELEMENTS:
case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:

2
deps/v8/src/compiler.cc

@ -511,7 +511,6 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
info.SetPreParseData(pre_data);
if (natives == NATIVES_CODE) {
info.MarkAsAllowingNativesSyntax();
info.MarkAsNative();
}
result = MakeFunctionInfo(&info);
if (extension == NULL && !result.is_null()) {
@ -679,7 +678,6 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
info.SetFunction(literal);
info.SetScope(literal->scope());
if (literal->scope()->is_strict_mode()) info.MarkAsStrictMode();
if (script->type()->value() == Script::TYPE_NATIVE) info.MarkAsNative();
LiveEditFunctionTracker live_edit_tracker(info.isolate(), literal);
// Determine if the function can be lazily compiled. This is necessary to

9
deps/v8/src/compiler.h

@ -173,9 +173,12 @@ class CompilationInfo BASE_EMBEDDED {
void Initialize(Mode mode) {
mode_ = V8::UseCrankshaft() ? mode : NONOPT;
if (!shared_info_.is_null()) {
if (shared_info_->strict_mode()) MarkAsStrictMode();
if (shared_info_->native()) MarkAsNative();
ASSERT(!script_.is_null());
if (script_->type()->value() == Script::TYPE_NATIVE) {
MarkAsNative();
}
if (!shared_info_.is_null() && shared_info_->strict_mode()) {
MarkAsStrictMode();
}
}

2
deps/v8/src/contexts.h

@ -110,6 +110,7 @@ enum ContextLookupFlags {
V(MAP_CACHE_INDEX, Object, map_cache) \
V(CONTEXT_DATA_INDEX, Object, data) \
V(ALLOW_CODE_GEN_FROM_STRINGS_INDEX, Object, allow_code_gen_from_strings) \
V(DERIVED_HAS_TRAP_INDEX, JSFunction, derived_has_trap) \
V(DERIVED_GET_TRAP_INDEX, JSFunction, derived_get_trap) \
V(DERIVED_SET_TRAP_INDEX, JSFunction, derived_set_trap)
@ -227,6 +228,7 @@ class Context: public FixedArray {
OUT_OF_MEMORY_INDEX,
CONTEXT_DATA_INDEX,
ALLOW_CODE_GEN_FROM_STRINGS_INDEX,
DERIVED_HAS_TRAP_INDEX,
DERIVED_GET_TRAP_INDEX,
DERIVED_SET_TRAP_INDEX,

7
deps/v8/src/conversions-inl.h

@ -454,7 +454,6 @@ static double InternalStringToDouble(UnicodeCache* unicode_cache,
int significant_digits = 0;
int insignificant_digits = 0;
bool nonzero_digit_dropped = false;
bool fractional_part = false;
bool negative = false;
@ -557,10 +556,8 @@ static double InternalStringToDouble(UnicodeCache* unicode_cache,
}
}
// We don't emit a '.', but adjust the exponent instead.
fractional_part = true;
// There is a fractional part.
// There is a fractional part. We don't emit a '.', but adjust the exponent
// instead.
while (*current >= '0' && *current <= '9') {
if (significant_digits < kMaxSignificantDigits) {
ASSERT(buffer_pos < kBufferSize);

232
deps/v8/src/d8.cc

@ -26,33 +26,49 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef V8_SHARED
#define USING_V8_SHARED
#endif
#ifdef COMPRESS_STARTUP_DATA_BZ2
#include <bzlib.h>
#endif
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "v8.h"
#ifdef USING_V8_SHARED
#include <assert.h>
#include "../include/v8-testing.h"
#endif // USING_V8_SHARED
#include "d8.h"
#ifndef USING_V8_SHARED
#include "api.h"
#include "checks.h"
#include "d8-debug.h"
#include "debug.h"
#include "api.h"
#include "natives.h"
#include "platform.h"
#include "v8.h"
#endif // USING_V8_SHARED
#if !defined(_WIN32) && !defined(_WIN64)
#include <unistd.h> // NOLINT
#endif
namespace v8 {
#ifdef USING_V8_SHARED
#define ASSERT(condition) assert(condition)
#endif // USING_V8_SHARED
const char* Shell::kHistoryFileName = ".d8_history";
const char* Shell::kPrompt = "d8> ";
namespace v8 {
#ifndef USING_V8_SHARED
LineEditor *LineEditor::first_ = NULL;
const char* Shell::kHistoryFileName = ".d8_history";
LineEditor::LineEditor(Type type, const char* name)
@ -98,17 +114,22 @@ CounterMap* Shell::counter_map_;
i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
CounterCollection Shell::local_counters_;
CounterCollection* Shell::counters_ = &local_counters_;
i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
Persistent<Context> Shell::utility_context_;
#endif // USING_V8_SHARED
Persistent<Context> Shell::evaluation_context_;
i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
ShellOptions Shell::options;
const char* Shell::kPrompt = "d8> ";
#ifndef USING_V8_SHARED
bool CounterMap::Match(void* key1, void* key2) {
const char* name1 = reinterpret_cast<const char*>(key1);
const char* name2 = reinterpret_cast<const char*>(key2);
return strcmp(name1, name2) == 0;
}
#endif // USING_V8_SHARED
// Converts a V8 value to a C string.
@ -122,17 +143,22 @@ bool Shell::ExecuteString(Handle<String> source,
Handle<Value> name,
bool print_result,
bool report_exceptions) {
#ifndef USING_V8_SHARED
bool FLAG_debugger = i::FLAG_debugger;
#else
bool FLAG_debugger = false;
#endif // USING_V8_SHARED
HandleScope handle_scope;
TryCatch try_catch;
options.script_executed = true;
if (i::FLAG_debugger) {
if (FLAG_debugger) {
// When debugging make exceptions appear to be uncaught.
try_catch.SetVerbose(true);
}
Handle<Script> script = Script::Compile(source, name);
if (script.IsEmpty()) {
// Print errors that happened during compilation.
if (report_exceptions && !i::FLAG_debugger)
if (report_exceptions && !FLAG_debugger)
ReportException(&try_catch);
return false;
} else {
@ -140,7 +166,7 @@ bool Shell::ExecuteString(Handle<String> source,
if (result.IsEmpty()) {
ASSERT(try_catch.HasCaught());
// Print errors that happened during execution.
if (report_exceptions && !i::FLAG_debugger)
if (report_exceptions && !FLAG_debugger)
ReportException(&try_catch);
return false;
} else {
@ -161,6 +187,7 @@ bool Shell::ExecuteString(Handle<String> source,
Handle<Value> Shell::Print(const Arguments& args) {
Handle<Value> val = Write(args);
printf("\n");
fflush(stdout);
return val;
}
@ -196,15 +223,20 @@ Handle<Value> Shell::Read(const Arguments& args) {
Handle<Value> Shell::ReadLine(const Arguments& args) {
i::SmartPointer<char> line(i::ReadLine(""));
if (*line == NULL) {
return Null();
}
size_t len = strlen(*line);
if (len > 0 && line[len - 1] == '\n') {
--len;
}
return String::New(*line, len);
static const int kBufferSize = 256;
char buffer[kBufferSize];
Handle<String> accumulator = String::New("");
bool linebreak;
int length;
do { // Repeat if the line ends with an escape '\'.
// fgets got an error. Just give up.
if (fgets(buffer, kBufferSize, stdin) == NULL) return Null();
length = strlen(buffer);
linebreak = (length > 1 && buffer[length-2] == '\\');
if (linebreak) buffer[length-2] = '\n';
accumulator = String::Concat(accumulator, String::New(buffer, length-1));
} while (linebreak);
return accumulator;
}
@ -236,6 +268,10 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args,
return ThrowException(
String::New("Array constructor needs one parameter."));
}
static const int kMaxLength = 0x3fffffff;
#ifndef USING_V8_SHARED
ASSERT(kMaxLength == i::ExternalArray::kMaxLength);
#endif // USING_V8_SHARED
size_t length = 0;
if (args[0]->IsUint32()) {
length = args[0]->Uint32Value();
@ -244,7 +280,7 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args,
if (raw_length < 0) {
return ThrowException(String::New("Array length must not be negative."));
}
if (raw_length > i::ExternalArray::kMaxLength) {
if (raw_length > kMaxLength) {
return ThrowException(
String::New("Array length exceeds maximum length."));
}
@ -252,7 +288,7 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args,
} else {
return ThrowException(String::New("Array length must be a number."));
}
if (length > static_cast<size_t>(i::ExternalArray::kMaxLength)) {
if (length > static_cast<size_t>(kMaxLength)) {
return ThrowException(String::New("Array length exceeds maximum length."));
}
void* data = calloc(length, element_size);
@ -332,7 +368,9 @@ Handle<Value> Shell::Yield(const Arguments& args) {
Handle<Value> Shell::Quit(const Arguments& args) {
int exit_code = args[0]->Int32Value();
#ifndef USING_V8_SHARED
OnExit();
#endif // USING_V8_SHARED
exit(exit_code);
return Undefined();
}
@ -381,6 +419,7 @@ void Shell::ReportException(v8::TryCatch* try_catch) {
}
#ifndef USING_V8_SHARED
Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) {
HandleScope handle_scope;
Context::Scope context_scope(utility_context_);
@ -414,9 +453,11 @@ Handle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) {
Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv);
return val;
}
#endif
#endif // ENABLE_DEBUGGER_SUPPORT
#endif // USING_V8_SHARED
#ifndef USING_V8_SHARED
int32_t* Counter::Bind(const char* name, bool is_histogram) {
int i;
for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
@ -448,8 +489,8 @@ Counter* CounterCollection::GetNextCounter() {
void Shell::MapCounters(const char* name) {
counters_file_ = i::OS::MemoryMappedFile::create(name,
sizeof(CounterCollection), &local_counters_);
counters_file_ = i::OS::MemoryMappedFile::create(
name, sizeof(CounterCollection), &local_counters_);
void* memory = (counters_file_ == NULL) ?
NULL : counters_file_->memory();
if (memory == NULL) {
@ -514,6 +555,7 @@ void Shell::AddHistogramSample(void* histogram, int sample) {
counter->AddSample(sample);
}
void Shell::InstallUtilityScript() {
Locker lock;
HandleScope scope;
@ -532,7 +574,7 @@ void Shell::InstallUtilityScript() {
utility_context_->Global()->Set(String::New("$debug"),
Utils::ToLocal(js_debug));
debug->debug_context()->set_security_token(HEAP->undefined_value());
#endif
#endif // ENABLE_DEBUGGER_SUPPORT
// Run the d8 shell utility script in the utility context
int source_index = i::NativesCollection<i::D8>::GetIndex("d8");
@ -550,10 +592,10 @@ void Shell::InstallUtilityScript() {
// in the debugger.
i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script);
i::Handle<i::Script> script_object = compiled_script->IsJSFunction()
? i::Handle<i::Script>(i::Script::cast(
i::JSFunction::cast(*compiled_script)->shared()->script()))
: i::Handle<i::Script>(i::Script::cast(
i::SharedFunctionInfo::cast(*compiled_script)->script()));
? i::Handle<i::Script>(i::Script::cast(
i::JSFunction::cast(*compiled_script)->shared()->script()))
: i::Handle<i::Script>(i::Script::cast(
i::SharedFunctionInfo::cast(*compiled_script)->script()));
script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
#ifdef ENABLE_DEBUGGER_SUPPORT
@ -561,8 +603,9 @@ void Shell::InstallUtilityScript() {
if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
v8::Debug::SetDebugEventListener(HandleDebugEvent);
}
#endif
#endif // ENABLE_DEBUGGER_SUPPORT
}
#endif // USING_V8_SHARED
#ifdef COMPRESS_STARTUP_DATA_BZ2
@ -629,9 +672,11 @@ Handle<ObjectTemplate> Shell::CreateGlobalTemplate() {
global_template->Set(String::New("lol_is_enabled"), Boolean::New(false));
#endif
#ifndef USING_V8_SHARED
Handle<ObjectTemplate> os_templ = ObjectTemplate::New();
AddOSMethods(os_templ);
global_template->Set(String::New("os"), os_templ);
#endif // USING_V8_SHARED
return global_template;
}
@ -647,6 +692,7 @@ void Shell::Initialize() {
}
#endif
#ifndef USING_V8_SHARED
Shell::counter_map_ = new CounterMap();
// Set up counters
if (i::StrLength(i::FLAG_map_counters) != 0)
@ -656,9 +702,10 @@ void Shell::Initialize() {
V8::SetCreateHistogramFunction(CreateHistogram);
V8::SetAddHistogramSampleFunction(AddHistogramSample);
}
#endif // USING_V8_SHARED
if (options.test_shell) return;
#ifndef USING_V8_SHARED
Locker lock;
HandleScope scope;
Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
@ -669,18 +716,22 @@ void Shell::Initialize() {
if (i::FLAG_debugger_agent) {
v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
}
#endif
#endif // ENABLE_DEBUGGER_SUPPORT
#endif // USING_V8_SHARED
}
Persistent<Context> Shell::CreateEvaluationContext() {
#ifndef USING_V8_SHARED
// This needs to be a critical section since this is not thread-safe
i::ScopedLock lock(context_mutex_);
#endif // USING_V8_SHARED
// Initialize the global objects
Handle<ObjectTemplate> global_template = CreateGlobalTemplate();
Persistent<Context> context = Context::New(NULL, global_template);
Context::Scope scope(context);
#ifndef USING_V8_SHARED
i::JSArguments js_args = i::FLAG_js_arguments;
i::Handle<i::FixedArray> arguments_array =
FACTORY->NewFixedArray(js_args.argc());
@ -692,11 +743,13 @@ Persistent<Context> Shell::CreateEvaluationContext() {
i::Handle<i::JSArray> arguments_jsarray =
FACTORY->NewJSArrayWithElements(arguments_array);
context->Global()->Set(String::New("arguments"),
Utils::ToLocal(arguments_jsarray));
Utils::ToLocal(arguments_jsarray));
#endif // USING_V8_SHARED
return context;
}
#ifndef USING_V8_SHARED
void Shell::OnExit() {
if (i::FLAG_dump_counters) {
printf("+----------------------------------------+-------------+\n");
@ -716,12 +769,18 @@ void Shell::OnExit() {
if (counters_file_ != NULL)
delete counters_file_;
}
#endif // USING_V8_SHARED
static char* ReadChars(const char* name, int* size_out) {
// Release the V8 lock while reading files.
v8::Unlocker unlocker(Isolate::GetCurrent());
#ifndef USING_V8_SHARED
FILE* file = i::OS::FOpen(name, "rb");
#else
// TODO(yangguo@chromium.org): reading from a directory hangs!
FILE* file = fopen(name, "rb");
#endif // USING_V8_SHARED
if (file == NULL) return NULL;
fseek(file, 0, SEEK_END);
@ -740,6 +799,7 @@ static char* ReadChars(const char* name, int* size_out) {
}
#ifndef USING_V8_SHARED
static char* ReadToken(char* data, char token) {
char* next = i::OS::StrChr(data, token);
if (next != NULL) {
@ -759,6 +819,7 @@ static char* ReadLine(char* data) {
static char* ReadWord(char* data) {
return ReadToken(data, ' ');
}
#endif // USING_V8_SHARED
// Reads a file into a v8 string.
@ -773,34 +834,44 @@ Handle<String> Shell::ReadFile(const char* name) {
void Shell::RunShell() {
Locker locker;
Context::Scope context_scope(evaluation_context_);
HandleScope handle_scope;
Handle<String> name = String::New("(d8)");
#ifndef USING_V8_SHARED
LineEditor* editor = LineEditor::Get();
printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name());
if (i::FLAG_debugger) {
printf("JavaScript debugger enabled\n");
}
editor->Open();
while (true) {
Locker locker;
HandleScope handle_scope;
Context::Scope context_scope(evaluation_context_);
i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt);
if (input.is_empty())
break;
if (input.is_empty()) break;
editor->AddHistory(*input);
Handle<String> name = String::New("(d8)");
ExecuteString(String::New(*input), name, true, true);
}
editor->Close();
#else
printf("V8 version %s [D8 light using shared library]\n", V8::GetVersion());
static const int kBufferSize = 256;
while (true) {
char buffer[kBufferSize];
printf("%s", Shell::kPrompt);
if (fgets(buffer, kBufferSize, stdin) == NULL) break;
ExecuteString(String::New(buffer), name, true, true);
}
#endif // USING_V8_SHARED
printf("\n");
}
#ifndef USING_V8_SHARED
class ShellThread : public i::Thread {
public:
ShellThread(int no, i::Vector<const char> files)
: Thread("d8:ShellThread"),
no_(no), files_(files) { }
: Thread("d8:ShellThread"),
no_(no), files_(files) { }
virtual void Run();
private:
int no_;
@ -848,6 +919,7 @@ void ShellThread::Run() {
ptr = next_line;
}
}
#endif // USING_V8_SHARED
void SourceGroup::ExitShell(int exit_code) {
@ -894,7 +966,12 @@ void SourceGroup::Execute() {
Handle<String> SourceGroup::ReadFile(const char* name) {
#ifndef USING_V8_SHARED
FILE* file = i::OS::FOpen(name, "rb");
#else
// TODO(yangguo@chromium.org): reading from a directory hangs!
FILE* file = fopen(name, "rb");
#endif // USING_V8_SHARED
if (file == NULL) return Handle<String>();
fseek(file, 0, SEEK_END);
@ -914,6 +991,7 @@ Handle<String> SourceGroup::ReadFile(const char* name) {
}
#ifndef USING_V8_SHARED
i::Thread::Options SourceGroup::GetThreadOptions() {
i::Thread::Options options;
options.name = "IsolateThread";
@ -965,6 +1043,7 @@ void SourceGroup::WaitForThread() {
done_semaphore_->Wait();
}
}
#endif // USING_V8_SHARED
bool Shell::SetOptions(int argc, char* argv[]) {
@ -986,12 +1065,26 @@ bool Shell::SetOptions(int argc, char* argv[]) {
options.test_shell = true;
argv[i] = NULL;
} else if (strcmp(argv[i], "--preemption") == 0) {
#ifdef USING_V8_SHARED
printf("D8 with shared library does not support multi-threading\n");
return false;
#else
options.use_preemption = true;
argv[i] = NULL;
#endif // USING_V8_SHARED
} else if (strcmp(argv[i], "--no-preemption") == 0) {
#ifdef USING_V8_SHARED
printf("D8 with shared library does not support multi-threading\n");
return false;
#else
options.use_preemption = false;
argv[i] = NULL;
#endif // USING_V8_SHARED
} else if (strcmp(argv[i], "--preemption-interval") == 0) {
#ifdef USING_V8_SHARED
printf("D8 with shared library does not support multi-threading\n");
return false;
#else
if (++i < argc) {
argv[i-1] = NULL;
char* end = NULL;
@ -1007,15 +1100,33 @@ bool Shell::SetOptions(int argc, char* argv[]) {
printf("Missing value for --preemption-interval\n");
return false;
}
#endif // USING_V8_SHARED
} else if (strcmp(argv[i], "-f") == 0) {
// Ignore any -f flags for compatibility with other stand-alone
// JavaScript engines.
continue;
} else if (strcmp(argv[i], "--isolate") == 0) {
#ifdef USING_V8_SHARED
printf("D8 with shared library does not support multi-threading\n");
return false;
#endif // USING_V8_SHARED
options.num_isolates++;
}
#ifdef USING_V8_SHARED
else if (strcmp(argv[i], "--dump-counters") == 0) {
printf("D8 with shared library does not include counters\n");
return false;
} else if (strcmp(argv[i], "-p") == 0) {
printf("D8 with shared library does not support multi-threading\n");
return false;
} else if (strcmp(argv[i], "--debugger") == 0) {
printf("Javascript debugger not included\n");
return false;
}
#endif // USING_V8_SHARED
}
#ifndef USING_V8_SHARED
// Run parallel threads if we are not using --isolate
for (int i = 1; i < argc; i++) {
if (argv[i] == NULL) continue;
@ -1038,6 +1149,7 @@ bool Shell::SetOptions(int argc, char* argv[]) {
options.parallel_files->Add(i::Vector<const char>(files, size));
}
}
#endif // USING_V8_SHARED
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
@ -1062,21 +1174,21 @@ bool Shell::SetOptions(int argc, char* argv[]) {
int Shell::RunMain(int argc, char* argv[]) {
#ifndef USING_V8_SHARED
i::List<i::Thread*> threads(1);
{
if (options.parallel_files != NULL)
for (int i = 0; i < options.parallel_files->length(); i++) {
i::Vector<const char> files = options.parallel_files->at(i);
ShellThread* thread = new ShellThread(threads.length(), files);
thread->Start();
threads.Add(thread);
}
for (int i = 1; i < options.num_isolates; ++i) {
options.isolate_sources[i].StartExecuteInThread();
if (options.parallel_files != NULL)
for (int i = 0; i < options.parallel_files->length(); i++) {
i::Vector<const char> files = options.parallel_files->at(i);
ShellThread* thread = new ShellThread(threads.length(), files);
thread->Start();
threads.Add(thread);
}
for (int i = 1; i < options.num_isolates; ++i) {
options.isolate_sources[i].StartExecuteInThread();
}
#endif // USING_V8_SHARED
{ // NOLINT
Locker lock;
HandleScope scope;
Persistent<Context> context = CreateEvaluationContext();
@ -1090,14 +1202,18 @@ int Shell::RunMain(int argc, char* argv[]) {
} else {
context.Dispose();
}
#ifndef USING_V8_SHARED
// Start preemption if threads have been created and preemption is enabled.
if (options.parallel_files != NULL
&& threads.length() > 0
&& options.use_preemption) {
Locker::StartPreemption(options.preemption_interval);
}
#endif // USING_V8_SHARED
}
#ifndef USING_V8_SHARED
for (int i = 1; i < options.num_isolates; ++i) {
options.isolate_sources[i].WaitForThread();
}
@ -1110,6 +1226,7 @@ int Shell::RunMain(int argc, char* argv[]) {
}
OnExit();
#endif // USING_V8_SHARED
return 0;
}
@ -1136,14 +1253,15 @@ int Shell::Main(int argc, char* argv[]) {
result = RunMain(argc, argv);
}
#ifdef ENABLE_DEBUGGER_SUPPORT
#if !defined(USING_V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT)
// Run remote debugger if requested, but never on --test
if (i::FLAG_remote_debugger && !options.test_shell) {
InstallUtilityScript();
RunRemoteDebugger(i::FLAG_debugger_port);
return 0;
}
#endif
#endif // !USING_V8_SHARED && ENABLE_DEBUGGER_SUPPORT
// Run interactive shell if explicitly requested or if no script has been
// executed, but never on --test
@ -1151,7 +1269,9 @@ int Shell::Main(int argc, char* argv[]) {
if (( options.interactive_shell
|| !options.script_executed )
&& !options.test_shell ) {
#ifndef USING_V8_SHARED
InstallUtilityScript();
#endif // USING_V8_SHARED
RunShell();
}

27
deps/v8/src/d8.gyp

@ -26,12 +26,14 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
'variables': {
'console%': '',
},
'targets': [
{
'target_name': 'd8',
'type': 'executable',
'dependencies': [
'd8_js2c#host',
'../tools/gyp/v8.gyp:v8',
],
'include_dirs+': [
@ -42,15 +44,24 @@
],
'sources': [
'd8.cc',
'd8-debug.cc',
'<(SHARED_INTERMEDIATE_DIR)/d8-js.cc',
],
'conditions': [
[ 'OS=="linux" or OS=="mac" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
'sources': [ 'd8-posix.cc', ]
}],
[ 'OS=="win"', {
'sources': [ 'd8-windows.cc', ]
[ 'component!="shared_library"', {
'dependencies': [ 'd8_js2c#host', ],
'sources': [ 'd8-debug.cc', '<(SHARED_INTERMEDIATE_DIR)/d8-js.cc', ],
'conditions': [
[ 'console=="readline"', {
'libraries': [ '-lreadline', ],
'sources': [ 'd8-readline.cc' ],
}],
[ '(OS=="linux" or OS=="mac" or OS=="freebsd" \
or OS=="openbsd" or OS=="solaris")', {
'sources': [ 'd8-posix.cc', ]
}],
[ 'OS=="win"', {
'sources': [ 'd8-windows.cc', ]
}],
],
}],
],
},

111
deps/v8/src/d8.h

@ -28,16 +28,23 @@
#ifndef V8_D8_H_
#define V8_D8_H_
#include "allocation.h"
#ifndef USING_V8_SHARED
#include "v8.h"
#include "allocation.h"
#include "hashmap.h"
#else
#include "../include/v8.h"
#endif // USING_V8_SHARED
namespace v8 {
#ifndef USING_V8_SHARED
namespace i = v8::internal;
#endif // USING_V8_SHARED
#ifndef USING_V8_SHARED
// A single counter in a counter collection.
class Counter {
public:
@ -110,17 +117,20 @@ class CounterMap {
static bool Match(void* key1, void* key2);
i::HashMap hash_map_;
};
#endif // USING_V8_SHARED
class SourceGroup {
public:
SourceGroup()
: next_semaphore_(v8::internal::OS::CreateSemaphore(0)),
done_semaphore_(v8::internal::OS::CreateSemaphore(0)),
thread_(NULL),
argv_(NULL),
begin_offset_(0),
end_offset_(0) { }
SourceGroup() :
#ifndef USING_V8_SHARED
next_semaphore_(v8::internal::OS::CreateSemaphore(0)),
done_semaphore_(v8::internal::OS::CreateSemaphore(0)),
thread_(NULL),
#endif // USING_V8_SHARED
argv_(NULL),
begin_offset_(0),
end_offset_(0) { }
void Begin(char** argv, int offset) {
argv_ = const_cast<const char**>(argv);
@ -131,6 +141,7 @@ class SourceGroup {
void Execute();
#ifndef USING_V8_SHARED
void StartExecuteInThread();
void WaitForThread();
@ -154,6 +165,7 @@ class SourceGroup {
i::Semaphore* next_semaphore_;
i::Semaphore* done_semaphore_;
i::Thread* thread_;
#endif // USING_V8_SHARED
void ExitShell(int exit_code);
Handle<String> ReadFile(const char* name);
@ -166,34 +178,41 @@ class SourceGroup {
class ShellOptions {
public:
ShellOptions()
: script_executed(false),
last_run(true),
stress_opt(false),
stress_deopt(false),
interactive_shell(false),
test_shell(false),
use_preemption(true),
preemption_interval(10),
num_isolates(1),
isolate_sources(NULL),
parallel_files(NULL) { }
ShellOptions() :
#ifndef USING_V8_SHARED
use_preemption(true),
preemption_interval(10),
parallel_files(NULL),
#endif // USING_V8_SHARED
script_executed(false),
last_run(true),
stress_opt(false),
stress_deopt(false),
interactive_shell(false),
test_shell(false),
num_isolates(1),
isolate_sources(NULL) { }
#ifndef USING_V8_SHARED
bool use_preemption;
int preemption_interval;
i::List< i::Vector<const char> >* parallel_files;
#endif // USING_V8_SHARED
bool script_executed;
bool last_run;
bool stress_opt;
bool stress_deopt;
bool interactive_shell;
bool test_shell;
bool use_preemption;
int preemption_interval;
int num_isolates;
SourceGroup* isolate_sources;
i::List< i::Vector<const char> >* parallel_files;
};
class Shell: public i::AllStatic {
#ifdef USING_V8_SHARED
class Shell {
#else
class Shell : public i::AllStatic {
#endif // USING_V8_SHARED
public:
static bool ExecuteString(Handle<String> source,
Handle<Value> name,
@ -201,6 +220,14 @@ class Shell: public i::AllStatic {
bool report_exceptions);
static const char* ToCString(const v8::String::Utf8Value& value);
static void ReportException(TryCatch* try_catch);
static Handle<String> ReadFile(const char* name);
static Persistent<Context> CreateEvaluationContext();
static int RunMain(int argc, char* argv[]);
static int Main(int argc, char* argv[]);
#ifndef USING_V8_SHARED
static Handle<Array> GetCompletions(Handle<String> text,
Handle<String> full);
static void OnExit();
static int* LookupCounter(const char* name);
static void* CreateHistogram(const char* name,
@ -209,18 +236,8 @@ class Shell: public i::AllStatic {
size_t buckets);
static void AddHistogramSample(void* histogram, int sample);
static void MapCounters(const char* name);
static Handle<String> ReadFile(const char* name);
static void Initialize();
static Persistent<Context> CreateEvaluationContext();
static void InstallUtilityScript();
static void RunShell();
static bool SetOptions(int argc, char* argv[]);
static int RunScript(char* filename);
static int RunMain(int argc, char* argv[]);
static int Main(int argc, char* argv[]);
static Handle<ObjectTemplate> CreateGlobalTemplate();
static Handle<Array> GetCompletions(Handle<String> text,
Handle<String> full);
#endif // USING_V8_SHARED
#ifdef ENABLE_DEBUGGER_SUPPORT
static Handle<Object> DebugMessageDetails(Handle<String> message);
static Handle<Value> DebugCommandToJSONRequest(Handle<String> command);
@ -283,15 +300,16 @@ class Shell: public i::AllStatic {
static Handle<Value> RemoveDirectory(const Arguments& args);
static void AddOSMethods(Handle<ObjectTemplate> os_template);
#ifndef USING_V8_SHARED
static const char* kHistoryFileName;
#endif // USING_V8_SHARED
static const char* kPrompt;
static ShellOptions options;
private:
static Persistent<Context> utility_context_;
static Persistent<Context> evaluation_context_;
#ifndef USING_V8_SHARED
static Persistent<Context> utility_context_;
static CounterMap* counter_map_;
// We statically allocate a set of local counters to be used if we
// don't want to store the stats in a memory-mapped file
@ -299,7 +317,14 @@ class Shell: public i::AllStatic {
static CounterCollection* counters_;
static i::OS::MemoryMappedFile* counters_file_;
static i::Mutex* context_mutex_;
static Counter* GetCounter(const char* name, bool is_histogram);
static void InstallUtilityScript();
#endif // USING_V8_SHARED
static void Initialize();
static void RunShell();
static bool SetOptions(int argc, char* argv[]);
static Handle<ObjectTemplate> CreateGlobalTemplate();
static Handle<Value> CreateExternalArray(const Arguments& args,
ExternalArrayType type,
size_t element_size);
@ -307,6 +332,7 @@ class Shell: public i::AllStatic {
};
#ifndef USING_V8_SHARED
class LineEditor {
public:
enum Type { DUMB = 0, READLINE = 1 };
@ -326,6 +352,7 @@ class LineEditor {
LineEditor* next_;
static LineEditor* first_;
};
#endif // USING_V8_SHARED
} // namespace v8

14
deps/v8/src/debug.cc

@ -772,9 +772,9 @@ bool Debug::CompileDebuggerScript(int index) {
bool caught_exception = false;
Handle<JSFunction> function =
factory->NewFunctionFromSharedFunctionInfo(function_info, context);
Handle<Object> result =
Execution::TryCall(function, Handle<Object>(context->global()),
0, NULL, &caught_exception);
Execution::TryCall(function, Handle<Object>(context->global()),
0, NULL, &caught_exception);
// Check for caught exceptions.
if (caught_exception) {
@ -1886,8 +1886,7 @@ void Debug::ClearMirrorCache() {
*function_name));
ASSERT(fun->IsJSFunction());
bool caught_exception;
Handle<Object> js_object = Execution::TryCall(
Handle<JSFunction>::cast(fun),
Execution::TryCall(Handle<JSFunction>::cast(fun),
Handle<JSObject>(Debug::debug_context()->global()),
0, NULL, &caught_exception);
}
@ -2252,8 +2251,7 @@ void Debugger::OnAfterCompile(Handle<Script> script,
bool caught_exception = false;
const int argc = 1;
Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
Handle<Object> result = Execution::TryCall(
Handle<JSFunction>::cast(update_script_break_points),
Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
Isolate::Current()->js_builtins_object(), argc, argv,
&caught_exception);
if (caught_exception) {
@ -2930,7 +2928,7 @@ v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
// Isolate::context() may be NULL when "script collected" event occures.
ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
return GetDebugEventContext(isolate);
return context;
}

7
deps/v8/src/factory.cc

@ -892,6 +892,13 @@ Handle<JSProxy> Factory::NewJSProxy(Handle<Object> handler,
}
void Factory::BecomeJSObject(Handle<JSProxy> object) {
CALL_HEAP_FUNCTION_VOID(
isolate(),
isolate()->heap()->ReinitializeJSProxyAsJSObject(*object));
}
Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
Handle<String> name,
int number_of_literals,

3
deps/v8/src/factory.h

@ -253,6 +253,9 @@ class Factory {
Handle<JSProxy> NewJSProxy(Handle<Object> handler, Handle<Object> prototype);
// Change the type of the argument into a regular JS object and reinitialize.
void BecomeJSObject(Handle<JSProxy> object);
Handle<JSFunction> NewFunction(Handle<String> name,
Handle<Object> prototype);

1
deps/v8/src/frames.cc

@ -371,7 +371,6 @@ Code* StackFrame::GetSafepointData(Isolate* isolate,
unsigned* stack_slots) {
PcToCodeCache::PcToCodeCacheEntry* entry =
isolate->pc_to_code_cache()->GetCacheEntry(pc);
SafepointEntry cached_safepoint_entry = entry->safepoint_entry;
if (!entry->safepoint_entry.is_valid()) {
entry->safepoint_entry = entry->code->GetSafepointEntry(pc);
ASSERT(entry->safepoint_entry.is_valid());

1
deps/v8/src/full-codegen.cc

@ -686,7 +686,6 @@ FullCodeGenerator::InlineFunctionGenerator
void FullCodeGenerator::EmitInlineRuntimeCall(CallRuntime* node) {
ZoneList<Expression*>* args = node->arguments();
Handle<String> name = node->name();
const Runtime::Function* function = node->function();
ASSERT(function != NULL);
ASSERT(function->intrinsic_type == Runtime::INLINE);

4
deps/v8/src/globals.h

@ -1,4 +1,4 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -199,6 +199,8 @@ const int kDoubleSize = sizeof(double); // NOLINT
const int kIntptrSize = sizeof(intptr_t); // NOLINT
const int kPointerSize = sizeof(void*); // NOLINT
const int kDoubleSizeLog2 = 3;
#if V8_HOST_ARCH_64_BIT
const int kPointerSizeLog2 = 3;
const intptr_t kIntptrSignBit = V8_INT64_C(0x8000000000000000);

33
deps/v8/src/heap.cc

@ -3267,14 +3267,13 @@ MaybeObject* Heap::AllocateJSProxy(Object* handler, Object* prototype) {
MaybeObject* maybe_map_obj = AllocateMap(JS_PROXY_TYPE, JSProxy::kSize);
if (!maybe_map_obj->To<Map>(&map)) return maybe_map_obj;
map->set_prototype(prototype);
map->set_pre_allocated_property_fields(1);
map->set_inobject_properties(1);
// Allocate the proxy object.
Object* result;
MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
if (!maybe_result->ToObject(&result)) return maybe_result;
JSProxy::cast(result)->set_handler(handler);
JSProxy::cast(result)->set_padding(Smi::FromInt(0));
return result;
}
@ -3414,6 +3413,36 @@ MaybeObject* Heap::CopyJSObject(JSObject* source) {
}
MaybeObject* Heap::ReinitializeJSProxyAsJSObject(JSProxy* object) {
// Allocate fresh map.
// TODO(rossberg): Once we optimize proxies, cache these maps.
Map* map;
MaybeObject* maybe_map_obj =
AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
if (!maybe_map_obj->To<Map>(&map)) return maybe_map_obj;
// Check that the receiver has the same size as a fresh object.
ASSERT(map->instance_size() == object->map()->instance_size());
map->set_prototype(object->map()->prototype());
// Allocate the backing storage for the properties.
int prop_size = map->unused_property_fields() - map->inobject_properties();
Object* properties;
{ MaybeObject* maybe_properties = AllocateFixedArray(prop_size, TENURED);
if (!maybe_properties->ToObject(&properties)) return maybe_properties;
}
// Reset the map for the object.
object->set_map(map);
// Reinitialize the object from the constructor map.
InitializeJSObjectFromMap(JSObject::cast(object),
FixedArray::cast(properties), map);
return object;
}
MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
JSGlobalProxy* object) {
ASSERT(constructor->has_initial_map());

5
deps/v8/src/heap.h

@ -441,6 +441,11 @@ class Heap {
MUST_USE_RESULT MaybeObject* AllocateJSProxy(Object* handler,
Object* prototype);
// Reinitialize a JSProxy into an (empty) JSObject. The receiver
// must have the same size as an empty object. The object is reinitialized
// and behaves as an object that has been freshly allocated.
MUST_USE_RESULT MaybeObject* ReinitializeJSProxyAsJSObject(JSProxy* object);
// Reinitialize an JSGlobalProxy based on a constructor. The object
// must have the same size as objects allocated using the
// constructor. The object is reinitialized and behaves as an

22
deps/v8/src/hydrogen-instructions.cc

@ -1366,6 +1366,19 @@ bool HLoadKeyedFastElement::RequiresHoleCheck() const {
}
void HLoadKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
elements()->PrintNameTo(stream);
stream->Add("[");
key()->PrintNameTo(stream);
stream->Add("]");
}
bool HLoadKeyedFastDoubleElement::RequiresHoleCheck() const {
return true;
}
void HLoadKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add("[");
@ -1451,6 +1464,15 @@ void HStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
}
void HStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
elements()->PrintNameTo(stream);
stream->Add("[");
key()->PrintNameTo(stream);
stream->Add("] = ");
value()->PrintNameTo(stream);
}
void HStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintNameTo(stream);
stream->Add("[");

101
deps/v8/src/hydrogen-instructions.h

@ -131,6 +131,7 @@ class LChunkBuilder;
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
V(LoadKeyedFastDoubleElement) \
V(LoadKeyedFastElement) \
V(LoadKeyedGeneric) \
V(LoadKeyedSpecializedArrayElement) \
@ -156,6 +157,7 @@ class LChunkBuilder;
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
V(StoreKeyedFastDoubleElement) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
V(StoreKeyedSpecializedArrayElement) \
@ -588,9 +590,9 @@ class HValue: public ZoneObject {
// it would otherwise output what should be a minus zero as an int32 zero.
// If the operation also exists in a form that takes int32 and outputs int32
// then the operation should return its input value so that we can propagate
// back. There are two operations that need to propagate back to more than
// one input. They are phi and binary add. They always return NULL and
// expect the caller to take care of things.
// back. There are three operations that need to propagate back to more than
// one input. They are phi and binary div and mul. They always return NULL
// and expect the caller to take care of things.
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited) {
visited->Add(id());
return NULL;
@ -1123,40 +1125,19 @@ class HChange: public HUnaryOperation {
class HClampToUint8: public HUnaryOperation {
public:
explicit HClampToUint8(HValue* value)
: HUnaryOperation(value),
input_rep_(Representation::None()) {
SetFlag(kFlexibleRepresentation);
set_representation(Representation::Tagged());
: HUnaryOperation(value) {
set_representation(Representation::Integer32());
SetFlag(kUseGVN);
}
virtual Representation RequiredInputRepresentation(int index) const {
return input_rep_;
}
virtual Representation InferredRepresentation() {
// TODO(danno): Inference on input types should happen separately from
// return representation.
Representation new_rep = value()->representation();
if (input_rep_.IsNone()) {
if (!new_rep.IsNone()) {
input_rep_ = new_rep;
return Representation::Integer32();
} else {
return Representation::None();
}
} else {
return Representation::Integer32();
}
return Representation::None();
}
DECLARE_CONCRETE_INSTRUCTION(ClampToUint8)
protected:
virtual bool DataEquals(HValue* other) { return true; }
private:
Representation input_rep_;
};
@ -3540,6 +3521,37 @@ class HLoadKeyedFastElement: public HTemplateInstruction<2> {
};
class HLoadKeyedFastDoubleElement: public HTemplateInstruction<2> {
public:
HLoadKeyedFastDoubleElement(HValue* elements, HValue* key) {
SetOperandAt(0, elements);
SetOperandAt(1, key);
set_representation(Representation::Double());
SetFlag(kDependsOnArrayElements);
SetFlag(kUseGVN);
}
HValue* elements() { return OperandAt(0); }
HValue* key() { return OperandAt(1); }
virtual Representation RequiredInputRepresentation(int index) const {
// The key is supposed to be Integer32.
return index == 0
? Representation::Tagged()
: Representation::Integer32();
}
virtual void PrintDataTo(StringStream* stream);
bool RequiresHoleCheck() const;
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement)
protected:
virtual bool DataEquals(HValue* other) { return true; }
};
class HLoadKeyedSpecializedArrayElement: public HTemplateInstruction<2> {
public:
HLoadKeyedSpecializedArrayElement(HValue* external_elements,
@ -3725,6 +3737,41 @@ class HStoreKeyedFastElement: public HTemplateInstruction<3> {
};
class HStoreKeyedFastDoubleElement: public HTemplateInstruction<3> {
public:
HStoreKeyedFastDoubleElement(HValue* elements,
HValue* key,
HValue* val) {
SetOperandAt(0, elements);
SetOperandAt(1, key);
SetOperandAt(2, val);
SetFlag(kChangesArrayElements);
}
virtual Representation RequiredInputRepresentation(int index) const {
if (index == 1) {
return Representation::Integer32();
} else if (index == 2) {
return Representation::Double();
} else {
return Representation::Tagged();
}
}
HValue* elements() { return OperandAt(0); }
HValue* key() { return OperandAt(1); }
HValue* value() { return OperandAt(2); }
bool NeedsWriteBarrier() {
return StoringValueNeedsWriteBarrier(value());
}
virtual void PrintDataTo(StringStream* stream);
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement)
};
class HStoreKeyedSpecializedArrayElement: public HTemplateInstruction<3> {
public:
HStoreKeyedSpecializedArrayElement(HValue* external_elements,

86
deps/v8/src/hydrogen.cc

@ -1666,8 +1666,8 @@ void HInferRepresentation::Analyze() {
HValue* use = it.value();
if (use->IsPhi()) {
int id = HPhi::cast(use)->phi_id();
change = change ||
connected_phis[i]->UnionIsChanged(*connected_phis[id]);
if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
change = true;
}
}
}
@ -3901,7 +3901,9 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
bool is_store) {
ASSERT(expr->IsMonomorphic());
Handle<Map> map = expr->GetMonomorphicReceiverType();
if (!map->has_fast_elements() && !map->has_external_array_elements()) {
if (!map->has_fast_elements() &&
!map->has_fast_double_elements() &&
!map->has_external_array_elements()) {
return is_store ? BuildStoreKeyedGeneric(object, key, val)
: BuildLoadKeyedGeneric(object, key);
}
@ -3920,20 +3922,39 @@ HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
return BuildExternalArrayElementAccess(external_elements, checked_key,
val, map->elements_kind(), is_store);
}
ASSERT(map->has_fast_elements());
bool fast_double_elements = map->has_fast_double_elements();
ASSERT(map->has_fast_elements() || fast_double_elements);
if (map->instance_type() == JS_ARRAY_TYPE) {
length = AddInstruction(new(zone()) HJSArrayLength(object));
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
AddInstruction(elements);
if (is_store && !fast_double_elements) {
AddInstruction(new(zone()) HCheckMap(
elements, isolate()->factory()->fixed_array_map()));
}
} else {
AddInstruction(elements);
if (is_store && !fast_double_elements) {
AddInstruction(new(zone()) HCheckMap(
elements, isolate()->factory()->fixed_array_map()));
}
length = AddInstruction(new(zone()) HFixedArrayLength(elements));
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
}
if (is_store) {
return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
if (fast_double_elements) {
return new(zone()) HStoreKeyedFastDoubleElement(elements,
checked_key,
val);
} else {
return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
}
} else {
return new(zone()) HLoadKeyedFastElement(elements, checked_key);
if (fast_double_elements) {
return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
} else {
return new(zone()) HLoadKeyedFastElement(elements, checked_key);
}
}
}
@ -3966,8 +3987,6 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
todo_external_array = true;
}
}
// Support for FAST_DOUBLE_ELEMENTS isn't implemented yet, so we deopt.
type_todo[JSObject::FAST_DOUBLE_ELEMENTS] = false;
HBasicBlock* join = graph()->CreateBasicBlock();
@ -4016,7 +4035,8 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
set_current_block(if_true);
HInstruction* access;
if (elements_kind == JSObject::FAST_ELEMENTS) {
if (elements_kind == JSObject::FAST_ELEMENTS ||
elements_kind == JSObject::FAST_DOUBLE_ELEMENTS) {
HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
HHasInstanceTypeAndBranch* typecheck =
@ -4032,12 +4052,28 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
elements = AddInstruction(new(zone()) HLoadElements(object));
elements->ClearFlag(HValue::kUseGVN);
bool fast_double_elements =
elements_kind == JSObject::FAST_DOUBLE_ELEMENTS;
if (is_store) {
access = AddInstruction(
new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
if (fast_double_elements) {
access = AddInstruction(
new(zone()) HStoreKeyedFastDoubleElement(elements,
checked_key,
val));
} else {
AddInstruction(new(zone()) HCheckMap(
elements, isolate()->factory()->fixed_array_map()));
access = AddInstruction(
new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
}
} else {
access = AddInstruction(
new(zone()) HLoadKeyedFastElement(elements, checked_key));
if (fast_double_elements) {
access = AddInstruction(
new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
} else {
access = AddInstruction(
new(zone()) HLoadKeyedFastElement(elements, checked_key));
}
Push(access);
}
*has_side_effects |= access->HasSideEffects();
@ -4049,14 +4085,30 @@ HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
set_current_block(if_fastobject);
elements = AddInstruction(new(zone()) HLoadElements(object));
elements->ClearFlag(HValue::kUseGVN);
if (is_store && !fast_double_elements) {
AddInstruction(new(zone()) HCheckMap(
elements, isolate()->factory()->fixed_array_map()));
}
length = AddInstruction(new(zone()) HFixedArrayLength(elements));
checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
if (is_store) {
access = AddInstruction(
new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
if (fast_double_elements) {
access = AddInstruction(
new(zone()) HStoreKeyedFastDoubleElement(elements,
checked_key,
val));
} else {
access = AddInstruction(
new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
}
} else {
access = AddInstruction(
new(zone()) HLoadKeyedFastElement(elements, checked_key));
if (fast_double_elements) {
access = AddInstruction(
new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
} else {
access = AddInstruction(
new(zone()) HLoadKeyedFastElement(elements, checked_key));
}
}
} else if (elements_kind == JSObject::DICTIONARY_ELEMENTS) {
if (is_store) {

1
deps/v8/src/ia32/code-stubs-ia32.cc

@ -4158,6 +4158,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ GetBuiltinEntry(edx, Builtins::CALL_NON_FUNCTION);
Handle<Code> adaptor =
masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
__ SetCallKind(ecx, CALL_AS_METHOD);
__ jmp(adaptor, RelocInfo::CODE_TARGET);
}

69
deps/v8/src/ia32/lithium-codegen-ia32.cc

@ -2230,10 +2230,34 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
}
Operand LCodeGen::BuildExternalArrayOperand(
void LCodeGen::DoLoadKeyedFastDoubleElement(
LLoadKeyedFastDoubleElement* instr) {
Register elements = ToRegister(instr->elements());
XMMRegister result = ToDoubleRegister(instr->result());
if (instr->hydrogen()->RequiresHoleCheck()) {
int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
sizeof(kHoleNanLower32);
Operand hole_check_operand = BuildFastArrayOperand(
instr->elements(), instr->key(),
JSObject::FAST_DOUBLE_ELEMENTS,
offset);
__ cmp(hole_check_operand, Immediate(kHoleNanUpper32));
DeoptimizeIf(equal, instr->environment());
}
Operand double_load_operand = BuildFastArrayOperand(
instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
FixedDoubleArray::kHeaderSize - kHeapObjectTag);
__ movdbl(result, double_load_operand);
}
Operand LCodeGen::BuildFastArrayOperand(
LOperand* external_pointer,
LOperand* key,
JSObject::ElementsKind elements_kind) {
JSObject::ElementsKind elements_kind,
uint32_t offset) {
Register external_pointer_reg = ToRegister(external_pointer);
int shift_size = ElementsKindToShiftSize(elements_kind);
if (key->IsConstantOperand()) {
@ -2241,10 +2265,11 @@ Operand LCodeGen::BuildExternalArrayOperand(
if (constant_value & 0xF0000000) {
Abort("array index constant value too big");
}
return Operand(external_pointer_reg, constant_value * (1 << shift_size));
return Operand(external_pointer_reg,
constant_value * (1 << shift_size) + offset);
} else {
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
return Operand(external_pointer_reg, ToRegister(key), scale_factor, offset);
}
}
@ -2252,8 +2277,8 @@ Operand LCodeGen::BuildExternalArrayOperand(
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
LLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
instr->key(), elements_kind));
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
instr->key(), elements_kind, 0));
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
XMMRegister result(ToDoubleRegister(instr->result()));
__ movss(result, operand);
@ -2790,7 +2815,8 @@ void LCodeGen::DoMathLog(LUnaryMathOperation* instr) {
__ ucomisd(input_reg, xmm0);
__ j(above, &positive, Label::kNear);
__ j(equal, &zero, Label::kNear);
ExternalReference nan = ExternalReference::address_of_nan();
ExternalReference nan =
ExternalReference::address_of_canonical_non_hole_nan();
__ movdbl(input_reg, Operand::StaticVariable(nan));
__ jmp(&done, Label::kNear);
__ bind(&zero);
@ -3000,8 +3026,8 @@ void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
LStoreKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
instr->key(), elements_kind));
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
instr->key(), elements_kind, 0));
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
__ cvtsd2ss(xmm0, ToDoubleRegister(instr->value()));
__ movss(operand, xmm0);
@ -3068,6 +3094,28 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
}
void LCodeGen::DoStoreKeyedFastDoubleElement(
LStoreKeyedFastDoubleElement* instr) {
XMMRegister value = ToDoubleRegister(instr->value());
Register elements = ToRegister(instr->elements());
Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
Label have_value;
__ ucomisd(value, value);
__ j(parity_odd, &have_value); // NaN.
ExternalReference canonical_nan_reference =
ExternalReference::address_of_canonical_non_hole_nan();
__ movdbl(value, Operand::StaticVariable(canonical_nan_reference));
__ bind(&have_value);
Operand double_store_operand = BuildFastArrayOperand(
instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
FixedDoubleArray::kHeaderSize - kHeapObjectTag);
__ movdbl(double_store_operand, value);
}
void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
ASSERT(ToRegister(instr->context()).is(esi));
ASSERT(ToRegister(instr->object()).is(edx));
@ -3451,7 +3499,8 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
DeoptimizeIf(not_equal, env);
// Convert undefined to NaN.
ExternalReference nan = ExternalReference::address_of_nan();
ExternalReference nan =
ExternalReference::address_of_canonical_non_hole_nan();
__ movdbl(result_reg, Operand::StaticVariable(nan));
__ jmp(&done, Label::kNear);

7
deps/v8/src/ia32/lithium-codegen-ia32.h

@ -222,9 +222,10 @@ class LCodeGen BASE_EMBEDDED {
Register ToRegister(int index) const;
XMMRegister ToDoubleRegister(int index) const;
int ToInteger32(LConstantOperand* op) const;
Operand BuildExternalArrayOperand(LOperand* external_pointer,
LOperand* key,
JSObject::ElementsKind elements_kind);
Operand BuildFastArrayOperand(LOperand* external_pointer,
LOperand* key,
JSObject::ElementsKind elements_kind,
uint32_t offset);
// Specific math operations - used from DoUnaryMathOperation.
void EmitIntegerMathAbs(LUnaryMathOperation* instr);

35
deps/v8/src/ia32/lithium-ia32.cc

@ -429,6 +429,15 @@ void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
}
void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
elements()->PrintTo(stream);
stream->Add("[");
key()->PrintTo(stream);
stream->Add("] <- ");
value()->PrintTo(stream);
}
void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add("[");
@ -1878,6 +1887,18 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
}
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
HLoadKeyedFastDoubleElement* instr) {
ASSERT(instr->representation().IsDouble());
ASSERT(instr->key()->representation().IsInteger32());
LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result =
new LLoadKeyedFastDoubleElement(elements, key);
return AssignEnvironment(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
HLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
@ -1933,6 +1954,20 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
}
LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
HStoreKeyedFastDoubleElement* instr) {
ASSERT(instr->value()->representation().IsDouble());
ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32());
LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* val = UseTempRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
return new LStoreKeyedFastDoubleElement(elements, key, val);
}
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
HStoreKeyedSpecializedArrayElement* instr) {
Representation representation(instr->value()->representation());

41
deps/v8/src/ia32/lithium-ia32.h

@ -116,6 +116,7 @@ class LCodeGen;
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
V(LoadKeyedFastElement) \
V(LoadKeyedFastDoubleElement) \
V(LoadKeyedGeneric) \
V(LoadKeyedSpecializedArrayElement) \
V(LoadNamedField) \
@ -141,6 +142,7 @@ class LCodeGen;
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
V(StoreKeyedFastDoubleElement) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
V(StoreKeyedSpecializedArrayElement) \
@ -1161,6 +1163,23 @@ class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
};
class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedFastDoubleElement(LOperand* elements,
LOperand* key) {
inputs_[0] = elements;
inputs_[1] = key;
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
"load-keyed-fast-double-element")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
};
class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
@ -1651,6 +1670,28 @@ class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
};
class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedFastDoubleElement(LOperand* elements,
LOperand* key,
LOperand* val) {
inputs_[0] = elements;
inputs_[1] = key;
inputs_[2] = val;
}
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
"store-keyed-fast-double-element")
DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
virtual void PrintDataTo(StringStream* stream);
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
};
class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,

3
deps/v8/src/ia32/macro-assembler-ia32.cc

@ -2043,6 +2043,9 @@ void MacroAssembler::AssertFastElements(Register elements) {
cmp(FieldOperand(elements, HeapObject::kMapOffset),
Immediate(factory->fixed_array_map()));
j(equal, &ok);
cmp(FieldOperand(elements, HeapObject::kMapOffset),
Immediate(factory->fixed_double_array_map()));
j(equal, &ok);
cmp(FieldOperand(elements, HeapObject::kMapOffset),
Immediate(factory->fixed_cow_array_map()));
j(equal, &ok);

157
deps/v8/src/ia32/stub-cache-ia32.cc

@ -3790,6 +3790,71 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
}
void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : key
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss_force_generic, slow_allocate_heapnumber;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
// Check that the key is a smi.
__ JumpIfNotSmi(eax, &miss_force_generic);
// Get the elements array.
__ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
__ AssertFastElements(ecx);
// Check that the key is within bounds.
__ cmp(eax, FieldOperand(ecx, FixedDoubleArray::kLengthOffset));
__ j(above_equal, &miss_force_generic);
// Check for the hole
uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
__ cmp(FieldOperand(ecx, eax, times_4, offset), Immediate(kHoleNanUpper32));
__ j(equal, &miss_force_generic);
// Always allocate a heap number for the result.
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope use_sse2(SSE2);
__ movdbl(xmm0, FieldOperand(ecx, eax, times_4,
FixedDoubleArray::kHeaderSize));
} else {
__ fld_d(FieldOperand(ecx, eax, times_4, FixedDoubleArray::kHeaderSize));
}
__ AllocateHeapNumber(ecx, ebx, edi, &slow_allocate_heapnumber);
// Set the value.
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope use_sse2(SSE2);
__ movdbl(FieldOperand(ecx, HeapNumber::kValueOffset), xmm0);
} else {
__ fstp_d(FieldOperand(ecx, HeapNumber::kValueOffset));
}
__ mov(eax, ecx);
__ ret(0);
__ bind(&slow_allocate_heapnumber);
// A value was pushed on the floating point stack before the allocation, if
// the allocation fails it needs to be removed.
if (!CpuFeatures::IsSupported(SSE2)) {
__ ffree();
__ fincstp();
}
Handle<Code> slow_ic =
masm->isolate()->builtins()->KeyedLoadIC_Slow();
__ jmp(slow_ic, RelocInfo::CODE_TARGET);
__ bind(&miss_force_generic);
Handle<Code> miss_ic =
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
}
void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
@ -3839,6 +3904,98 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
}
void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
// -- eax : value
// -- ecx : key
// -- edx : receiver
// -- esp[0] : return address
// -----------------------------------
Label miss_force_generic, smi_value, is_nan, maybe_nan;
Label have_double_value, not_nan;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
// Check that the key is a smi.
__ JumpIfNotSmi(ecx, &miss_force_generic);
// Get the elements array.
__ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
__ AssertFastElements(edi);
if (is_js_array) {
// Check that the key is within bounds.
__ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
} else {
// Check that the key is within bounds.
__ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
}
__ j(above_equal, &miss_force_generic);
__ JumpIfSmi(eax, &smi_value, Label::kNear);
__ CheckMap(eax,
masm->isolate()->factory()->heap_number_map(),
&miss_force_generic,
DONT_DO_SMI_CHECK);
// Double value, canonicalize NaN.
uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
__ cmp(FieldOperand(eax, offset), Immediate(kNaNOrInfinityLowerBoundUpper32));
__ j(greater_equal, &maybe_nan, Label::kNear);
__ bind(&not_nan);
ExternalReference canonical_nan_reference =
ExternalReference::address_of_canonical_non_hole_nan();
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope use_sse2(SSE2);
__ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
__ bind(&have_double_value);
__ movdbl(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize),
xmm0);
__ ret(0);
} else {
__ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
__ bind(&have_double_value);
__ fstp_d(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize));
__ ret(0);
}
__ bind(&maybe_nan);
// Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
// it's an Infinity, and the non-NaN code path applies.
__ j(greater, &is_nan, Label::kNear);
__ cmp(FieldOperand(eax, HeapNumber::kValueOffset), Immediate(0));
__ j(zero, &not_nan);
__ bind(&is_nan);
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope use_sse2(SSE2);
__ movdbl(xmm0, Operand::StaticVariable(canonical_nan_reference));
} else {
__ fld_d(Operand::StaticVariable(canonical_nan_reference));
}
__ jmp(&have_double_value, Label::kNear);
__ bind(&smi_value);
// Value is a smi. convert to a double and store.
__ SmiUntag(eax);
__ push(eax);
__ fild_s(Operand(esp, 0));
__ pop(eax);
__ fstp_d(FieldOperand(edi, ecx, times_4, FixedDoubleArray::kHeaderSize));
__ ret(0);
// Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic);
Handle<Code> ic_force_generic =
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
}
#undef __
} } // namespace v8::internal

8
deps/v8/src/jsregexp.cc

@ -1,4 +1,4 @@
// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -1958,13 +1958,10 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
ASSERT(characters_filled_in < details->characters());
int characters = details->characters();
int char_mask;
int char_shift;
if (compiler->ascii()) {
char_mask = String::kMaxAsciiCharCode;
char_shift = 8;
} else {
char_mask = String::kMaxUC16CharCode;
char_shift = 16;
}
for (int k = 0; k < elms_->length(); k++) {
TextElement elm = elms_->at(k);
@ -4888,7 +4885,6 @@ void TextNode::CalculateOffsets() {
cp_offset += elm.data.u_atom->data().length();
} else {
cp_offset++;
Vector<const uc16> quarks = elm.data.u_atom->data();
}
}
}
@ -5327,8 +5323,6 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
return CompilationResult(error_message);
}
NodeInfo info = *node->info();
// Create the correct assembler for the architecture.
#ifndef V8_INTERPRETED_REGEXP
// Native regexp implementation.

19
deps/v8/src/messages.js

@ -195,7 +195,8 @@ function FormatMessage(message) {
non_extensible_proto: ["%0", " is not extensible"],
handler_non_object: ["Proxy.", "%0", " called with non-object as handler"],
handler_trap_missing: ["Proxy handler ", "%0", " has no '", "%1", "' trap"],
handler_failed: ["Proxy handler ", "%0", " returned false for '", "%1", "' trap"],
handler_returned_false: ["Proxy handler ", "%0", " returned false for '", "%1", "' trap"],
handler_returned_undefined: ["Proxy handler ", "%0", " returned undefined for '", "%1", "' trap"],
proxy_prop_not_configurable: ["Trap ", "%1", " of proxy handler ", "%0", " returned non-configurable descriptor for property ", "%2"],
proxy_non_object_prop_names: ["Trap ", "%1", " returned non-object ", "%0"],
proxy_repeated_prop_name: ["Trap ", "%1", " returned repeated property name ", "%2"],
@ -1050,13 +1051,15 @@ function captureStackTrace(obj, cons_opt) {
$Math.__proto__ = global.Object.prototype;
DefineError(function Error() { });
DefineError(function TypeError() { });
DefineError(function RangeError() { });
DefineError(function SyntaxError() { });
DefineError(function ReferenceError() { });
DefineError(function EvalError() { });
DefineError(function URIError() { });
// DefineError is a native function. Use explicit receiver. Otherwise
// the receiver will be 'undefined'.
this.DefineError(function Error() { });
this.DefineError(function TypeError() { });
this.DefineError(function RangeError() { });
this.DefineError(function SyntaxError() { });
this.DefineError(function ReferenceError() { });
this.DefineError(function EvalError() { });
this.DefineError(function URIError() { });
$Error.captureStackTrace = captureStackTrace;

7
deps/v8/src/mips/assembler-mips.cc

@ -285,7 +285,7 @@ Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size)
unbound_labels_count_ = 0;
block_buffer_growth_ = false;
ast_id_for_reloc_info_ = kNoASTId;
ClearRecordedAstId();
}
@ -1947,9 +1947,8 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
}
ASSERT(buffer_space() >= kMaxRelocSize); // Too late to grow buffer here.
if (rmode == RelocInfo::CODE_TARGET_WITH_ID) {
ASSERT(ast_id_for_reloc_info_ != kNoASTId);
RelocInfo reloc_info_with_ast_id(pc_, rmode, ast_id_for_reloc_info_);
ast_id_for_reloc_info_ = kNoASTId;
RelocInfo reloc_info_with_ast_id(pc_, rmode, RecordedAstId());
ClearRecordedAstId();
reloc_info_writer.Write(&reloc_info_with_ast_id);
} else {
reloc_info_writer.Write(&rinfo);

14
deps/v8/src/mips/assembler-mips.h

@ -833,7 +833,17 @@ class Assembler : public AssemblerBase {
// Record the AST id of the CallIC being compiled, so that it can be placed
// in the relocation information.
void RecordAstId(unsigned ast_id) { ast_id_for_reloc_info_ = ast_id; }
void SetRecordedAstId(unsigned ast_id) {
ASSERT(recorded_ast_id_ == kNoASTId);
recorded_ast_id_ = ast_id;
}
unsigned RecordedAstId() {
ASSERT(recorded_ast_id_ != kNoASTId);
return recorded_ast_id_;
}
void ClearRecordedAstId() { recorded_ast_id_ = kNoASTId; }
// Record a comment relocation entry that can be used by a disassembler.
// Use --code-comments to enable.
@ -926,7 +936,7 @@ class Assembler : public AssemblerBase {
// Relocation for a type-recording IC has the AST id added to it. This
// member variable is a way to pass the information from the call site to
// the relocation info.
unsigned ast_id_for_reloc_info_;
unsigned recorded_ast_id_;
bool emit_debug_code() const { return emit_debug_code_; }

1
deps/v8/src/mips/code-stubs-mips.cc

@ -4913,6 +4913,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ li(a0, Operand(argc_)); // Setup the number of arguments.
__ mov(a2, zero_reg);
__ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION);
__ SetCallKind(t1, CALL_AS_METHOD);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET);
}

5
deps/v8/src/mips/macro-assembler-mips.cc

@ -2080,8 +2080,7 @@ void MacroAssembler::Call(Handle<Code> code,
bind(&start);
ASSERT(RelocInfo::IsCodeTarget(rmode));
if (rmode == RelocInfo::CODE_TARGET && ast_id != kNoASTId) {
ASSERT(ast_id_for_reloc_info_ == kNoASTId);
ast_id_for_reloc_info_ = ast_id;
SetRecordedAstId(ast_id);
rmode = RelocInfo::CODE_TARGET_WITH_ID;
}
Call(reinterpret_cast<Address>(code.location()), rmode, cond, rs, rt, bd);
@ -3701,6 +3700,8 @@ void MacroAssembler::AssertFastElements(Register elements) {
lw(elements, FieldMemOperand(elements, HeapObject::kMapOffset));
LoadRoot(at, Heap::kFixedArrayMapRootIndex);
Branch(&ok, eq, elements, Operand(at));
LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex);
Branch(&ok, eq, elements, Operand(at));
LoadRoot(at, Heap::kFixedCOWArrayMapRootIndex);
Branch(&ok, eq, elements, Operand(at));
Abort("JSObject with fast elements map has slow elements");

189
deps/v8/src/mips/stub-cache-mips.cc

@ -4229,6 +4229,75 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
}
void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- ra : return address
// -- a0 : key
// -- a1 : receiver
// -----------------------------------
Label miss_force_generic, slow_allocate_heapnumber;
Register key_reg = a0;
Register receiver_reg = a1;
Register elements_reg = a2;
Register heap_number_reg = a2;
Register indexed_double_offset = a3;
Register scratch = t0;
Register scratch2 = t1;
Register scratch3 = t2;
Register heap_number_map = t3;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
// Check that the key is a smi.
__ JumpIfNotSmi(key_reg, &miss_force_generic);
// Get the elements array.
__ lw(elements_reg,
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
// Check that the key is within bounds.
__ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
__ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
// Load the upper word of the double in the fixed array and test for NaN.
__ sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize);
__ Addu(indexed_double_offset, elements_reg, Operand(scratch2));
uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32);
__ lw(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset));
__ Branch(&miss_force_generic, eq, scratch, Operand(kHoleNanUpper32));
// Non-NaN. Allocate a new heap number and copy the double value into it.
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
__ AllocateHeapNumber(heap_number_reg, scratch2, scratch3,
heap_number_map, &slow_allocate_heapnumber);
// Don't need to reload the upper 32 bits of the double, it's already in
// scratch.
__ sw(scratch, FieldMemOperand(heap_number_reg,
HeapNumber::kExponentOffset));
__ lw(scratch, FieldMemOperand(indexed_double_offset,
FixedArray::kHeaderSize));
__ sw(scratch, FieldMemOperand(heap_number_reg,
HeapNumber::kMantissaOffset));
__ mov(v0, heap_number_reg);
__ Ret();
__ bind(&slow_allocate_heapnumber);
Handle<Code> slow_ic =
masm->isolate()->builtins()->KeyedLoadIC_Slow();
__ Jump(slow_ic, RelocInfo::CODE_TARGET);
__ bind(&miss_force_generic);
Handle<Code> miss_ic =
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
__ Jump(miss_ic, RelocInfo::CODE_TARGET);
}
void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
@ -4292,6 +4361,126 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
}
void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
// -- a0 : value
// -- a1 : key
// -- a2 : receiver
// -- ra : return address
// -- a3 : scratch
// -- t0 : scratch (elements_reg)
// -- t1 : scratch (mantissa_reg)
// -- t2 : scratch (exponent_reg)
// -- t3 : scratch4
// -----------------------------------
Label miss_force_generic, smi_value, is_nan, maybe_nan, have_double_value;
Register value_reg = a0;
Register key_reg = a1;
Register receiver_reg = a2;
Register scratch = a3;
Register elements_reg = t0;
Register mantissa_reg = t1;
Register exponent_reg = t2;
Register scratch4 = t3;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
__ JumpIfNotSmi(key_reg, &miss_force_generic);
__ lw(elements_reg,
FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
// Check that the key is within bounds.
if (is_js_array) {
__ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
} else {
__ lw(scratch,
FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
}
// Compare smis, unsigned compare catches both negative and out-of-bound
// indexes.
__ Branch(&miss_force_generic, hs, key_reg, Operand(scratch));
// Handle smi values specially.
__ JumpIfSmi(value_reg, &smi_value);
// Ensure that the object is a heap number
__ CheckMap(value_reg,
scratch,
masm->isolate()->factory()->heap_number_map(),
&miss_force_generic,
DONT_DO_SMI_CHECK);
// Check for nan: all NaN values have a value greater (signed) than 0x7ff00000
// in the exponent.
__ li(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
__ lw(exponent_reg, FieldMemOperand(value_reg, HeapNumber::kExponentOffset));
__ Branch(&maybe_nan, ge, exponent_reg, Operand(scratch));
__ lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
__ bind(&have_double_value);
__ sll(scratch4, key_reg, kDoubleSizeLog2 - kSmiTagSize);
__ Addu(scratch, elements_reg, Operand(scratch4));
__ sw(mantissa_reg, FieldMemOperand(scratch, FixedDoubleArray::kHeaderSize));
uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
__ sw(exponent_reg, FieldMemOperand(scratch, offset));
__ Ret();
__ bind(&maybe_nan);
// Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
// it's an Infinity, and the non-NaN code path applies.
__ li(scratch, Operand(kNaNOrInfinityLowerBoundUpper32));
__ Branch(&is_nan, gt, exponent_reg, Operand(scratch));
__ lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset));
__ Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg));
__ bind(&is_nan);
// Load canonical NaN for storing into the double array.
uint64_t nan_int64 = BitCast<uint64_t>(
FixedDoubleArray::canonical_not_the_hole_nan_as_double());
__ li(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64)));
__ li(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32)));
__ jmp(&have_double_value);
__ bind(&smi_value);
__ Addu(scratch, elements_reg,
Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag));
__ sll(scratch4, key_reg, kDoubleSizeLog2 - kSmiTagSize);
__ Addu(scratch, scratch, scratch4);
// scratch is now effective address of the double element
FloatingPointHelper::Destination destination;
if (CpuFeatures::IsSupported(FPU)) {
destination = FloatingPointHelper::kFPURegisters;
} else {
destination = FloatingPointHelper::kCoreRegisters;
}
__ SmiUntag(value_reg, value_reg);
FloatingPointHelper::ConvertIntToDouble(
masm, value_reg, destination,
f0, mantissa_reg, exponent_reg, // These are: double_dst, dst1, dst2.
scratch4, f2); // These are: scratch2, single_scratch.
if (destination == FloatingPointHelper::kFPURegisters) {
CpuFeatures::Scope scope(FPU);
__ sdc1(f0, MemOperand(scratch, 0));
} else {
__ sw(mantissa_reg, MemOperand(scratch, 0));
__ sw(exponent_reg, MemOperand(scratch, Register::kSizeInBytes));
}
__ Ret();
// Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic);
Handle<Code> ic =
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ Jump(ic, RelocInfo::CODE_TARGET);
}
#undef __
} } // namespace v8::internal

41
deps/v8/src/mirror-debugger.js

@ -1250,9 +1250,9 @@ const kFrameDetailsNameIndex = 0;
const kFrameDetailsValueIndex = 1;
const kFrameDetailsNameValueSize = 2;
const kFrameDetailsFlagDebuggerFrame = 1;
const kFrameDetailsFlagOptimizedFrame = 2;
const kFrameDetailsFlagInlinedFrame = 4;
const kFrameDetailsFlagDebuggerFrameMask = 1 << 0;
const kFrameDetailsFlagOptimizedFrameMask = 1 << 1;
const kFrameDetailsFlagInlinedFrameIndexMask = 7 << 2;
/**
* Wrapper for the frame details information retreived from the VM. The frame
@ -1266,7 +1266,7 @@ const kFrameDetailsFlagInlinedFrame = 4;
* 5: Source position
* 6: Construct call
* 7: Is at return
* 8: Flags (debugger frame, optimized frame, inlined frame)
* 8: Flags (debugger frame, optimized frame, inlined frame index)
* Arguments name, value
* Locals name, value
* Return value if any
@ -1312,22 +1312,27 @@ FrameDetails.prototype.isAtReturn = function() {
FrameDetails.prototype.isDebuggerFrame = function() {
%CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagDebuggerFrame;
var f = kFrameDetailsFlagDebuggerFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
}
FrameDetails.prototype.isOptimizedFrame = function() {
%CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagOptimizedFrame;
var f = kFrameDetailsFlagOptimizedFrameMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
}
FrameDetails.prototype.isInlinedFrame = function() {
return this.inlinedFrameIndex() > 0;
}
FrameDetails.prototype.inlinedFrameIndex = function() {
%CheckExecutionState(this.break_id_);
var f = kFrameDetailsFlagInlinedFrame;
return (this.details_[kFrameDetailsFlagsIndex] & f) == f;
var f = kFrameDetailsFlagInlinedFrameIndexMask;
return (this.details_[kFrameDetailsFlagsIndex] & f) >> 2
}
@ -1476,6 +1481,11 @@ FrameMirror.prototype.isInlinedFrame = function() {
};
FrameMirror.prototype.inlinedFrameIndex = function() {
return this.details_.inlinedFrameIndex();
};
FrameMirror.prototype.argumentCount = function() {
return this.details_.argumentCount();
};
@ -1565,8 +1575,12 @@ FrameMirror.prototype.scope = function(index) {
FrameMirror.prototype.evaluate = function(source, disable_break, opt_context_object) {
var result = %DebugEvaluate(this.break_id_, this.details_.frameId(),
source, Boolean(disable_break), opt_context_object);
var result = %DebugEvaluate(this.break_id_,
this.details_.frameId(),
this.details_.inlinedFrameIndex(),
source,
Boolean(disable_break),
opt_context_object);
return MakeMirror(result);
};
@ -1591,8 +1605,10 @@ FrameMirror.prototype.invocationText = function() {
// Try to find the function as a property in the receiver. Include the
// prototype chain in the lookup.
var property = GetUndefinedMirror();
if (!receiver.isUndefined()) {
for (var r = receiver; !r.isNull() && property.isUndefined(); r = r.protoObject()) {
if (receiver.isObject()) {
for (var r = receiver;
!r.isNull() && property.isUndefined();
r = r.protoObject()) {
property = r.lookupProperty(func);
}
}
@ -1719,6 +1735,7 @@ function ScopeDetails(frame, index) {
this.break_id_ = frame.break_id_;
this.details_ = %GetScopeDetails(frame.break_id_,
frame.details_.frameId(),
frame.details_.inlinedFrameIndex(),
index);
}

2
deps/v8/src/natives.h

@ -36,7 +36,7 @@ typedef bool (*NativeSourceCallback)(Vector<const char> name,
int index);
enum NativeType {
CORE, EXPERIMENTAL, D8
CORE, EXPERIMENTAL, D8, TEST
};
template <NativeType type>

3
deps/v8/src/objects-debug.cc

@ -315,7 +315,8 @@ void FixedDoubleArray::FixedDoubleArrayVerify() {
if (!is_the_hole(i)) {
double value = get(i);
ASSERT(!isnan(value) ||
BitCast<uint64_t>(value) == kCanonicalNonHoleNanInt64);
(BitCast<uint64_t>(value) ==
BitCast<uint64_t>(canonical_not_the_hole_nan_as_double())));
}
}
}

37
deps/v8/src/objects-inl.h

@ -1610,6 +1610,23 @@ void FixedArray::set(int index, Object* value) {
}
inline bool FixedDoubleArray::is_the_hole_nan(double value) {
return BitCast<uint64_t, double>(value) == kHoleNanInt64;
}
inline double FixedDoubleArray::hole_nan_as_double() {
return BitCast<double, uint64_t>(kHoleNanInt64);
}
inline double FixedDoubleArray::canonical_not_the_hole_nan_as_double() {
ASSERT(BitCast<uint64_t>(OS::nan_value()) != kHoleNanInt64);
ASSERT((BitCast<uint64_t>(OS::nan_value()) >> 32) != kHoleNanUpper32);
return OS::nan_value();
}
double FixedDoubleArray::get(int index) {
ASSERT(map() != HEAP->fixed_cow_array_map() &&
map() != HEAP->fixed_array_map());
@ -3744,6 +3761,7 @@ void JSBuiltinsObject::set_javascript_builtin_code(Builtins::JavaScript id,
ACCESSORS(JSProxy, handler, Object, kHandlerOffset)
ACCESSORS(JSProxy, padding, Object, kPaddingOffset)
Address Foreign::address() {
@ -3989,7 +4007,8 @@ bool JSObject::HasIndexedInterceptor() {
bool JSObject::AllowsSetElementsLength() {
bool result = elements()->IsFixedArray();
bool result = elements()->IsFixedArray() ||
elements()->IsFixedDoubleArray();
ASSERT(result == !HasExternalArrayElements());
return result;
}
@ -4139,6 +4158,22 @@ Object* JSReceiver::GetPrototype() {
}
bool JSReceiver::HasProperty(String* name) {
if (IsJSProxy()) {
return JSProxy::cast(this)->HasPropertyWithHandler(name);
}
return GetPropertyAttribute(name) != ABSENT;
}
bool JSReceiver::HasLocalProperty(String* name) {
if (IsJSProxy()) {
return JSProxy::cast(this)->HasPropertyWithHandler(name);
}
return GetLocalPropertyAttribute(name) != ABSENT;
}
PropertyAttributes JSReceiver::GetPropertyAttribute(String* key) {
return GetPropertyAttributeWithReceiver(this, key);
}

255
deps/v8/src/objects.cc

@ -58,11 +58,6 @@ namespace internal {
const int kGetterIndex = 0;
const int kSetterIndex = 1;
uint64_t FixedDoubleArray::kHoleNanInt64 = -1;
uint64_t FixedDoubleArray::kCanonicalNonHoleNanLower32 = 0x7FF00000;
uint64_t FixedDoubleArray::kCanonicalNonHoleNanInt64 =
kCanonicalNonHoleNanLower32 << 32;
MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor,
Object* value) {
Object* result;
@ -194,7 +189,7 @@ MaybeObject* Object::GetPropertyWithCallback(Object* receiver,
AccessorInfo* data = AccessorInfo::cast(structure);
Object* fun_obj = data->getter();
v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj);
HandleScope scope;
HandleScope scope(isolate);
JSObject* self = JSObject::cast(receiver);
JSObject* holder_handle = JSObject::cast(holder);
Handle<String> key(name);
@ -234,7 +229,7 @@ MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw,
String* name_raw,
Object* handler_raw) {
Isolate* isolate = name_raw->GetIsolate();
HandleScope scope;
HandleScope scope(isolate);
Handle<Object> receiver(receiver_raw);
Handle<Object> name(name_raw);
Handle<Object> handler(handler_raw);
@ -2178,9 +2173,9 @@ MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(
}
}
HandleScope scope;
Handle<Object> value_handle(value);
Heap* heap = GetHeap();
HandleScope scope(heap->isolate());
Handle<Object> value_handle(value);
heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
return *value_handle;
}
@ -2201,13 +2196,38 @@ MaybeObject* JSReceiver::SetProperty(LookupResult* result,
}
bool JSProxy::HasPropertyWithHandler(String* name_raw) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<Object> receiver(this);
Handle<Object> name(name_raw);
Handle<Object> handler(this->handler());
// Extract trap function.
Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("has");
Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
if (trap->IsUndefined()) {
trap = isolate->derived_has_trap();
}
// Call trap function.
Object** args[] = { name.location() };
bool has_exception;
Handle<Object> result =
Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
if (has_exception) return Failure::Exception();
return result->ToBoolean()->IsTrue();
}
MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
String* name_raw,
Object* value_raw,
PropertyAttributes attributes,
StrictModeFlag strict_mode) {
Isolate* isolate = GetIsolate();
HandleScope scope;
HandleScope scope(isolate);
Handle<Object> receiver(this);
Handle<Object> name(name_raw);
Handle<Object> value(value_raw);
@ -2225,11 +2245,48 @@ MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler(
receiver.location(), name.location(), value.location()
};
bool has_exception;
Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
if (has_exception) return Failure::Exception();
return *value;
}
MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler(
String* name_raw, DeleteMode mode) {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<Object> receiver(this);
Handle<Object> name(name_raw);
Handle<Object> handler(this->handler());
// Extract trap function.
Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete");
Handle<Object> trap(v8::internal::GetProperty(handler, trap_name));
if (trap->IsUndefined()) {
Handle<Object> args[] = { handler, trap_name };
Handle<Object> error = isolate->factory()->NewTypeError(
"handler_trap_missing", HandleVector(args, ARRAY_SIZE(args)));
isolate->Throw(*error);
return Failure::Exception();
}
// Call trap function.
Object** args[] = { name.location() };
bool has_exception;
Handle<Object> result =
Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception);
if (has_exception) return Failure::Exception();
return *value;
Object* bool_result = result->ToBoolean();
if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) {
Handle<Object> args[] = { handler, trap_name };
Handle<Object> error = isolate->factory()->NewTypeError(
"handler_failed", HandleVector(args, ARRAY_SIZE(args)));
isolate->Throw(*error);
return Failure::Exception();
}
return bool_result;
}
@ -2238,7 +2295,7 @@ MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
String* name_raw,
bool* has_exception) {
Isolate* isolate = GetIsolate();
HandleScope scope;
HandleScope scope(isolate);
Handle<JSReceiver> receiver(receiver_raw);
Handle<Object> name(name_raw);
Handle<Object> handler(this->handler());
@ -2268,6 +2325,18 @@ MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler(
}
void JSProxy::Fix() {
Isolate* isolate = GetIsolate();
HandleScope scope(isolate);
Handle<JSProxy> self(this);
isolate->factory()->BecomeJSObject(self);
ASSERT(IsJSObject());
// TODO(rossberg): recognize function proxies.
}
MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
String* name,
Object* value,
@ -2327,7 +2396,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result,
}
if (result->IsReadOnly() && result->IsProperty()) {
if (strict_mode == kStrictMode) {
HandleScope scope;
HandleScope scope(heap->isolate());
Handle<String> key(name);
Handle<Object> holder(this);
Handle<Object> args[2] = { key, holder };
@ -2811,16 +2880,18 @@ MaybeObject* JSObject::NormalizeElements() {
ASSERT(!HasExternalArrayElements());
// Find the backing store.
FixedArray* array = FixedArray::cast(elements());
FixedArrayBase* array = FixedArrayBase::cast(elements());
Map* old_map = array->map();
bool is_arguments =
(old_map == old_map->heap()->non_strict_arguments_elements_map());
if (is_arguments) {
array = FixedArray::cast(array->get(1));
array = FixedArrayBase::cast(FixedArray::cast(array)->get(1));
}
if (array->IsDictionary()) return array;
ASSERT(HasFastElements() || HasFastArgumentsElements());
ASSERT(HasFastElements() ||
HasFastDoubleElements() ||
HasFastArgumentsElements());
// Compute the effective length and allocate a new backing store.
int length = IsJSArray()
? Smi::cast(JSArray::cast(this)->length())->value()
@ -2833,7 +2904,7 @@ MaybeObject* JSObject::NormalizeElements() {
}
// Copy the elements to the new backing store.
bool has_double_elements = old_map->has_fast_double_elements();
bool has_double_elements = array->IsFixedDoubleArray();
for (int i = 0; i < length; i++) {
Object* value = NULL;
if (has_double_elements) {
@ -2851,7 +2922,7 @@ MaybeObject* JSObject::NormalizeElements() {
}
} else {
ASSERT(old_map->has_fast_elements());
value = array->get(i);
value = FixedArray::cast(array)->get(i);
}
PropertyDetails details = PropertyDetails(NONE, NORMAL);
if (!value->IsTheHole()) {
@ -3135,7 +3206,7 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
case FAST_DOUBLE_ELEMENTS: {
int length = IsJSArray()
? Smi::cast(JSArray::cast(this)->length())->value()
: FixedArray::cast(elements())->length();
: FixedDoubleArray::cast(elements())->length();
if (index < static_cast<uint32_t>(length)) {
FixedDoubleArray::cast(elements())->set_the_hole(index);
}
@ -3179,6 +3250,15 @@ MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) {
}
MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) {
if (IsJSProxy()) {
return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode);
} else {
return JSObject::cast(this)->DeleteProperty(name, mode);
}
}
MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) {
Isolate* isolate = GetIsolate();
// ECMA-262, 3rd, 8.6.2.5
@ -7317,22 +7397,28 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
new_map = Map::cast(object);
}
AssertNoAllocation no_gc;
WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
switch (GetElementsKind()) {
case FAST_ELEMENTS:
case FAST_ELEMENTS: {
AssertNoAllocation no_gc;
WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode);
set_map(new_map);
set_elements(new_elements);
break;
case DICTIONARY_ELEMENTS:
}
case DICTIONARY_ELEMENTS: {
AssertNoAllocation no_gc;
WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
CopySlowElementsToFast(NumberDictionary::cast(elements()),
new_elements,
mode);
set_map(new_map);
set_elements(new_elements);
break;
}
case NON_STRICT_ARGUMENTS_ELEMENTS: {
AssertNoAllocation no_gc;
WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc);
// The object's map and the parameter map are unchanged, the unaliased
// arguments are copied to the new backing store.
FixedArray* parameter_map = FixedArray::cast(elements());
@ -7368,6 +7454,8 @@ MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity,
new_elements->set(i, obj, UPDATE_WRITE_BARRIER);
}
}
set_map(new_map);
set_elements(new_elements);
break;
}
case EXTERNAL_BYTE_ELEMENTS:
@ -7430,7 +7518,9 @@ MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength(
break;
}
ASSERT(new_map->has_fast_double_elements());
set_map(new_map);
ASSERT(elems->IsFixedDoubleArray());
set_elements(elems);
if (IsJSArray()) {
@ -7520,7 +7610,7 @@ void JSArray::Expand(int required_size) {
static Failure* ArrayLengthRangeError(Heap* heap) {
HandleScope scope;
HandleScope scope(heap->isolate());
return heap->isolate()->Throw(
*FACTORY->NewRangeError("invalid_array_length",
HandleVector<Object>(NULL, 0)));
@ -7536,32 +7626,57 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
const int value = Smi::cast(smi_length)->value();
if (value < 0) return ArrayLengthRangeError(GetHeap());
switch (GetElementsKind()) {
case FAST_ELEMENTS: {
int old_capacity = FixedArray::cast(elements())->length();
JSObject::ElementsKind elements_kind = GetElementsKind();
switch (elements_kind) {
case FAST_ELEMENTS:
case FAST_DOUBLE_ELEMENTS: {
int old_capacity = FixedArrayBase::cast(elements())->length();
if (value <= old_capacity) {
if (IsJSArray()) {
Object* obj;
{ MaybeObject* maybe_obj = EnsureWritableFastElements();
if (elements_kind == FAST_ELEMENTS) {
MaybeObject* maybe_obj = EnsureWritableFastElements();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
FixedArray* fast_elements = FixedArray::cast(elements());
if (2 * value <= old_capacity) {
// If more than half the elements won't be used, trim the array.
if (value == 0) {
initialize_elements();
} else {
fast_elements->set_length(value);
Address filler_start = fast_elements->address() +
FixedArray::OffsetOfElementAt(value);
int filler_size = (old_capacity - value) * kPointerSize;
Address filler_start;
int filler_size;
if (GetElementsKind() == FAST_ELEMENTS) {
FixedArray* fast_elements = FixedArray::cast(elements());
fast_elements->set_length(value);
filler_start = fast_elements->address() +
FixedArray::OffsetOfElementAt(value);
filler_size = (old_capacity - value) * kPointerSize;
} else {
ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
FixedDoubleArray* fast_double_elements =
FixedDoubleArray::cast(elements());
fast_double_elements->set_length(value);
filler_start = fast_double_elements->address() +
FixedDoubleArray::OffsetOfElementAt(value);
filler_size = (old_capacity - value) * kDoubleSize;
}
GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
}
} else {
// Otherwise, fill the unused tail with holes.
int old_length = FastD2I(JSArray::cast(this)->length()->Number());
for (int i = value; i < old_length; i++) {
fast_elements->set_the_hole(i);
if (GetElementsKind() == FAST_ELEMENTS) {
FixedArray* fast_elements = FixedArray::cast(elements());
for (int i = value; i < old_length; i++) {
fast_elements->set_the_hole(i);
}
} else {
ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
FixedDoubleArray* fast_double_elements =
FixedDoubleArray::cast(elements());
for (int i = value; i < old_length; i++) {
fast_double_elements->set_the_hole(i);
}
}
}
JSArray::cast(this)->set_length(Smi::cast(smi_length));
@ -7572,8 +7687,14 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
int new_capacity = value > min ? value : min;
if (new_capacity <= kMaxFastElementsLength ||
!ShouldConvertToSlowElements(new_capacity)) {
MaybeObject* result =
SetFastElementsCapacityAndLength(new_capacity, value);
MaybeObject* result;
if (GetElementsKind() == FAST_ELEMENTS) {
result = SetFastElementsCapacityAndLength(new_capacity, value);
} else {
ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS);
result = SetFastDoubleElementsCapacityAndLength(new_capacity,
value);
}
if (result->IsFailure()) return result;
return this;
}
@ -7609,7 +7730,6 @@ MaybeObject* JSObject::SetElementsLength(Object* len) {
case EXTERNAL_FLOAT_ELEMENTS:
case EXTERNAL_DOUBLE_ELEMENTS:
case EXTERNAL_PIXEL_ELEMENTS:
case FAST_DOUBLE_ELEMENTS:
UNREACHABLE();
break;
}
@ -7718,7 +7838,7 @@ MaybeObject* JSReceiver::SetPrototype(Object* value,
// or [[Extensible]] must not violate the invariants defined in the preceding
// paragraph.
if (!this->map()->is_extensible()) {
HandleScope scope;
HandleScope scope(heap->isolate());
Handle<Object> handle(this, heap->isolate());
return heap->isolate()->Throw(
*FACTORY->NewTypeError("non_extensible_proto",
@ -7732,7 +7852,7 @@ MaybeObject* JSReceiver::SetPrototype(Object* value,
for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) {
if (JSObject::cast(pt) == this) {
// Cycle detected.
HandleScope scope;
HandleScope scope(heap->isolate());
return heap->isolate()->Throw(
*FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0)));
}
@ -8022,6 +8142,15 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
!FixedArray::cast(elements())->get(index)->IsTheHole()) return true;
break;
}
case FAST_DOUBLE_ELEMENTS: {
uint32_t length = IsJSArray() ?
static_cast<uint32_t>
(Smi::cast(JSArray::cast(this)->length())->value()) :
static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length());
if ((index < length) &&
!FixedDoubleArray::cast(elements())->is_the_hole(index)) return true;
break;
}
case EXTERNAL_PIXEL_ELEMENTS: {
ExternalPixelArray* pixels = ExternalPixelArray::cast(elements());
if (index < static_cast<uint32_t>(pixels->length())) {
@ -8043,9 +8172,6 @@ bool JSObject::HasElementWithReceiver(JSReceiver* receiver, uint32_t index) {
}
break;
}
case FAST_DOUBLE_ELEMENTS:
UNREACHABLE();
break;
case DICTIONARY_ELEMENTS: {
if (element_dictionary()->FindEntry(index)
!= NumberDictionary::kNotFound) {
@ -8407,8 +8533,9 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
} else {
new_length = dictionary->max_number_key() + 1;
}
MaybeObject* result =
SetFastElementsCapacityAndLength(new_length, new_length);
MaybeObject* result = ShouldConvertToFastDoubleElements()
? SetFastDoubleElementsCapacityAndLength(new_length, new_length)
: SetFastElementsCapacityAndLength(new_length, new_length);
if (result->IsFailure()) return result;
#ifdef DEBUG
if (FLAG_trace_normalization) {
@ -8495,6 +8622,9 @@ MUST_USE_RESULT MaybeObject* JSObject::SetFastDoubleElement(
}
// Otherwise default to slow case.
ASSERT(HasFastDoubleElements());
ASSERT(map()->has_fast_double_elements());
ASSERT(elements()->IsFixedDoubleArray());
Object* obj;
{ MaybeObject* maybe_obj = NormalizeElements();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
@ -8512,7 +8642,7 @@ MaybeObject* JSObject::SetElement(uint32_t index,
if (IsAccessCheckNeeded()) {
Heap* heap = GetHeap();
if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) {
HandleScope scope;
HandleScope scope(heap->isolate());
Handle<Object> value_handle(value);
heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET);
return *value_handle;
@ -8948,10 +9078,13 @@ bool JSObject::HasDenseElements() {
int capacity = 0;
int number_of_elements = 0;
FixedArray* backing_store = FixedArray::cast(elements());
FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements());
FixedArray* backing_store = NULL;
switch (GetElementsKind()) {
case NON_STRICT_ARGUMENTS_ELEMENTS:
backing_store = FixedArray::cast(backing_store->get(1));
backing_store_base =
FixedArray::cast(FixedArray::cast(backing_store_base)->get(1));
backing_store = FixedArray::cast(backing_store_base);
if (backing_store->IsDictionary()) {
NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
capacity = dictionary->Capacity();
@ -8960,13 +9093,15 @@ bool JSObject::HasDenseElements() {
}
// Fall through.
case FAST_ELEMENTS:
backing_store = FixedArray::cast(backing_store_base);
capacity = backing_store->length();
for (int i = 0; i < capacity; ++i) {
if (!backing_store->get(i)->IsTheHole()) ++number_of_elements;
}
break;
case DICTIONARY_ELEMENTS: {
NumberDictionary* dictionary = NumberDictionary::cast(backing_store);
NumberDictionary* dictionary =
NumberDictionary::cast(FixedArray::cast(elements()));
capacity = dictionary->Capacity();
number_of_elements = dictionary->NumberOfElements();
break;
@ -9474,6 +9609,21 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
ASSERT(!storage || storage->length() >= counter);
break;
}
case FAST_DOUBLE_ELEMENTS: {
int length = IsJSArray() ?
Smi::cast(JSArray::cast(this)->length())->value() :
FixedDoubleArray::cast(elements())->length();
for (int i = 0; i < length; i++) {
if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) {
if (storage != NULL) {
storage->set(counter, Smi::FromInt(i));
}
counter++;
}
}
ASSERT(!storage || storage->length() >= counter);
break;
}
case EXTERNAL_PIXEL_ELEMENTS: {
int length = ExternalPixelArray::cast(elements())->length();
while (counter < length) {
@ -9503,9 +9653,6 @@ int JSObject::GetLocalElementKeys(FixedArray* storage,
ASSERT(!storage || storage->length() >= counter);
break;
}
case FAST_DOUBLE_ELEMENTS:
UNREACHABLE();
break;
case DICTIONARY_ELEMENTS: {
if (storage != NULL) {
element_dictionary()->CopyKeysTo(storage,
@ -11053,11 +11200,11 @@ void NumberDictionary::RemoveNumberEntries(uint32_t from, uint32_t to) {
template<typename Shape, typename Key>
Object* Dictionary<Shape, Key>::DeleteProperty(int entry,
JSObject::DeleteMode mode) {
JSReceiver::DeleteMode mode) {
Heap* heap = Dictionary<Shape, Key>::GetHeap();
PropertyDetails details = DetailsAt(entry);
// Ignore attributes if forcing a deletion.
if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) {
if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) {
return heap->false_value();
}
SetEntry(entry, heap->null_value(), heap->null_value());

72
deps/v8/src/objects.h

@ -1359,6 +1359,12 @@ class HeapNumber: public HeapObject {
// JSObject and JSProxy.
class JSReceiver: public HeapObject {
public:
enum DeleteMode {
NORMAL_DELETION,
STRICT_DELETION,
FORCE_DELETION
};
// Casting.
static inline JSReceiver* cast(Object* obj);
@ -1373,6 +1379,8 @@ class JSReceiver: public HeapObject {
PropertyAttributes attributes,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
// Returns the class name ([[Class]] property in the specification).
String* class_name();
@ -1386,14 +1394,8 @@ class JSReceiver: public HeapObject {
PropertyAttributes GetLocalPropertyAttribute(String* name);
// Can cause a GC.
bool HasProperty(String* name) {
return GetPropertyAttribute(name) != ABSENT;
}
// Can cause a GC.
bool HasLocalProperty(String* name) {
return GetLocalPropertyAttribute(name) != ABSENT;
}
inline bool HasProperty(String* name);
inline bool HasLocalProperty(String* name);
// Return the object's prototype (might be Heap::null_value()).
inline Object* GetPrototype();
@ -1422,12 +1424,6 @@ class JSReceiver: public HeapObject {
// caching.
class JSObject: public JSReceiver {
public:
enum DeleteMode {
NORMAL_DELETION,
STRICT_DELETION,
FORCE_DELETION
};
enum ElementsKind {
// The "fast" kind for tagged values. Must be first to make it possible
// to efficiently check maps if they have fast elements.
@ -2173,23 +2169,12 @@ class FixedDoubleArray: public FixedArrayBase {
return kHeaderSize + length * kDoubleSize;
}
// The following can't be declared inline as const static
// because they're 64-bit.
static uint64_t kCanonicalNonHoleNanLower32;
static uint64_t kCanonicalNonHoleNanInt64;
static uint64_t kHoleNanInt64;
inline static bool is_the_hole_nan(double value) {
return BitCast<uint64_t, double>(value) == kHoleNanInt64;
}
inline static double hole_nan_as_double() {
return BitCast<double, uint64_t>(kHoleNanInt64);
}
// Code Generation support.
static int OffsetOfElementAt(int index) { return SizeFor(index); }
inline static double canonical_not_the_hole_nan_as_double() {
return BitCast<double, uint64_t>(kCanonicalNonHoleNanInt64);
}
inline static bool is_the_hole_nan(double value);
inline static double hole_nan_as_double();
inline static double canonical_not_the_hole_nan_as_double();
// Casting.
static inline FixedDoubleArray* cast(Object* obj);
@ -6487,20 +6472,32 @@ class JSProxy: public JSReceiver {
// [handler]: The handler property.
DECL_ACCESSORS(handler, Object)
// [padding]: The padding slot (unused, see below).
DECL_ACCESSORS(padding, Object)
// Casting.
static inline JSProxy* cast(Object* obj);
bool HasPropertyWithHandler(String* name);
MUST_USE_RESULT MaybeObject* SetPropertyWithHandler(
String* name_raw,
Object* value_raw,
String* name,
Object* value,
PropertyAttributes attributes,
StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* DeletePropertyWithHandler(
String* name,
DeleteMode mode);
MUST_USE_RESULT PropertyAttributes GetPropertyAttributeWithHandler(
JSReceiver* receiver,
String* name_raw,
String* name,
bool* has_exception);
// Turn this into an (empty) JSObject.
void Fix();
// Dispatched behavior.
#ifdef OBJECT_PRINT
inline void JSProxyPrint() {
@ -6512,9 +6509,14 @@ class JSProxy: public JSReceiver {
void JSProxyVerify();
#endif
// Layout description.
// Layout description. We add padding so that a proxy has the same
// size as a virgin JSObject. This is essential for becoming a JSObject
// upon freeze.
static const int kHandlerOffset = HeapObject::kHeaderSize;
static const int kSize = kHandlerOffset + kPointerSize;
static const int kPaddingOffset = kHandlerOffset + kPointerSize;
static const int kSize = kPaddingOffset + kPointerSize;
STATIC_CHECK(kSize == JSObject::kHeaderSize);
typedef FixedBodyDescriptor<kHandlerOffset,
kHandlerOffset + kPointerSize,

186
deps/v8/src/parser.cc

@ -648,6 +648,7 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source,
}
if (ok) {
result = new(zone()) FunctionLiteral(
isolate(),
no_name,
top_scope_,
body,
@ -718,7 +719,6 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info,
{
// Parse the function literal.
Handle<String> no_name = isolate()->factory()->empty_symbol();
Scope* scope = NewScope(top_scope_, Scope::GLOBAL_SCOPE, inside_with());
if (!info->closure().is_null()) {
scope = Scope::DeserializeScopeChain(info, scope);
@ -1262,7 +1262,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
// one must take great care not to treat it as a
// fall-through. It is much easier just to wrap the entire
// try-statement in a statement block and put the labels there
Block* result = new(zone()) Block(labels, 1, false);
Block* result = new(zone()) Block(isolate(), labels, 1, false);
Target target(&this->target_stack_, result);
TryStatement* statement = ParseTryStatement(CHECK_OK);
if (statement) {
@ -1453,10 +1453,10 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
// introduced dynamically when we meet their declarations, whereas
// other functions are setup when entering the surrounding scope.
SharedFunctionInfoLiteral* lit =
new(zone()) SharedFunctionInfoLiteral(shared);
new(zone()) SharedFunctionInfoLiteral(isolate(), shared);
VariableProxy* var = Declare(name, Variable::VAR, NULL, true, CHECK_OK);
return new(zone()) ExpressionStatement(new(zone()) Assignment(
Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
isolate(), Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
}
@ -1489,7 +1489,7 @@ Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
// (ECMA-262, 3rd, 12.2)
//
// Construct block expecting 16 statements.
Block* result = new(zone()) Block(labels, 16, false);
Block* result = new(zone()) Block(isolate(), labels, 16, false);
Target target(&this->target_stack_, result);
Expect(Token::LBRACE, CHECK_OK);
InitializationBlockFinder block_finder(top_scope_, target_stack_);
@ -1564,7 +1564,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// is inside an initializer block, it is ignored.
//
// Create new block with one expected declaration.
Block* block = new(zone()) Block(NULL, 1, true);
Block* block = new(zone()) Block(isolate(), NULL, 1, true);
int nvars = 0; // the number of variables declared
Handle<String> name;
do {
@ -1676,7 +1676,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// Compute the arguments for the runtime call.
ZoneList<Expression*>* arguments = new(zone()) ZoneList<Expression*>(3);
// We have at least 1 parameter.
arguments->Add(new(zone()) Literal(name));
arguments->Add(NewLiteral(name));
CallRuntime* initialize;
if (is_const) {
@ -1689,9 +1689,10 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// the number of arguments (1 or 2).
initialize =
new(zone()) CallRuntime(
isolate()->factory()->InitializeConstGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
arguments);
isolate(),
isolate()->factory()->InitializeConstGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeConstGlobal),
arguments);
} else {
// Add strict mode.
// We may want to pass singleton to avoid Literal allocations.
@ -1715,9 +1716,10 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
// the number of arguments (2 or 3).
initialize =
new(zone()) CallRuntime(
isolate()->factory()->InitializeVarGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
arguments);
isolate(),
isolate()->factory()->InitializeVarGlobal_symbol(),
Runtime::FunctionForId(Runtime::kInitializeVarGlobal),
arguments);
}
block->AddStatement(new(zone()) ExpressionStatement(initialize));
@ -1739,7 +1741,7 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
VariableProxy* proxy =
initialization_scope->NewUnresolved(name, in_with);
Assignment* assignment =
new(zone()) Assignment(op, proxy, value, position);
new(zone()) Assignment(isolate(), op, proxy, value, position);
if (block) {
block->AddStatement(new(zone()) ExpressionStatement(assignment));
}
@ -1842,7 +1844,8 @@ IfStatement* Parser::ParseIfStatement(ZoneStringList* labels, bool* ok) {
} else {
else_statement = EmptyStatement();
}
return new(zone()) IfStatement(condition, then_statement, else_statement);
return new(zone()) IfStatement(
isolate(), condition, then_statement, else_statement);
}
@ -1961,17 +1964,17 @@ Block* Parser::WithHelper(Expression* obj, ZoneStringList* labels, bool* ok) {
// Create resulting block with two statements.
// 1: Evaluate the with expression.
// 2: The try-finally block evaluating the body.
Block* result = new(zone()) Block(NULL, 2, false);
Block* result = new(zone()) Block(isolate(), NULL, 2, false);
if (result != NULL) {
result->AddStatement(new(zone()) EnterWithContextStatement(obj));
// Create body block.
Block* body = new(zone()) Block(NULL, 1, false);
Block* body = new(zone()) Block(isolate(), NULL, 1, false);
body->AddStatement(stat);
// Create exit block.
Block* exit = new(zone()) Block(NULL, 1, false);
Block* exit = new(zone()) Block(isolate(), NULL, 1, false);
exit->AddStatement(new(zone()) ExitContextStatement());
// Return a try-finally statement.
@ -2032,7 +2035,7 @@ CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
statements->Add(stat);
}
return new(zone()) CaseClause(label, statements, pos);
return new(zone()) CaseClause(isolate(), label, statements, pos);
}
@ -2041,7 +2044,7 @@ SwitchStatement* Parser::ParseSwitchStatement(ZoneStringList* labels,
// SwitchStatement ::
// 'switch' '(' Expression ')' '{' CaseClause* '}'
SwitchStatement* statement = new(zone()) SwitchStatement(labels);
SwitchStatement* statement = new(zone()) SwitchStatement(isolate(), labels);
Target target(&this->target_stack_, statement);
Expect(Token::SWITCH, CHECK_OK);
@ -2077,7 +2080,8 @@ Statement* Parser::ParseThrowStatement(bool* ok) {
Expression* exception = ParseExpression(true, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return new(zone()) ExpressionStatement(new(zone()) Throw(exception, pos));
return new(zone()) ExpressionStatement(
new(zone()) Throw(isolate(), exception, pos));
}
@ -2156,7 +2160,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
}
// Create exit block.
Block* inner_finally = new(zone()) Block(NULL, 1, false);
Block* inner_finally = new(zone()) Block(isolate(), NULL, 1, false);
inner_finally->AddStatement(new(zone()) ExitContextStatement());
// Create a try/finally statement.
@ -2164,7 +2168,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
new(zone()) TryFinallyStatement(inner_body, inner_finally);
inner_try_finally->set_escaping_targets(inner_collector.targets());
catch_block = new(zone()) Block(NULL, 1, false);
catch_block = new(zone()) Block(isolate(), NULL, 1, false);
catch_block->AddStatement(inner_try_finally);
} else {
Expect(Token::LBRACE, CHECK_OK);
@ -2193,7 +2197,7 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
catch_variable,
catch_block);
statement->set_escaping_targets(try_collector.targets());
try_block = new(zone()) Block(NULL, 1, false);
try_block = new(zone()) Block(isolate(), NULL, 1, false);
try_block->AddStatement(statement);
catch_block = NULL; // Clear to indicate it's been handled.
}
@ -2224,7 +2228,7 @@ DoWhileStatement* Parser::ParseDoWhileStatement(ZoneStringList* labels,
// DoStatement ::
// 'do' Statement 'while' '(' Expression ')' ';'
DoWhileStatement* loop = new(zone()) DoWhileStatement(labels);
DoWhileStatement* loop = new(zone()) DoWhileStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
Expect(Token::DO, CHECK_OK);
@ -2255,7 +2259,7 @@ WhileStatement* Parser::ParseWhileStatement(ZoneStringList* labels, bool* ok) {
// WhileStatement ::
// 'while' '(' Expression ')' Statement
WhileStatement* loop = new(zone()) WhileStatement(labels);
WhileStatement* loop = new(zone()) WhileStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
Expect(Token::WHILE, CHECK_OK);
@ -2285,7 +2289,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
if (peek() == Token::IN && !name.is_null()) {
VariableProxy* each = top_scope_->NewUnresolved(name, inside_with());
ForInStatement* loop = new(zone()) ForInStatement(labels);
ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
@ -2294,7 +2298,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
Statement* body = ParseStatement(NULL, CHECK_OK);
loop->Initialize(each, enumerable, body);
Block* result = new(zone()) Block(NULL, 2, false);
Block* result = new(zone()) Block(isolate(), NULL, 2, false);
result->AddStatement(variable_statement);
result->AddStatement(loop);
// Parsed for-in loop w/ variable/const declaration.
@ -2315,7 +2319,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
isolate()->factory()->invalid_lhs_in_for_in_symbol();
expression = NewThrowReferenceError(type);
}
ForInStatement* loop = new(zone()) ForInStatement(labels);
ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
Expect(Token::IN, CHECK_OK);
@ -2334,7 +2338,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
}
// Standard 'for' loop
ForStatement* loop = new(zone()) ForStatement(labels);
ForStatement* loop = new(zone()) ForStatement(isolate(), labels);
Target target(&this->target_stack_, loop);
// Parsed initializer at this point.
@ -2370,7 +2374,8 @@ Expression* Parser::ParseExpression(bool accept_IN, bool* ok) {
Expect(Token::COMMA, CHECK_OK);
int position = scanner().location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
result = new(zone()) BinaryOperation(Token::COMMA, result, right, position);
result = new(zone()) BinaryOperation(
isolate(), Token::COMMA, result, right, position);
}
return result;
}
@ -2442,7 +2447,7 @@ Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
fni_->Leave();
}
return new(zone()) Assignment(op, expression, right, pos);
return new(zone()) Assignment(isolate(), op, expression, right, pos);
}
@ -2464,8 +2469,8 @@ Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
Expect(Token::COLON, CHECK_OK);
int right_position = scanner().peek_location().beg_pos;
Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
return new(zone()) Conditional(expression, left, right,
left_position, right_position);
return new(zone()) Conditional(
isolate(), expression, left, right, left_position, right_position);
}
@ -2552,12 +2557,12 @@ Expression* Parser::ParseBinaryExpression(int prec, bool accept_IN, bool* ok) {
x = NewCompareNode(cmp, x, y, position);
if (cmp != op) {
// The comparison was negated - add a NOT.
x = new(zone()) UnaryOperation(Token::NOT, x, position);
x = new(zone()) UnaryOperation(isolate(), Token::NOT, x, position);
}
} else {
// We have a "normal" binary operation.
x = new(zone()) BinaryOperation(op, x, y, position);
x = new(zone()) BinaryOperation(isolate(), op, x, y, position);
}
}
}
@ -2574,15 +2579,15 @@ Expression* Parser::NewCompareNode(Token::Value op,
bool is_strict = (op == Token::EQ_STRICT);
Literal* x_literal = x->AsLiteral();
if (x_literal != NULL && x_literal->IsNull()) {
return new(zone()) CompareToNull(is_strict, y);
return new(zone()) CompareToNull(isolate(), is_strict, y);
}
Literal* y_literal = y->AsLiteral();
if (y_literal != NULL && y_literal->IsNull()) {
return new(zone()) CompareToNull(is_strict, x);
return new(zone()) CompareToNull(isolate(), is_strict, x);
}
}
return new(zone()) CompareOperation(op, x, y, position);
return new(zone()) CompareOperation(isolate(), op, x, y, position);
}
@ -2611,7 +2616,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
// Convert the literal to a boolean condition and negate it.
bool condition = literal->ToBoolean()->IsTrue();
Handle<Object> result(isolate()->heap()->ToBoolean(!condition));
return new(zone()) Literal(result);
return NewLiteral(result);
} else if (literal->IsNumber()) {
// Compute some expressions involving only number literals.
double value = literal->Number();
@ -2638,7 +2643,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
}
return new(zone()) UnaryOperation(op, expression, position);
return new(zone()) UnaryOperation(isolate(), op, expression, position);
} else if (Token::IsCountOp(op)) {
op = Next();
@ -2659,7 +2664,8 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
int position = scanner().location().beg_pos;
return new(zone()) CountOperation(op,
return new(zone()) CountOperation(isolate(),
op,
true /* prefix */,
expression,
position);
@ -2695,7 +2701,8 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
Token::Value next = Next();
int position = scanner().location().beg_pos;
expression =
new(zone()) CountOperation(next,
new(zone()) CountOperation(isolate(),
next,
false /* postfix */,
expression,
position);
@ -2721,7 +2728,7 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
result = new(zone()) Property(result, index, pos);
result = new(zone()) Property(isolate(), result, index, pos);
Expect(Token::RBRACK, CHECK_OK);
break;
}
@ -2759,7 +2766,10 @@ Expression* Parser::ParseLeftHandSideExpression(bool* ok) {
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
result = new(zone()) Property(result, new(zone()) Literal(name), pos);
result = new(zone()) Property(isolate(),
result,
NewLiteral(name),
pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
@ -2795,7 +2805,8 @@ Expression* Parser::ParseNewPrefix(PositionStack* stack, bool* ok) {
if (!stack->is_empty()) {
int last = stack->pop();
result = new(zone()) CallNew(result,
result = new(zone()) CallNew(isolate(),
result,
new(zone()) ZoneList<Expression*>(0),
last);
}
@ -2843,7 +2854,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
Consume(Token::LBRACK);
int pos = scanner().location().beg_pos;
Expression* index = ParseExpression(true, CHECK_OK);
result = new(zone()) Property(result, index, pos);
result = new(zone()) Property(isolate(), result, index, pos);
if (fni_ != NULL) {
if (index->IsPropertyName()) {
fni_->PushLiteralName(index->AsLiteral()->AsPropertyName());
@ -2859,7 +2870,10 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
Consume(Token::PERIOD);
int pos = scanner().location().beg_pos;
Handle<String> name = ParseIdentifierName(CHECK_OK);
result = new(zone()) Property(result, new(zone()) Literal(name), pos);
result = new(zone()) Property(isolate(),
result,
NewLiteral(name),
pos);
if (fni_ != NULL) fni_->PushLiteralName(name);
break;
}
@ -2868,7 +2882,7 @@ Expression* Parser::ParseMemberWithNewPrefixesExpression(PositionStack* stack,
// Consume one of the new prefixes (already parsed).
ZoneList<Expression*>* args = ParseArguments(CHECK_OK);
int last = stack->pop();
result = new CallNew(result, args, last);
result = new(zone()) CallNew(isolate(), result, args, last);
break;
}
default:
@ -2952,23 +2966,26 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
switch (peek()) {
case Token::THIS: {
Consume(Token::THIS);
result = new(zone()) VariableProxy(top_scope_->receiver());
result = new(zone()) VariableProxy(isolate(), top_scope_->receiver());
break;
}
case Token::NULL_LITERAL:
Consume(Token::NULL_LITERAL);
result = new(zone()) Literal(isolate()->factory()->null_value());
result = new(zone()) Literal(
isolate(), isolate()->factory()->null_value());
break;
case Token::TRUE_LITERAL:
Consume(Token::TRUE_LITERAL);
result = new(zone()) Literal(isolate()->factory()->true_value());
result = new(zone()) Literal(
isolate(), isolate()->factory()->true_value());
break;
case Token::FALSE_LITERAL:
Consume(Token::FALSE_LITERAL);
result = new(zone()) Literal(isolate()->factory()->false_value());
result = new(zone()) Literal(
isolate(), isolate()->factory()->false_value());
break;
case Token::IDENTIFIER:
@ -2994,7 +3011,7 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
case Token::STRING: {
Consume(Token::STRING);
Handle<String> symbol = GetSymbol(CHECK_OK);
result = new(zone()) Literal(symbol);
result = NewLiteral(symbol);
if (fni_ != NULL) fni_->PushLiteralName(symbol);
break;
}
@ -3121,8 +3138,8 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
literals->set_map(isolate()->heap()->fixed_cow_array_map());
}
return new(zone()) ArrayLiteral(literals, values,
literal_index, is_simple, depth);
return new(zone()) ArrayLiteral(
isolate(), literals, values, literal_index, is_simple, depth);
}
@ -3425,7 +3442,6 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
ObjectLiteralPropertyChecker checker(this, top_scope_->is_strict_mode());
Expect(Token::LBRACE, CHECK_OK);
Scanner::Location loc = scanner().location();
while (peek() != Token::RBRACE) {
if (fni_ != NULL) fni_->Enter();
@ -3467,7 +3483,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
}
// Failed to parse as get/set property, so it's just a property
// called "get" or "set".
key = new(zone()) Literal(id);
key = NewLiteral(id);
break;
}
case Token::STRING: {
@ -3479,7 +3495,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
key = NewNumberLiteral(index);
break;
}
key = new(zone()) Literal(string);
key = NewLiteral(string);
break;
}
case Token::NUMBER: {
@ -3495,7 +3511,7 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
if (Token::IsKeyword(next)) {
Consume(next);
Handle<String> string = GetSymbol(CHECK_OK);
key = new(zone()) Literal(string);
key = NewLiteral(string);
} else {
// Unexpected token.
Token::Value next = Next();
@ -3548,13 +3564,14 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
&is_simple,
&fast_elements,
&depth);
return new(zone()) ObjectLiteral(constant_properties,
properties,
literal_index,
is_simple,
fast_elements,
depth,
has_function);
return new(zone()) ObjectLiteral(isolate(),
constant_properties,
properties,
literal_index,
is_simple,
fast_elements,
depth,
has_function);
}
@ -3573,7 +3590,8 @@ Expression* Parser::ParseRegExpLiteral(bool seen_equal, bool* ok) {
Handle<String> js_flags = NextLiteralString(TENURED);
Next();
return new(zone()) RegExpLiteral(js_pattern, js_flags, literal_index);
return new(zone()) RegExpLiteral(
isolate(), js_pattern, js_flags, literal_index);
}
@ -3690,9 +3708,11 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
top_scope_->NewUnresolved(function_name, inside_with());
fproxy->BindTo(fvar);
body->Add(new(zone()) ExpressionStatement(
new(zone()) Assignment(Token::INIT_CONST, fproxy,
new(zone()) ThisFunction(),
RelocInfo::kNoPosition)));
new(zone()) Assignment(isolate(),
Token::INIT_CONST,
fproxy,
new(zone()) ThisFunction(isolate()),
RelocInfo::kNoPosition)));
}
// Determine if the function will be lazily compiled. The mode can
@ -3782,7 +3802,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> var_name,
}
FunctionLiteral* function_literal =
new(zone()) FunctionLiteral(name,
new(zone()) FunctionLiteral(isolate(),
name,
scope,
body,
materialized_literal_count,
@ -3843,7 +3864,7 @@ Expression* Parser::ParseV8Intrinsic(bool* ok) {
}
// We have a valid intrinsics call or a call to a builtin.
return new(zone()) CallRuntime(name, function, args);
return new(zone()) CallRuntime(isolate(), name, function, args);
}
@ -3899,12 +3920,12 @@ void Parser::ExpectSemicolon(bool* ok) {
Literal* Parser::GetLiteralUndefined() {
return new(zone()) Literal(isolate()->factory()->undefined_value());
return NewLiteral(isolate()->factory()->undefined_value());
}
Literal* Parser::GetLiteralTheHole() {
return new(zone()) Literal(isolate()->factory()->the_hole_value());
return NewLiteral(isolate()->factory()->the_hole_value());
}
@ -4060,7 +4081,7 @@ void Parser::RegisterTargetUse(Label* target, Target* stop) {
Literal* Parser::NewNumberLiteral(double number) {
return new(zone()) Literal(isolate()->factory()->NewNumber(number, TENURED));
return NewLiteral(isolate()->factory()->NewNumber(number, TENURED));
}
@ -4107,10 +4128,15 @@ Expression* Parser::NewThrowError(Handle<String> constructor,
TENURED);
ZoneList<Expression*>* args = new(zone()) ZoneList<Expression*>(2);
args->Add(new(zone()) Literal(type));
args->Add(new(zone()) Literal(array));
return new(zone()) Throw(new(zone()) CallRuntime(constructor, NULL, args),
scanner().location().beg_pos);
args->Add(NewLiteral(type));
args->Add(NewLiteral(array));
CallRuntime* call_constructor = new(zone()) CallRuntime(isolate(),
constructor,
NULL,
args);
return new(zone()) Throw(isolate(),
call_constructor,
scanner().location().beg_pos);
}
// ----------------------------------------------------------------------------

5
deps/v8/src/parser.h

@ -668,9 +668,12 @@ class Parser {
Expression* NewCall(Expression* expression,
ZoneList<Expression*>* arguments,
int pos) {
return new Call(expression, arguments, pos);
return new(zone()) Call(isolate(), expression, arguments, pos);
}
inline Literal* NewLiteral(Handle<Object> handle) {
return new(zone()) Literal(isolate(), handle);
}
// Create a number literal.
Literal* NewNumberLiteral(double value);

1
deps/v8/src/platform-linux.cc

@ -734,6 +734,7 @@ class LinuxMutex : public Mutex {
ASSERT(result == 0);
result = pthread_mutex_init(&mutex_, &attrs);
ASSERT(result == 0);
USE(result);
}
virtual ~LinuxMutex() { pthread_mutex_destroy(&mutex_); }

5
deps/v8/src/platform-nullos.cc

@ -217,6 +217,11 @@ void OS::Free(void* buf, const size_t length) {
}
void OS::Guard(void* address, const size_t size) {
UNIMPLEMENTED();
}
void OS::Sleep(int milliseconds) {
UNIMPLEMENTED();
}

9
deps/v8/src/platform-posix.cc

@ -33,6 +33,7 @@
#include <errno.h>
#include <time.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/resource.h>
#include <sys/time.h>
@ -43,6 +44,8 @@
#include <netinet/in.h>
#include <netdb.h>
#undef MAP_TYPE
#if defined(ANDROID)
#define LOG_TAG "v8"
#include <utils/Log.h> // LOG_PRI_VA
@ -67,6 +70,12 @@ intptr_t OS::MaxVirtualMemory() {
}
// Create guard pages.
void OS::Guard(void* address, const size_t size) {
mprotect(address, size, PROT_NONE);
}
// ----------------------------------------------------------------------------
// Math functions

6
deps/v8/src/platform-win32.cc

@ -957,6 +957,12 @@ void OS::Free(void* address, const size_t size) {
}
void OS::Guard(void* address, const size_t size) {
DWORD oldprotect;
VirtualProtect(address, size, PAGE_READONLY | PAGE_GUARD, &oldprotect);
}
void OS::Sleep(int milliseconds) {
::Sleep(milliseconds);
}

4
deps/v8/src/platform.h

@ -206,6 +206,10 @@ class OS {
size_t* allocated,
bool is_executable);
static void Free(void* address, const size_t size);
// Assign memory as a guard page so that access will cause an exception.
static void Guard(void* address, const size_t size);
// Get the Alignment guaranteed by Allocate().
static size_t AllocateAlignment();

16
deps/v8/src/rewriter.cc

@ -66,9 +66,13 @@ class Processor: public AstVisitor {
Expression* SetResult(Expression* value) {
result_assigned_ = true;
VariableProxy* result_proxy = new VariableProxy(result_);
return new Assignment(Token::ASSIGN, result_proxy, value,
RelocInfo::kNoPosition);
Zone* zone = isolate()->zone();
VariableProxy* result_proxy = new(zone) VariableProxy(isolate(), result_);
return new(zone) Assignment(isolate(),
Token::ASSIGN,
result_proxy,
value,
RelocInfo::kNoPosition);
}
// Node visitors.
@ -229,8 +233,10 @@ bool Rewriter::Rewrite(CompilationInfo* info) {
if (processor.HasStackOverflow()) return false;
if (processor.result_assigned()) {
VariableProxy* result_proxy = new VariableProxy(result);
body->Add(new ReturnStatement(result_proxy));
Isolate* isolate = info->isolate();
Zone* zone = isolate->zone();
VariableProxy* result_proxy = new(zone) VariableProxy(isolate, result);
body->Add(new(zone) ReturnStatement(result_proxy));
}
}

273
deps/v8/src/runtime.cc

@ -615,6 +615,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
ASSERT(args.length() == 1);
CONVERT_CHECKED(JSProxy, proxy, args[0]);
proxy->Fix();
return proxy;
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@ -3872,7 +3880,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
|| result.type() == CONSTANT_FUNCTION)) {
Object* ok;
{ MaybeObject* maybe_ok =
obj->DeleteProperty(name, JSObject::NORMAL_DELETION);
obj->DeleteProperty(name, JSReceiver::NORMAL_DELETION);
if (!maybe_ok->ToObject(&ok)) return maybe_ok;
}
}
@ -4126,24 +4134,25 @@ MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
Handle<JSObject> js_object,
Handle<JSReceiver> receiver,
Handle<Object> key) {
HandleScope scope(isolate);
// Check if the given key is an array index.
uint32_t index;
if (key->ToArrayIndex(&index)) {
if (receiver->IsJSObject() && key->ToArrayIndex(&index)) {
// In Firefox/SpiderMonkey, Safari and Opera you can access the
// characters of a string using [] notation. In the case of a
// String object we just need to redirect the deletion to the
// underlying string if the index is in range. Since the
// underlying string does nothing with the deletion, we can ignore
// such deletions.
if (js_object->IsStringObjectWithCharacterAt(index)) {
if (receiver->IsStringObjectWithCharacterAt(index)) {
return isolate->heap()->true_value();
}
return js_object->DeleteElement(index, JSObject::FORCE_DELETION);
return JSObject::cast(*receiver)->DeleteElement(
index, JSReceiver::FORCE_DELETION);
}
Handle<String> key_string;
@ -4158,7 +4167,7 @@ MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
}
key_string->TryFlatten();
return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION);
return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
}
@ -4237,12 +4246,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
NoHandleAllocation ha;
ASSERT(args.length() == 3);
CONVERT_CHECKED(JSObject, object, args[0]);
CONVERT_CHECKED(JSReceiver, object, args[0]);
CONVERT_CHECKED(String, key, args[1]);
CONVERT_SMI_ARG_CHECKED(strict, 2);
return object->DeleteProperty(key, (strict == kStrictMode)
? JSObject::STRICT_DELETION
: JSObject::NORMAL_DELETION);
? JSReceiver::STRICT_DELETION
: JSReceiver::NORMAL_DELETION);
}
@ -4306,11 +4315,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
// Only JS objects can have properties.
if (args[0]->IsJSObject()) {
JSObject* object = JSObject::cast(args[0]);
// Only JS receivers can have properties.
if (args[0]->IsJSReceiver()) {
JSReceiver* receiver = JSReceiver::cast(args[0]);
CONVERT_CHECKED(String, key, args[1]);
if (object->HasProperty(key)) return isolate->heap()->true_value();
if (receiver->HasProperty(key)) return isolate->heap()->true_value();
}
return isolate->heap()->false_value();
}
@ -8198,9 +8207,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
// index is non-negative.
Handle<JSObject> object = Handle<JSObject>::cast(holder);
if (index >= 0) {
return object->DeleteElement(index, JSObject::NORMAL_DELETION);
return object->DeleteElement(index, JSReceiver::NORMAL_DELETION);
} else {
return object->DeleteProperty(*name, JSObject::NORMAL_DELETION);
return object->DeleteProperty(*name, JSReceiver::NORMAL_DELETION);
}
}
@ -9976,6 +9985,71 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
}
class FrameInspector {
public:
FrameInspector(JavaScriptFrame* frame,
int inlined_frame_index,
Isolate* isolate)
: frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
// Calculate the deoptimized frame.
if (frame->is_optimized()) {
deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
frame, inlined_frame_index, isolate);
}
has_adapted_arguments_ = frame_->has_adapted_arguments();
is_optimized_ = frame_->is_optimized();
}
~FrameInspector() {
// Get rid of the calculated deoptimized frame if any.
if (deoptimized_frame_ != NULL) {
Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
isolate_);
}
}
int GetParametersCount() {
return is_optimized_
? deoptimized_frame_->parameters_count()
: frame_->ComputeParametersCount();
}
int expression_count() { return deoptimized_frame_->expression_count(); }
Object* GetFunction() {
return is_optimized_
? deoptimized_frame_->GetFunction()
: frame_->function();
}
Object* GetParameter(int index) {
return is_optimized_
? deoptimized_frame_->GetParameter(index)
: frame_->GetParameter(index);
}
Object* GetExpression(int index) {
return is_optimized_
? deoptimized_frame_->GetExpression(index)
: frame_->GetExpression(index);
}
// To inspect all the provided arguments the frame might need to be
// replaced with the arguments frame.
void SetArgumentsFrame(JavaScriptFrame* frame) {
ASSERT(has_adapted_arguments_);
frame_ = frame;
is_optimized_ = frame_->is_optimized();
ASSERT(!is_optimized_);
}
private:
JavaScriptFrame* frame_;
DeoptimizedFrameInfo* deoptimized_frame_;
Isolate* isolate_;
bool is_optimized_;
bool has_adapted_arguments_;
DISALLOW_COPY_AND_ASSIGN(FrameInspector);
};
static const int kFrameDetailsFrameIdIndex = 0;
static const int kFrameDetailsReceiverIndex = 1;
static const int kFrameDetailsFunctionIndex = 2;
@ -10024,8 +10098,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
return heap->undefined_value();
}
int deoptimized_frame_index = -1; // Frame index in optimized frame.
DeoptimizedFrameInfo* deoptimized_frame = NULL;
int inlined_frame_index = 0; // Inlined frame index in optimized frame.
int count = 0;
JavaScriptFrameIterator it(isolate, id);
@ -10036,13 +10109,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
if (it.done()) return heap->undefined_value();
if (it.frame()->is_optimized()) {
deoptimized_frame_index =
inlined_frame_index =
it.frame()->GetInlineCount() - (index - count) - 1;
deoptimized_frame = Deoptimizer::DebuggerInspectableFrame(
it.frame(),
deoptimized_frame_index,
isolate);
}
FrameInspector frame_inspector(it.frame(), inlined_frame_index, isolate);
// Traverse the saved contexts chain to find the active context for the
// selected frame.
@ -10061,12 +10131,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// Check for constructor frame. Inlined frames cannot be construct calls.
bool inlined_frame =
it.frame()->is_optimized() && deoptimized_frame_index != 0;
it.frame()->is_optimized() && inlined_frame_index != 0;
bool constructor = !inlined_frame && it.frame()->IsConstructor();
// Get scope info and read from it for local variable information.
Handle<JSFunction> function(JSFunction::cast(it.frame()->function()));
Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info());
Handle<SharedFunctionInfo> shared(function->shared());
Handle<SerializedScopeInfo> scope_info(shared->scope_info());
ASSERT(*scope_info != SerializedScopeInfo::Empty());
ScopeInfo<> info(*scope_info);
@ -10083,14 +10154,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
for (; i < info.number_of_stack_slots(); ++i) {
// Use the value from the stack.
locals->set(i * 2, *info.LocalName(i));
if (it.frame()->is_optimized()) {
// Get the value from the deoptimized frame.
locals->set(i * 2 + 1,
deoptimized_frame->GetExpression(i));
} else {
// Get the value from the stack.
locals->set(i * 2 + 1, it.frame()->GetExpression(i));
}
locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
}
if (i < info.NumberOfLocals()) {
// Get the context containing declarations.
@ -10147,18 +10211,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// the provided parameters whereas the function frame always have the number
// of arguments matching the functions parameters. The rest of the
// information (except for what is collected above) is the same.
it.AdvanceToArgumentsFrame();
if (it.frame()->has_adapted_arguments()) {
it.AdvanceToArgumentsFrame();
frame_inspector.SetArgumentsFrame(it.frame());
}
// Find the number of arguments to fill. At least fill the number of
// parameters for the function and fill more if more parameters are provided.
int argument_count = info.number_of_parameters();
if (argument_count < frame_inspector.GetParametersCount()) {
argument_count = frame_inspector.GetParametersCount();
}
#ifdef DEBUG
if (it.frame()->is_optimized()) {
ASSERT_EQ(argument_count, deoptimized_frame->parameters_count());
} else {
if (argument_count < it.frame()->ComputeParametersCount()) {
argument_count = it.frame()->ComputeParametersCount();
}
ASSERT_EQ(argument_count, frame_inspector.GetParametersCount());
}
#endif
// Calculate the size of the result.
int details_size = kFrameDetailsFirstDynamicIndex +
@ -10170,13 +10238,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
details->set(kFrameDetailsFrameIdIndex, *frame_id);
// Add the function (same as in function frame).
if (it.frame()->is_optimized()) {
// Get the function from the deoptimized frame.
details->set(kFrameDetailsFunctionIndex, deoptimized_frame->GetFunction());
} else {
// Get the function from the stack.
details->set(kFrameDetailsFunctionIndex, it.frame()->function());
}
details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
// Add the arguments count.
details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
@ -10208,9 +10270,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
if (it.frame()->is_optimized()) {
flags |= 1 << 1;
if (deoptimized_frame_index > 0) {
flags |= 1 << 2;
}
flags |= inlined_frame_index << 2;
}
details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
@ -10227,16 +10287,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
// Parameter value.
if (it.frame()->is_optimized()) {
// Get the value from the deoptimized frame.
details->set(details_index++, deoptimized_frame->GetParameter(i));
if (i < it.frame()->ComputeParametersCount()) {
// Get the value from the stack.
details->set(details_index++, frame_inspector.GetParameter(i));
} else {
if (i < it.frame()->ComputeParametersCount()) {
// Get the value from the stack.
details->set(details_index++, it.frame()->GetParameter(i));
} else {
details->set(details_index++, heap->undefined_value());
}
details->set(details_index++, heap->undefined_value());
}
}
@ -10254,10 +10309,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
// THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
// THE FRAME ITERATOR TO WRAP THE RECEIVER.
Handle<Object> receiver(it.frame()->receiver(), isolate);
if (!receiver->IsJSObject()) {
// If the receiver is NOT a JSObject we have hit an optimization
// where a value object is not converted into a wrapped JS objects.
// To hide this optimization from the debugger, we wrap the receiver
if (!receiver->IsJSObject() && !shared->strict_mode() && !shared->native()) {
// If the receiver is not a JSObject and the function is not a
// builtin or strict-mode we have hit an optimization where a
// value object is not converted into a wrapped JS objects. To
// hide this optimization from the debugger, we wrap the receiver
// by creating correct wrapper object based on the calling frame's
// global context.
it.Advance();
@ -10268,12 +10324,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
}
details->set(kFrameDetailsReceiverIndex, *receiver);
// Get rid of the calculated deoptimized frame if any.
if (deoptimized_frame != NULL) {
Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame,
isolate);
}
ASSERT_EQ(details_size, details_index);
return *isolate->factory()->NewJSArrayWithElements(details);
}
@ -10309,12 +10359,15 @@ static bool CopyContextLocalsToScopeObject(
// Create a plain JSObject which materializes the local scope for the specified
// frame.
static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
JavaScriptFrame* frame) {
static Handle<JSObject> MaterializeLocalScope(
Isolate* isolate,
JavaScriptFrame* frame,
int inlined_frame_index) {
Handle<JSFunction> function(JSFunction::cast(frame->function()));
Handle<SharedFunctionInfo> shared(function->shared());
Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info());
ScopeInfo<> scope_info(*serialized_scope_info);
FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
// Allocate and initialize a JSObject with all the arguments, stack locals
// heap locals and extension properties of the debugged function.
@ -10327,7 +10380,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
isolate,
SetProperty(local_scope,
scope_info.parameter_name(i),
Handle<Object>(frame->GetParameter(i), isolate),
Handle<Object>(frame_inspector.GetParameter(i)),
NONE,
kNonStrictMode),
Handle<JSObject>());
@ -10339,7 +10392,7 @@ static Handle<JSObject> MaterializeLocalScope(Isolate* isolate,
isolate,
SetProperty(local_scope,
scope_info.stack_slot_name(i),
Handle<Object>(frame->GetExpression(i), isolate),
Handle<Object>(frame_inspector.GetExpression(i)),
NONE,
kNonStrictMode),
Handle<JSObject>());
@ -10459,9 +10512,12 @@ class ScopeIterator {
ScopeTypeCatch
};
ScopeIterator(Isolate* isolate, JavaScriptFrame* frame)
ScopeIterator(Isolate* isolate,
JavaScriptFrame* frame,
int inlined_frame_index)
: isolate_(isolate),
frame_(frame),
inlined_frame_index_(inlined_frame_index),
function_(JSFunction::cast(frame->function())),
context_(Context::cast(frame->context())),
local_done_(false),
@ -10546,7 +10602,7 @@ class ScopeIterator {
return Handle<JSObject>(CurrentContext()->global());
case ScopeIterator::ScopeTypeLocal:
// Materialize the content of the local scope into a JSObject.
return MaterializeLocalScope(isolate_, frame_);
return MaterializeLocalScope(isolate_, frame_, inlined_frame_index_);
case ScopeIterator::ScopeTypeWith:
// Return the with object.
return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
@ -10626,6 +10682,7 @@ class ScopeIterator {
private:
Isolate* isolate_;
JavaScriptFrame* frame_;
int inlined_frame_index_;
Handle<JSFunction> function_;
Handle<Context> context_;
bool local_done_;
@ -10654,7 +10711,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
// Count the visible scopes.
int n = 0;
for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
for (ScopeIterator it(isolate, frame, 0);
!it.Done();
it.Next()) {
n++;
}
@ -10669,14 +10728,15 @@ static const int kScopeDetailsSize = 2;
// Return an array with scope details
// args[0]: number: break id
// args[1]: number: frame index
// args[2]: number: scope index
// args[2]: number: inlined frame index
// args[3]: number: scope index
//
// The array returned contains the following information:
// 0: Scope type
// 1: Scope object
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
HandleScope scope(isolate);
ASSERT(args.length() == 3);
ASSERT(args.length() == 4);
// Check arguments.
Object* check;
@ -10685,7 +10745,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
if (!maybe_check->ToObject(&check)) return maybe_check;
}
CONVERT_CHECKED(Smi, wrapped_id, args[1]);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[2]);
CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
// Get the frame where the debugging is performed.
StackFrame::Id id = UnwrapFrameId(wrapped_id);
@ -10694,7 +10755,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
// Find the requested scope.
int n = 0;
ScopeIterator it(isolate, frame);
ScopeIterator it(isolate, frame, inlined_frame_index);
for (; !it.Done() && n < index; it.Next()) {
n++;
}
@ -10724,7 +10785,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
// Print the scopes for the top frame.
StackFrameLocator locator;
JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
for (ScopeIterator it(isolate, frame); !it.Done(); it.Next()) {
for (ScopeIterator it(isolate, frame, 0);
!it.Done();
it.Next()) {
it.DebugPrint();
}
#endif
@ -11117,6 +11180,7 @@ static Handle<Context> CopyWithContextChain(Isolate* isolate,
// Runtime_DebugEvaluate.
static Handle<Object> GetArgumentsObject(Isolate* isolate,
JavaScriptFrame* frame,
int inlined_frame_index,
Handle<JSFunction> function,
Handle<SerializedScopeInfo> scope_info,
const ScopeInfo<>* sinfo,
@ -11128,6 +11192,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
if (sinfo->number_of_stack_slots() > 0) {
index = scope_info->StackSlotIndex(isolate->heap()->arguments_symbol());
if (index != -1) {
CHECK(false);
return Handle<Object>(frame->GetExpression(index), isolate);
}
}
@ -11140,7 +11205,9 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
}
}
const int length = frame->ComputeParametersCount();
FrameInspector frame_inspector(frame, inlined_frame_index, isolate);
int length = frame_inspector.GetParametersCount();
Handle<JSObject> arguments =
isolate->factory()->NewArgumentsObject(function, length);
Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
@ -11148,7 +11215,7 @@ static Handle<Object> GetArgumentsObject(Isolate* isolate,
AssertNoAllocation no_gc;
WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
for (int i = 0; i < length; i++) {
array->set(i, frame->GetParameter(i), mode);
array->set(i, frame_inspector.GetParameter(i), mode);
}
arguments->set_elements(*array);
return arguments;
@ -11175,7 +11242,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
// Check the execution state and decode arguments frame and source to be
// evaluated.
ASSERT(args.length() == 5);
ASSERT(args.length() == 6);
Object* check_result;
{ MaybeObject* maybe_check_result = Runtime_CheckExecutionState(
RUNTIME_ARGUMENTS(isolate, args));
@ -11184,9 +11251,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
}
}
CONVERT_CHECKED(Smi, wrapped_id, args[1]);
CONVERT_ARG_CHECKED(String, source, 2);
CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
Handle<Object> additional_context(args[4]);
CONVERT_NUMBER_CHECKED(int, inlined_frame_index, Int32, args[2]);
CONVERT_ARG_CHECKED(String, source, 3);
CONVERT_BOOLEAN_CHECKED(disable_break, args[4]);
Handle<Object> additional_context(args[5]);
// Handle the processing of break.
DisableBreak disable_break_save(disable_break);
@ -11226,7 +11294,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
#endif
// Materialize the content of the local scope into a JSObject.
Handle<JSObject> local_scope = MaterializeLocalScope(isolate, frame);
Handle<JSObject> local_scope = MaterializeLocalScope(
isolate, frame, inlined_frame_index);
RETURN_IF_EMPTY_HANDLE(isolate, local_scope);
// Allocate a new context for the debug evaluation and set the extension
@ -11275,7 +11344,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
&has_pending_exception);
if (has_pending_exception) return Failure::Exception();
Handle<Object> arguments = GetArgumentsObject(isolate, frame,
Handle<Object> arguments = GetArgumentsObject(isolate,
frame, inlined_frame_index,
function, scope_info,
&sinfo, function_context);
@ -12214,8 +12284,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
// call to this function is encountered it is skipped. The seen_caller
// in/out parameter is used to remember if the caller has been seen
// yet.
static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller,
bool* seen_caller) {
static bool ShowFrameInStackTrace(StackFrame* raw_frame,
Object* caller,
bool* seen_caller) {
// Only display JS frames.
if (!raw_frame->is_java_script())
return false;
@ -12228,11 +12299,25 @@ static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller,
*seen_caller = true;
return false;
}
// Skip all frames until we've seen the caller. Also, skip the most
// obvious builtin calls. Some builtin calls (such as Number.ADD
// which is invoked using 'call') are very difficult to recognize
// so we're leaving them in for now.
return *seen_caller && !frame->receiver()->IsJSBuiltinsObject();
// Skip all frames until we've seen the caller.
if (!(*seen_caller)) return false;
// Also, skip the most obvious builtin calls. We recognize builtins
// as (1) functions called with the builtins object as the receiver and
// as (2) functions from native scripts called with undefined as the
// receiver (direct calls to helper functions in the builtins
// code). Some builtin calls (such as Number.ADD which is invoked
// using 'call') are very difficult to recognize so we're leaving
// them in for now.
if (frame->receiver()->IsJSBuiltinsObject()) {
return false;
}
JSFunction* fun = JSFunction::cast(raw_fun);
Object* raw_script = fun->shared()->script();
if (frame->receiver()->IsUndefined() && raw_script->IsScript()) {
int script_type = Script::cast(raw_script)->type()->value();
return script_type != Script::TYPE_NATIVE;
}
return true;
}

7
deps/v8/src/runtime.h

@ -284,6 +284,7 @@ namespace internal {
F(CreateJSProxy, 2, 1) \
F(IsJSProxy, 1, 1) \
F(GetHandler, 1, 1) \
F(Fix, 1, 1) \
\
/* Statements */ \
F(NewClosure, 3, 1) \
@ -372,7 +373,7 @@ namespace internal {
F(GetFrameCount, 1, 1) \
F(GetFrameDetails, 2, 1) \
F(GetScopeCount, 2, 1) \
F(GetScopeDetails, 3, 1) \
F(GetScopeDetails, 4, 1) \
F(DebugPrintScopes, 0, 1) \
F(GetThreadCount, 1, 1) \
F(GetThreadDetails, 2, 1) \
@ -385,7 +386,7 @@ namespace internal {
F(IsBreakOnException, 1, 1) \
F(PrepareStep, 3, 1) \
F(ClearStepping, 0, 1) \
F(DebugEvaluate, 5, 1) \
F(DebugEvaluate, 6, 1) \
F(DebugEvaluateGlobal, 4, 1) \
F(DebugGetLoadedScripts, 0, 1) \
F(DebugReferencedBy, 3, 1) \
@ -636,7 +637,7 @@ class Runtime : public AllStatic {
MUST_USE_RESULT static MaybeObject* ForceDeleteObjectProperty(
Isolate* isolate,
Handle<JSObject> object,
Handle<JSReceiver> object,
Handle<Object> key);
MUST_USE_RESULT static MaybeObject* GetObjectProperty(

3
deps/v8/src/runtime.js

@ -354,7 +354,8 @@ function IN(x) {
if (!IS_SPEC_OBJECT(x)) {
throw %MakeTypeError('invalid_in_operator_use', [this, x]);
}
return %_IsNonNegativeSmi(this) ? %HasElement(x, this) : %HasProperty(x, %ToString(this));
return %_IsNonNegativeSmi(this) && !%IsJSProxy(x) ?
%HasElement(x, this) : %HasProperty(x, %ToString(this));
}

89
deps/v8/src/scopes.cc

@ -116,25 +116,27 @@ Variable* VariableMap::Lookup(Handle<String> name) {
// Dummy constructor
Scope::Scope(Type type)
: inner_scopes_(0),
variables_(false),
temps_(0),
params_(0),
unresolved_(0),
decls_(0),
already_resolved_(false) {
: isolate_(Isolate::Current()),
inner_scopes_(0),
variables_(false),
temps_(0),
params_(0),
unresolved_(0),
decls_(0),
already_resolved_(false) {
SetDefaults(type, NULL, Handle<SerializedScopeInfo>::null());
}
Scope::Scope(Scope* outer_scope, Type type)
: inner_scopes_(4),
variables_(),
temps_(4),
params_(4),
unresolved_(16),
decls_(4),
already_resolved_(false) {
: isolate_(Isolate::Current()),
inner_scopes_(4),
variables_(),
temps_(4),
params_(4),
unresolved_(16),
decls_(4),
already_resolved_(false) {
SetDefaults(type, outer_scope, Handle<SerializedScopeInfo>::null());
// At some point we might want to provide outer scopes to
// eval scopes (by walking the stack and reading the scope info).
@ -145,13 +147,14 @@ Scope::Scope(Scope* outer_scope, Type type)
Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info)
: inner_scopes_(4),
variables_(),
temps_(4),
params_(4),
unresolved_(16),
decls_(4),
already_resolved_(true) {
: isolate_(Isolate::Current()),
inner_scopes_(4),
variables_(),
temps_(4),
params_(4),
unresolved_(16),
decls_(4),
already_resolved_(true) {
ASSERT(!scope_info.is_null());
SetDefaults(FUNCTION_SCOPE, NULL, scope_info);
if (scope_info->HasHeapAllocatedLocals()) {
@ -162,7 +165,8 @@ Scope::Scope(Scope* inner_scope, Handle<SerializedScopeInfo> scope_info)
Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name)
: inner_scopes_(1),
: isolate_(Isolate::Current()),
inner_scopes_(1),
variables_(),
temps_(0),
params_(0),
@ -186,7 +190,7 @@ void Scope::SetDefaults(Type type,
Handle<SerializedScopeInfo> scope_info) {
outer_scope_ = outer_scope;
type_ = type;
scope_name_ = FACTORY->empty_symbol();
scope_name_ = isolate_->factory()->empty_symbol();
dynamics_ = NULL;
receiver_ = NULL;
function_ = NULL;
@ -295,9 +299,12 @@ void Scope::Initialize(bool inside_with) {
receiver_ = outer_scope()->receiver();
} else {
Variable* var =
variables_.Declare(this, FACTORY->this_symbol(), Variable::VAR,
false, Variable::THIS);
var->set_rewrite(new Slot(var, Slot::PARAMETER, -1));
variables_.Declare(this,
isolate_->factory()->this_symbol(),
Variable::VAR,
false,
Variable::THIS);
var->set_rewrite(NewSlot(var, Slot::PARAMETER, -1));
receiver_ = var;
}
@ -305,8 +312,11 @@ void Scope::Initialize(bool inside_with) {
// Declare 'arguments' variable which exists in all functions.
// Note that it might never be accessed, in which case it won't be
// allocated during variable allocation.
variables_.Declare(this, FACTORY->arguments_symbol(), Variable::VAR,
true, Variable::ARGUMENTS);
variables_.Declare(this,
isolate_->factory()->arguments_symbol(),
Variable::VAR,
true,
Variable::ARGUMENTS);
}
}
@ -320,7 +330,7 @@ Variable* Scope::LocalLookup(Handle<String> name) {
//
// We should never lookup 'arguments' in this scope as it is implicitly
// present in every scope.
ASSERT(*name != *FACTORY->arguments_symbol());
ASSERT(*name != *isolate_->factory()->arguments_symbol());
// There should be no local slot with the given name.
ASSERT(scope_info_->StackSlotIndex(*name) < 0);
@ -340,7 +350,7 @@ Variable* Scope::LocalLookup(Handle<String> name) {
Variable* var =
variables_.Declare(this, name, mode, true, Variable::NORMAL);
var->set_rewrite(new Slot(var, Slot::CONTEXT, index));
var->set_rewrite(NewSlot(var, Slot::CONTEXT, index));
return var;
}
@ -397,7 +407,8 @@ VariableProxy* Scope::NewUnresolved(Handle<String> name,
// the same name because they may be removed selectively via
// RemoveUnresolved().
ASSERT(!already_resolved());
VariableProxy* proxy = new VariableProxy(name, false, inside_with, position);
VariableProxy* proxy = new(isolate_->zone()) VariableProxy(
isolate_, name, false, inside_with, position);
unresolved_.Add(proxy);
return proxy;
}
@ -697,7 +708,7 @@ Variable* Scope::NonLocal(Handle<String> name, Variable::Mode mode) {
// Declare a new non-local.
var = map->Declare(NULL, name, mode, true, Variable::NORMAL);
// Allocate it by giving it a dynamic lookup.
var->set_rewrite(new Slot(var, Slot::LOOKUP, -1));
var->set_rewrite(NewSlot(var, Slot::LOOKUP, -1));
}
return var;
}
@ -943,26 +954,28 @@ bool Scope::MustAllocateInContext(Variable* var) {
bool Scope::HasArgumentsParameter() {
for (int i = 0; i < params_.length(); i++) {
if (params_[i]->name().is_identical_to(FACTORY->arguments_symbol()))
if (params_[i]->name().is_identical_to(
isolate_->factory()->arguments_symbol())) {
return true;
}
}
return false;
}
void Scope::AllocateStackSlot(Variable* var) {
var->set_rewrite(new Slot(var, Slot::LOCAL, num_stack_slots_++));
var->set_rewrite(NewSlot(var, Slot::LOCAL, num_stack_slots_++));
}
void Scope::AllocateHeapSlot(Variable* var) {
var->set_rewrite(new Slot(var, Slot::CONTEXT, num_heap_slots_++));
var->set_rewrite(NewSlot(var, Slot::CONTEXT, num_heap_slots_++));
}
void Scope::AllocateParameterLocals() {
ASSERT(is_function_scope());
Variable* arguments = LocalLookup(FACTORY->arguments_symbol());
Variable* arguments = LocalLookup(isolate_->factory()->arguments_symbol());
ASSERT(arguments != NULL); // functions have 'arguments' declared implicitly
bool uses_nonstrict_arguments = false;
@ -1009,7 +1022,7 @@ void Scope::AllocateParameterLocals() {
} else {
ASSERT(var->rewrite() == NULL || var->IsParameter());
if (var->rewrite() == NULL) {
var->set_rewrite(new Slot(var, Slot::PARAMETER, i));
var->set_rewrite(NewSlot(var, Slot::PARAMETER, i));
}
}
}
@ -1020,7 +1033,7 @@ void Scope::AllocateParameterLocals() {
void Scope::AllocateNonParameterLocal(Variable* var) {
ASSERT(var->scope() == this);
ASSERT(var->rewrite() == NULL ||
!var->IsVariable(FACTORY->result_symbol()) ||
!var->IsVariable(isolate_->factory()->result_symbol()) ||
var->AsSlot() == NULL ||
var->AsSlot()->type() != Slot::LOCAL);
if (var->rewrite() == NULL && MustAllocate(var)) {

6
deps/v8/src/scopes.h

@ -319,6 +319,8 @@ class Scope: public ZoneObject {
explicit Scope(Type type);
Isolate* const isolate_;
// Scope tree.
Scope* outer_scope_; // the immediately enclosing outer scope, or NULL
ZoneList<Scope*> inner_scopes_; // the immediately enclosed inner scopes
@ -423,6 +425,10 @@ class Scope: public ZoneObject {
// Construct a catch scope with a binding for the name.
Scope(Scope* inner_scope, Handle<String> catch_variable_name);
inline Slot* NewSlot(Variable* var, Slot::Type type, int index) {
return new(isolate_->zone()) Slot(isolate_, var, type, index);
}
void AddInnerScope(Scope* inner_scope) {
if (inner_scope != NULL) {
inner_scopes_.Add(inner_scope);

57
deps/v8/src/spaces.cc

@ -402,7 +402,9 @@ void MemoryAllocator::FreeRawMemory(void* mem,
size_t length,
Executability executable) {
#ifdef DEBUG
ZapBlock(reinterpret_cast<Address>(mem), length);
// Do not try to zap the guard page.
size_t guard_size = (executable == EXECUTABLE) ? Page::kPageSize : 0;
ZapBlock(reinterpret_cast<Address>(mem) + guard_size, length - guard_size);
#endif
if (isolate_->code_range()->contains(static_cast<Address>(mem))) {
isolate_->code_range()->FreeRawMemory(mem, length);
@ -504,14 +506,28 @@ Page* MemoryAllocator::AllocatePages(int requested_pages,
LOG(isolate_, NewEvent("PagedChunk", chunk, chunk_size));
*allocated_pages = PagesInChunk(static_cast<Address>(chunk), chunk_size);
// We may 'lose' a page due to alignment.
ASSERT(*allocated_pages >= kPagesPerChunk - 1);
if (*allocated_pages == 0) {
FreeRawMemory(chunk, chunk_size, owner->executable());
size_t guard_size = (owner->executable() == EXECUTABLE) ? Page::kPageSize : 0;
// Check that we got at least one page that we can use.
if (*allocated_pages <= ((guard_size != 0) ? 1 : 0)) {
FreeRawMemory(chunk,
chunk_size,
owner->executable());
LOG(isolate_, DeleteEvent("PagedChunk", chunk));
return Page::FromAddress(NULL);
}
if (guard_size != 0) {
OS::Guard(chunk, guard_size);
chunk_size -= guard_size;
chunk = static_cast<Address>(chunk) + guard_size;
--*allocated_pages;
}
int chunk_id = Pop();
chunks_[chunk_id].init(static_cast<Address>(chunk), chunk_size, owner);
@ -681,7 +697,8 @@ void MemoryAllocator::DeleteChunk(int chunk_id) {
LOG(isolate_, DeleteEvent("PagedChunk", c.address()));
ObjectSpace space = static_cast<ObjectSpace>(1 << c.owner_identity());
size_t size = c.size();
FreeRawMemory(c.address(), size, c.executable());
size_t guard_size = (c.executable() == EXECUTABLE) ? Page::kPageSize : 0;
FreeRawMemory(c.address() - guard_size, size + guard_size, c.executable());
PerformAllocationCallback(space, kAllocationActionFree, size);
}
c.init(NULL, 0, NULL);
@ -2672,9 +2689,10 @@ LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes,
Executability executable) {
size_t requested = ChunkSizeFor(size_in_bytes);
size_t size;
size_t guard_size = (executable == EXECUTABLE) ? Page::kPageSize : 0;
Isolate* isolate = Isolate::Current();
void* mem = isolate->memory_allocator()->AllocateRawMemory(
requested, &size, executable);
requested + guard_size, &size, executable);
if (mem == NULL) return NULL;
// The start of the chunk may be overlayed with a page so we have to
@ -2682,13 +2700,19 @@ LargeObjectChunk* LargeObjectChunk::New(int size_in_bytes,
ASSERT((size & Page::kPageFlagMask) == 0);
LOG(isolate, NewEvent("LargeObjectChunk", mem, size));
if (size < requested) {
if (size < requested + guard_size) {
isolate->memory_allocator()->FreeRawMemory(
mem, size, executable);
LOG(isolate, DeleteEvent("LargeObjectChunk", mem));
return NULL;
}
if (guard_size != 0) {
OS::Guard(mem, guard_size);
size -= guard_size;
mem = static_cast<Address>(mem) + guard_size;
}
ObjectSpace space = (executable == EXECUTABLE)
? kObjectSpaceCodeSpace
: kObjectSpaceLoSpace;
@ -2742,9 +2766,11 @@ void LargeObjectSpace::TearDown() {
ObjectSpace space = kObjectSpaceLoSpace;
if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace;
size_t size = chunk->size();
heap()->isolate()->memory_allocator()->FreeRawMemory(chunk->address(),
size,
executable);
size_t guard_size = (executable == EXECUTABLE) ? Page::kPageSize : 0;
heap()->isolate()->memory_allocator()->FreeRawMemory(
chunk->address() - guard_size,
size + guard_size,
executable);
heap()->isolate()->memory_allocator()->PerformAllocationCallback(
space, kAllocationActionFree, size);
}
@ -2941,10 +2967,15 @@ void LargeObjectSpace::FreeUnmarkedObjects() {
objects_size_ -= object->Size();
page_count_--;
ObjectSpace space = kObjectSpaceLoSpace;
if (executable == EXECUTABLE) space = kObjectSpaceCodeSpace;
heap()->isolate()->memory_allocator()->FreeRawMemory(chunk_address,
chunk_size,
executable);
size_t guard_size = 0;
if (executable == EXECUTABLE) {
space = kObjectSpaceCodeSpace;
guard_size = Page::kPageSize;
}
heap()->isolate()->memory_allocator()->FreeRawMemory(
chunk_address - guard_size,
chunk_size + guard_size,
executable);
heap()->isolate()->memory_allocator()->PerformAllocationCallback(
space, kAllocationActionFree, size_);
LOG(heap()->isolate(), DeleteEvent("LargeObjectChunk", chunk_address));

3
deps/v8/src/spaces.h

@ -647,13 +647,11 @@ class MemoryAllocator {
#ifdef V8_TARGET_ARCH_X64
static const int kPagesPerChunk = 32;
// On 64 bit the chunk table consists of 4 levels of 4096-entry tables.
static const int kPagesPerChunkLog2 = 5;
static const int kChunkTableLevels = 4;
static const int kChunkTableBitsPerLevel = 12;
#else
static const int kPagesPerChunk = 16;
// On 32 bit the chunk table consists of 2 levels of 256-entry tables.
static const int kPagesPerChunkLog2 = 4;
static const int kChunkTableLevels = 2;
static const int kChunkTableBitsPerLevel = 8;
#endif
@ -662,7 +660,6 @@ class MemoryAllocator {
MemoryAllocator();
static const int kChunkSize = kPagesPerChunk * Page::kPageSize;
static const int kChunkSizeLog2 = kPagesPerChunkLog2 + kPageSizeBits;
// Maximum space size in bytes.
intptr_t capacity_;

5
deps/v8/src/stub-cache.h

@ -662,6 +662,8 @@ class KeyedLoadStubCompiler: public StubCompiler {
static void GenerateLoadFastElement(MacroAssembler* masm);
static void GenerateLoadFastDoubleElement(MacroAssembler* masm);
static void GenerateLoadDictionaryElement(MacroAssembler* masm);
private:
@ -717,6 +719,9 @@ class KeyedStoreStubCompiler: public StubCompiler {
static void GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array);
static void GenerateStoreFastDoubleElement(MacroAssembler* masm,
bool is_js_array);
static void GenerateStoreExternalArray(MacroAssembler* masm,
JSObject::ElementsKind elements_kind);

18
deps/v8/src/v8.cc

@ -50,6 +50,9 @@ bool V8::has_been_disposed_ = false;
bool V8::has_fatal_error_ = false;
bool V8::use_crankshaft_ = true;
static Mutex* entropy_mutex = OS::CreateMutex();
static EntropySource entropy_source;
bool V8::Initialize(Deserializer* des) {
InitializeOncePerProcess();
@ -102,8 +105,14 @@ void V8::TearDown() {
static void seed_random(uint32_t* state) {
for (int i = 0; i < 2; ++i) {
state[i] = FLAG_random_seed;
while (state[i] == 0) {
if (FLAG_random_seed != 0) {
state[i] = FLAG_random_seed;
} else if (entropy_source != NULL) {
uint32_t val;
ScopedLock lock(entropy_mutex);
entropy_source(reinterpret_cast<unsigned char*>(&val), sizeof(uint32_t));
state[i] = val;
} else {
state[i] = random();
}
}
@ -124,6 +133,11 @@ static uint32_t random_base(uint32_t* state) {
}
void V8::SetEntropySource(EntropySource source) {
entropy_source = source;
}
// Used by JavaScript APIs
uint32_t V8::Random(Isolate* isolate) {
ASSERT(isolate == Isolate::Current());

3
deps/v8/src/v8.h

@ -91,6 +91,9 @@ class V8 : public AllStatic {
static void FatalProcessOutOfMemory(const char* location,
bool take_snapshot = false);
// Allows an entropy source to be provided for use in random number
// generation.
static void SetEntropySource(EntropySource source);
// Random number generation support. Not cryptographically safe.
static uint32_t Random(Isolate* isolate);
// We use random numbers internally in memory allocation and in the

10
deps/v8/src/v8globals.h

@ -506,6 +506,16 @@ enum CallKind {
CALL_AS_FUNCTION
};
static const uint32_t kHoleNanUpper32 = 0x7FFFFFFF;
static const uint32_t kHoleNanLower32 = 0xFFFFFFFF;
static const uint32_t kNaNOrInfinityLowerBoundUpper32 = 0x7FF00000;
const uint64_t kHoleNanInt64 =
(static_cast<uint64_t>(kHoleNanUpper32) << 32) | kHoleNanLower32;
const uint64_t kLastNonNaNInt64 =
(static_cast<uint64_t>(kNaNOrInfinityLowerBoundUpper32) << 32);
} } // namespace v8::internal
#endif // V8_V8GLOBALS_H_

43
deps/v8/src/v8natives.js

@ -675,7 +675,8 @@ function DefineProxyProperty(obj, p, attributes, should_throw) {
var result = %_CallFunction(handler, p, attributes, defineProperty);
if (!ToBoolean(result)) {
if (should_throw) {
throw MakeTypeError("handler_failed", [handler, "defineProperty"]);
throw MakeTypeError("handler_returned_false",
[handler, "defineProperty"]);
} else {
return false;
}
@ -1032,11 +1033,30 @@ function ObjectDefineProperties(obj, properties) {
}
// Harmony proxies.
function ProxyFix(obj) {
var handler = %GetHandler(obj);
var fix = handler.fix;
if (IS_UNDEFINED(fix)) {
throw MakeTypeError("handler_trap_missing", [handler, "fix"]);
}
var props = %_CallFunction(handler, fix);
if (IS_UNDEFINED(props)) {
throw MakeTypeError("handler_returned_undefined", [handler, "fix"]);
}
%Fix(obj);
ObjectDefineProperties(obj, props);
}
// ES5 section 15.2.3.8.
function ObjectSeal(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["seal"]);
}
if (%IsJSProxy(obj)) {
ProxyFix(obj);
}
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@ -1046,7 +1066,8 @@ function ObjectSeal(obj) {
DefineOwnProperty(obj, name, desc, true);
}
}
return ObjectPreventExtension(obj);
%PreventExtensions(obj);
return obj;
}
@ -1055,6 +1076,9 @@ function ObjectFreeze(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["freeze"]);
}
if (%IsJSProxy(obj)) {
ProxyFix(obj);
}
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@ -1065,7 +1089,8 @@ function ObjectFreeze(obj) {
DefineOwnProperty(obj, name, desc, true);
}
}
return ObjectPreventExtension(obj);
%PreventExtensions(obj);
return obj;
}
@ -1074,6 +1099,9 @@ function ObjectPreventExtension(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["preventExtension"]);
}
if (%IsJSProxy(obj)) {
ProxyFix(obj);
}
%PreventExtensions(obj);
return obj;
}
@ -1084,6 +1112,9 @@ function ObjectIsSealed(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["isSealed"]);
}
if (%IsJSProxy(obj)) {
return false;
}
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@ -1102,6 +1133,9 @@ function ObjectIsFrozen(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["isFrozen"]);
}
if (%IsJSProxy(obj)) {
return false;
}
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
@ -1121,6 +1155,9 @@ function ObjectIsExtensible(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("obj_ctor_property_non_object", ["isExtensible"]);
}
if (%IsJSProxy(obj)) {
return true;
}
return %IsExtensible(obj);
}

4
deps/v8/src/version.cc

@ -34,8 +34,8 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 4
#define BUILD_NUMBER 12
#define PATCH_LEVEL 1
#define BUILD_NUMBER 14
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0

2
deps/v8/src/x64/assembler-x64.h

@ -125,7 +125,7 @@ struct Register {
return names[index];
}
static Register toRegister(int code) {
static Register from_code(int code) {
Register r = { code };
return r;
}

2
deps/v8/src/x64/code-stubs-x64.cc

@ -2529,6 +2529,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
#else
// Already there in AMD64 calling convention.
ASSERT(arg1.is(rdi));
USE(arg1);
#endif
// Locate the code entry and call it.
@ -3198,6 +3199,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
Handle<Code> adaptor =
Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline();
__ SetCallKind(rcx, CALL_AS_METHOD);
__ Jump(adaptor, RelocInfo::CODE_TARGET);
}

14
deps/v8/src/x64/deoptimizer-x64.cc

@ -128,7 +128,9 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
Address instruction_start = function->code()->instruction_start();
Address jump_table_address =
instruction_start + function->code()->safepoint_table_offset();
#ifdef DEBUG
Address previous_pc = instruction_start;
#endif
SafepointTableDeoptimiztionEntryIterator deoptimizations(function->code());
Address entry_pc = NULL;
@ -157,12 +159,16 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
CodePatcher patcher(call_address, Assembler::kCallInstructionLength);
patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index, LAZY),
RelocInfo::NONE);
#ifdef DEBUG
previous_pc = call_end_address;
#endif
} else {
// Not room enough for a long Call instruction. Write a short call
// instruction to a long jump placed elsewhere in the code.
#ifdef DEBUG
Address short_call_end_address =
call_address + MacroAssembler::kShortCallInstructionLength;
#endif
ASSERT(next_pc >= short_call_end_address);
// Write jump in jump-table.
@ -177,7 +183,9 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) {
CodePatcher call_patcher(call_address,
MacroAssembler::kShortCallInstructionLength);
call_patcher.masm()->call(jump_table_address);
#ifdef DEBUG
previous_pc = short_call_end_address;
#endif
}
// Continue with next deoptimization entry.
@ -643,7 +651,7 @@ void Deoptimizer::EntryGenerator::Generate() {
// We push all registers onto the stack, even though we do not need
// to restore all later.
for (int i = 0; i < kNumberOfRegisters; i++) {
Register r = Register::toRegister(i);
Register r = Register::from_code(i);
__ push(r);
}
@ -801,12 +809,12 @@ void Deoptimizer::EntryGenerator::Generate() {
// Restore the registers from the stack.
for (int i = kNumberOfRegisters - 1; i >= 0 ; i--) {
Register r = Register::toRegister(i);
Register r = Register::from_code(i);
// Do not restore rsp, simply pop the value into the next register
// and overwrite this afterwards.
if (r.is(rsp)) {
ASSERT(i > 0);
r = Register::toRegister(i - 1);
r = Register::from_code(i - 1);
}
__ pop(r);
}

2
deps/v8/src/x64/full-codegen-x64.cc

@ -4060,10 +4060,8 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
default: {
VisitForAccumulatorValue(expr->right());
Condition cc = no_condition;
bool strict = false;
switch (op) {
case Token::EQ_STRICT:
strict = true;
// Fall through.
case Token::EQ:
cc = equal;

66
deps/v8/src/x64/lithium-codegen-x64.cc

@ -1883,7 +1883,6 @@ void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
__ push(ToRegister(instr->InputAt(0)));
__ Push(instr->function());
Register temp = ToRegister(instr->TempAt(0));
static const int kAdditionalDelta = 10;
int delta =
masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta;
@ -2245,10 +2244,35 @@ void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) {
}
Operand LCodeGen::BuildExternalArrayOperand(
void LCodeGen::DoLoadKeyedFastDoubleElement(
LLoadKeyedFastDoubleElement* instr) {
Register elements = ToRegister(instr->elements());
XMMRegister result(ToDoubleRegister(instr->result()));
if (instr->hydrogen()->RequiresHoleCheck()) {
int offset = FixedDoubleArray::kHeaderSize - kHeapObjectTag +
sizeof(kHoleNanLower32);
Operand hole_check_operand = BuildFastArrayOperand(
instr->elements(),
instr->key(),
JSObject::FAST_DOUBLE_ELEMENTS,
offset);
__ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
DeoptimizeIf(equal, instr->environment());
}
Operand double_load_operand = BuildFastArrayOperand(
instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
FixedDoubleArray::kHeaderSize - kHeapObjectTag);
__ movsd(result, double_load_operand);
}
Operand LCodeGen::BuildFastArrayOperand(
LOperand* external_pointer,
LOperand* key,
JSObject::ElementsKind elements_kind) {
JSObject::ElementsKind elements_kind,
uint32_t offset) {
Register external_pointer_reg = ToRegister(external_pointer);
int shift_size = ElementsKindToShiftSize(elements_kind);
if (key->IsConstantOperand()) {
@ -2256,10 +2280,12 @@ Operand LCodeGen::BuildExternalArrayOperand(
if (constant_value & 0xF0000000) {
Abort("array index constant value too big");
}
return Operand(external_pointer_reg, constant_value * (1 << shift_size));
return Operand(external_pointer_reg,
constant_value * (1 << shift_size) + offset);
} else {
ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size);
return Operand(external_pointer_reg, ToRegister(key), scale_factor, 0);
return Operand(external_pointer_reg, ToRegister(key),
scale_factor, offset);
}
}
@ -2267,8 +2293,8 @@ Operand LCodeGen::BuildExternalArrayOperand(
void LCodeGen::DoLoadKeyedSpecializedArrayElement(
LLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
instr->key(), elements_kind));
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
instr->key(), elements_kind, 0));
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
XMMRegister result(ToDoubleRegister(instr->result()));
__ movss(result, operand);
@ -2994,8 +3020,8 @@ void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
void LCodeGen::DoStoreKeyedSpecializedArrayElement(
LStoreKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
Operand operand(BuildExternalArrayOperand(instr->external_pointer(),
instr->key(), elements_kind));
Operand operand(BuildFastArrayOperand(instr->external_pointer(),
instr->key(), elements_kind, 0));
if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
XMMRegister value(ToDoubleRegister(instr->value()));
__ cvtsd2ss(value, value);
@ -3072,6 +3098,28 @@ void LCodeGen::DoStoreKeyedFastElement(LStoreKeyedFastElement* instr) {
}
void LCodeGen::DoStoreKeyedFastDoubleElement(
LStoreKeyedFastDoubleElement* instr) {
XMMRegister value = ToDoubleRegister(instr->value());
Register elements = ToRegister(instr->elements());
Label have_value;
__ ucomisd(value, value);
__ j(parity_odd, &have_value); // NaN.
ExternalReference canonical_nan_reference =
ExternalReference::address_of_canonical_non_hole_nan();
__ Set(kScratchRegister, BitCast<uint64_t>(
FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
__ movq(value, kScratchRegister);
__ bind(&have_value);
Operand double_store_operand = BuildFastArrayOperand(
instr->elements(), instr->key(), JSObject::FAST_DOUBLE_ELEMENTS,
FixedDoubleArray::kHeaderSize - kHeapObjectTag);
__ movsd(double_store_operand, value);
}
void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
ASSERT(ToRegister(instr->object()).is(rdx));
ASSERT(ToRegister(instr->key()).is(rcx));

5
deps/v8/src/x64/lithium-codegen-x64.h

@ -215,10 +215,11 @@ class LCodeGen BASE_EMBEDDED {
Register ToRegister(int index) const;
XMMRegister ToDoubleRegister(int index) const;
Operand BuildExternalArrayOperand(
Operand BuildFastArrayOperand(
LOperand* external_pointer,
LOperand* key,
JSObject::ElementsKind elements_kind);
JSObject::ElementsKind elements_kind,
uint32_t offset);
// Specific math operations - used from DoUnaryMathOperation.
void EmitIntegerMathAbs(LUnaryMathOperation* instr);

35
deps/v8/src/x64/lithium-x64.cc

@ -428,6 +428,15 @@ void LStoreKeyedFastElement::PrintDataTo(StringStream* stream) {
}
void LStoreKeyedFastDoubleElement::PrintDataTo(StringStream* stream) {
elements()->PrintTo(stream);
stream->Add("[");
key()->PrintTo(stream);
stream->Add("] <- ");
value()->PrintTo(stream);
}
void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) {
object()->PrintTo(stream);
stream->Add("[");
@ -1822,6 +1831,18 @@ LInstruction* LChunkBuilder::DoLoadKeyedFastElement(
}
LInstruction* LChunkBuilder::DoLoadKeyedFastDoubleElement(
HLoadKeyedFastDoubleElement* instr) {
ASSERT(instr->representation().IsDouble());
ASSERT(instr->key()->representation().IsInteger32());
LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
LLoadKeyedFastDoubleElement* result =
new LLoadKeyedFastDoubleElement(elements, key);
return AssignEnvironment(DefineAsRegister(result));
}
LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement(
HLoadKeyedSpecializedArrayElement* instr) {
JSObject::ElementsKind elements_kind = instr->elements_kind();
@ -1874,6 +1895,20 @@ LInstruction* LChunkBuilder::DoStoreKeyedFastElement(
}
LInstruction* LChunkBuilder::DoStoreKeyedFastDoubleElement(
HStoreKeyedFastDoubleElement* instr) {
ASSERT(instr->value()->representation().IsDouble());
ASSERT(instr->elements()->representation().IsTagged());
ASSERT(instr->key()->representation().IsInteger32());
LOperand* elements = UseRegisterAtStart(instr->elements());
LOperand* val = UseTempRegister(instr->value());
LOperand* key = UseRegisterOrConstantAtStart(instr->key());
return new LStoreKeyedFastDoubleElement(elements, key, val);
}
LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement(
HStoreKeyedSpecializedArrayElement* instr) {
Representation representation(instr->value()->representation());

40
deps/v8/src/x64/lithium-x64.h

@ -121,6 +121,7 @@ class LCodeGen;
V(LoadFunctionPrototype) \
V(LoadGlobalCell) \
V(LoadGlobalGeneric) \
V(LoadKeyedFastDoubleElement) \
V(LoadKeyedFastElement) \
V(LoadKeyedGeneric) \
V(LoadKeyedSpecializedArrayElement) \
@ -147,6 +148,7 @@ class LCodeGen;
V(StoreContextSlot) \
V(StoreGlobalCell) \
V(StoreGlobalGeneric) \
V(StoreKeyedFastDoubleElement) \
V(StoreKeyedFastElement) \
V(StoreKeyedGeneric) \
V(StoreKeyedSpecializedArrayElement) \
@ -1134,6 +1136,22 @@ class LLoadKeyedFastElement: public LTemplateInstruction<1, 2, 0> {
};
class LLoadKeyedFastDoubleElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedFastDoubleElement(LOperand* elements, LOperand* key) {
inputs_[0] = elements;
inputs_[1] = key;
}
DECLARE_CONCRETE_INSTRUCTION(LoadKeyedFastDoubleElement,
"load-keyed-fast-double-element")
DECLARE_HYDROGEN_ACCESSOR(LoadKeyedFastDoubleElement)
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
};
class LLoadKeyedSpecializedArrayElement: public LTemplateInstruction<1, 2, 0> {
public:
LLoadKeyedSpecializedArrayElement(LOperand* external_pointer,
@ -1585,6 +1603,28 @@ class LStoreKeyedFastElement: public LTemplateInstruction<0, 3, 0> {
};
class LStoreKeyedFastDoubleElement: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedFastDoubleElement(LOperand* elements,
LOperand* key,
LOperand* val) {
inputs_[0] = elements;
inputs_[1] = key;
inputs_[2] = val;
}
DECLARE_CONCRETE_INSTRUCTION(StoreKeyedFastDoubleElement,
"store-keyed-fast-double-element")
DECLARE_HYDROGEN_ACCESSOR(StoreKeyedFastDoubleElement)
virtual void PrintDataTo(StringStream* stream);
LOperand* elements() { return inputs_[0]; }
LOperand* key() { return inputs_[1]; }
LOperand* value() { return inputs_[2]; }
};
class LStoreKeyedSpecializedArrayElement: public LTemplateInstruction<0, 3, 0> {
public:
LStoreKeyedSpecializedArrayElement(LOperand* external_pointer,

3
deps/v8/src/x64/macro-assembler-x64.cc

@ -384,6 +384,9 @@ void MacroAssembler::AssertFastElements(Register elements) {
CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
Heap::kFixedArrayMapRootIndex);
j(equal, &ok, Label::kNear);
CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
Heap::kFixedDoubleArrayMapRootIndex);
j(equal, &ok, Label::kNear);
CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
Heap::kFixedCOWArrayMapRootIndex);
j(equal, &ok, Label::kNear);

2
deps/v8/src/x64/regexp-macro-assembler-x64.cc

@ -661,7 +661,6 @@ bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type,
}
__ movq(rbx, ExternalReference::re_word_character_map());
ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
ExternalReference word_map = ExternalReference::re_word_character_map();
__ testb(Operand(rbx, current_character(), times_1, 0),
current_character());
BranchOrBacktrack(zero, on_no_match);
@ -676,7 +675,6 @@ bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type,
}
__ movq(rbx, ExternalReference::re_word_character_map());
ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
ExternalReference word_map = ExternalReference::re_word_character_map();
__ testb(Operand(rbx, current_character(), times_1, 0),
current_character());
BranchOrBacktrack(not_zero, on_no_match);

140
deps/v8/src/x64/stub-cache-x64.cc

@ -1089,9 +1089,8 @@ void StubCompiler::GenerateLoadConstant(JSObject* object,
__ JumpIfSmi(receiver, miss);
// Check that the maps haven't changed.
Register reg =
CheckPrototypes(object, receiver, holder,
scratch1, scratch2, scratch3, name, miss);
CheckPrototypes(object, receiver, holder,
scratch1, scratch2, scratch3, name, miss);
// Return the constant value.
__ Move(rax, Handle<Object>(value));
@ -3584,6 +3583,57 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
}
void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss_force_generic, slow_allocate_heapnumber;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
// Check that the key is a smi.
__ JumpIfNotSmi(rax, &miss_force_generic);
// Get the elements array.
__ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
__ AssertFastElements(rcx);
// Check that the key is within bounds.
__ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
__ j(above_equal, &miss_force_generic);
// Check for the hole
__ SmiToInteger32(kScratchRegister, rax);
uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
__ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset),
Immediate(kHoleNanUpper32));
__ j(equal, &miss_force_generic);
// Always allocate a heap number for the result.
__ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8,
FixedDoubleArray::kHeaderSize));
__ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber);
// Set the value.
__ movq(rax, rcx);
__ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
__ ret(0);
__ bind(&slow_allocate_heapnumber);
Handle<Code> slow_ic =
masm->isolate()->builtins()->KeyedLoadIC_Slow();
__ jmp(slow_ic, RelocInfo::CODE_TARGET);
__ bind(&miss_force_generic);
Handle<Code> miss_ic =
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
__ jmp(miss_ic, RelocInfo::CODE_TARGET);
}
void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
@ -3634,6 +3684,90 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
}
void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
MacroAssembler* masm,
bool is_js_array) {
// ----------- S t a t e -------------
// -- rax : value
// -- rcx : key
// -- rdx : receiver
// -- rsp[0] : return address
// -----------------------------------
Label miss_force_generic, smi_value, is_nan, maybe_nan;
Label have_double_value, not_nan;
// This stub is meant to be tail-jumped to, the receiver must already
// have been verified by the caller to not be a smi.
// Check that the key is a smi.
__ JumpIfNotSmi(rcx, &miss_force_generic);
// Get the elements array.
__ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
__ AssertFastElements(rdi);
// Check that the key is within bounds.
if (is_js_array) {
__ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
} else {
__ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
}
__ j(above_equal, &miss_force_generic);
// Handle smi values specially
__ JumpIfSmi(rax, &smi_value, Label::kNear);
__ CheckMap(rax,
masm->isolate()->factory()->heap_number_map(),
&miss_force_generic,
DONT_DO_SMI_CHECK);
// Double value, canonicalize NaN.
uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
__ cmpl(FieldOperand(rax, offset),
Immediate(kNaNOrInfinityLowerBoundUpper32));
__ j(greater_equal, &maybe_nan, Label::kNear);
__ bind(&not_nan);
__ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
__ bind(&have_double_value);
__ SmiToInteger32(rcx, rcx);
__ movsd(FieldOperand(rdi, rcx, times_8, FixedDoubleArray::kHeaderSize),
xmm0);
__ ret(0);
__ bind(&maybe_nan);
// Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
// it's an Infinity, and the non-NaN code path applies.
__ j(greater, &is_nan, Label::kNear);
__ cmpl(FieldOperand(rax, HeapNumber::kValueOffset), Immediate(0));
__ j(zero, &not_nan);
__ bind(&is_nan);
// Convert all NaNs to the same canonical NaN value when they are stored in
// the double array.
__ Set(kScratchRegister, BitCast<uint64_t>(
FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
__ movq(xmm0, kScratchRegister);
__ jmp(&have_double_value, Label::kNear);
__ bind(&smi_value);
// Value is a smi. convert to a double and store.
__ SmiToInteger32(rax, rax);
__ push(rax);
__ fild_s(Operand(rsp, 0));
__ pop(rax);
__ SmiToInteger32(rcx, rcx);
__ fstp_d(FieldOperand(rdi, rcx, times_8, FixedDoubleArray::kHeaderSize));
__ ret(0);
// Handle store cache miss, replacing the ic with the generic stub.
__ bind(&miss_force_generic);
Handle<Code> ic_force_generic =
masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
__ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
}
#undef __
} } // namespace v8::internal

2
deps/v8/src/zone.h

@ -74,6 +74,8 @@ class Zone {
inline void adjust_segment_bytes_allocated(int delta);
inline Isolate* isolate() { return isolate_; }
static unsigned allocation_size_;
private:

24
deps/v8/test/cctest/SConscript

@ -29,9 +29,23 @@ import sys
from os.path import join, dirname, abspath
root_dir = dirname(File('SConstruct').rfile().abspath)
sys.path.append(join(root_dir, 'tools'))
import js2c
Import('context object_files tools')
# Needed for test-log. Paths are relative to the cctest dir.
JS_FILES_FOR_TESTS = [
'../../../tools/splaytree.js',
'../../../tools/codemap.js',
'../../../tools/csvparser.js',
'../../../tools/consarray.js',
'../../../tools/profile.js',
'../../../tools/profile_view.js',
'../../../tools/logreader.js',
'log-eq-of-logging-and-traversal.js',
]
SOURCES = {
'all': [
'gay-fixed.cc',
@ -109,9 +123,19 @@ def Build():
env = Environment(tools=tools)
env.Replace(**context.flags['cctest'])
context.ApplyEnvOverrides(env)
env['BUILDERS']['JS2C'] = Builder(action=js2c.JS2C)
# Combine the JavaScript library files into a single C++ file and
# compile it.
js_files = [s for s in JS_FILES_FOR_TESTS]
js_files_src = env.JS2C(
['js-files-for-cctest.cc'], js_files, **{'TYPE': 'TEST', 'COMPRESSION': 'off'})
js_files_obj = context.ConfigureObject(env, js_files_src, CPPPATH=['.'])
# 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.
object_files.append(js_files_obj)
return env.Program('cctest', ['cctest.cc', cctest_files, object_files],
PDB='cctest.exe.pdb')

41
deps/v8/test/cctest/cctest.gyp

@ -26,6 +26,9 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
'variables': {
'generated_file': '<(SHARED_INTERMEDIATE_DIR)/resources.cc',
},
'includes': [ '../../build/v8-features.gypi' ],
'targets': [
{
@ -33,11 +36,13 @@
'type': 'executable',
'dependencies': [
'../../tools/gyp/v8.gyp:v8',
'resources',
],
'include_dirs': [
'../../src',
],
'sources': [
'<(generated_file)',
'cctest.cc',
'gay-fixed.cc',
'gay-precision.cc',
@ -131,5 +136,41 @@
}],
],
},
{
'target_name': 'resources',
'type': 'none',
'variables': {
'file_list': [
'../../tools/splaytree.js',
'../../tools/codemap.js',
'../../tools/csvparser.js',
'../../tools/consarray.js',
'../../tools/profile.js',
'../../tools/profile_view.js',
'../../tools/logreader.js',
'log-eq-of-logging-and-traversal.js',
],
},
'actions': [
{
'action_name': 'js2c',
'inputs': [
'../../tools/js2c.py',
'<@(file_list)',
],
'outputs': [
'<(generated_file)',
],
'action': [
'python',
'../../tools/js2c.py',
'<@(_outputs)',
'TEST', # type
'off', # compression
'<@(file_list)',
],
}
],
},
],
}

22
deps/v8/test/cctest/log-eq-of-logging-and-traversal.js

@ -137,36 +137,38 @@ function RunTest() {
return entityA.size === entityB.size && entityNamesEqual(entityA, entityB);
}
var i = 0, j = 0, k = logging_entries.length, l = traversal_entries.length;
var l_pos = 0, t_pos = 0;
var l_len = logging_entries.length, t_len = traversal_entries.length;
var comparison = [];
var equal = true;
// Do a merge-like comparison of entries. At the same address we expect to
// find the same entries. We skip builtins during log parsing, but compiled
// functions traversal may erroneously recognize them as functions, so we are
// expecting more functions in traversal vs. logging.
while (i < k && j < l) {
var entryA = logging_entries[i], entryB = traversal_entries[j];
while (l_pos < l_len && t_pos < t_len) {
var entryA = logging_entries[l_pos];
var entryB = traversal_entries[t_pos];
var cmp = addressComparator(entryA, entryB);
var entityA = entryA[1], entityB = entryB[1];
var address = entryA[0];
if (cmp < 0) {
++i;
++l_pos;
entityB = null;
} else if (cmp > 0) {
++j;
++t_pos;
entityA = null;
address = entryB[0];
} else {
++i;
++j;
++l_pos;
++t_pos;
}
var entities_equal = entitiesEqual(entityA, entityB);
if (!entities_equal) equal = false;
comparison.push([entities_equal, address, entityA, entityB]);
}
if (i < k) equal = false;
while (i < k) {
var entryA = logging_entries[i++];
if (l_pos < l_len) equal = false;
while (l_pos < l_len) {
var entryA = logging_entries[l_pos++];
comparison.push([false, entryA[0], entryA[1], null]);
}
return [equal, comparison];

110
deps/v8/test/cctest/test-api.cc

@ -1026,6 +1026,90 @@ THREADED_TEST(OutOfSignedRangeUnsignedInteger) {
}
THREADED_TEST(IsNativeError) {
v8::HandleScope scope;
LocalContext env;
v8::Handle<Value> syntax_error = CompileRun(
"var out = 0; try { eval(\"#\"); } catch(x) { out = x; } out; ");
CHECK(syntax_error->IsNativeError());
v8::Handle<Value> not_error = CompileRun("{a:42}");
CHECK(!not_error->IsNativeError());
v8::Handle<Value> not_object = CompileRun("42");
CHECK(!not_object->IsNativeError());
}
THREADED_TEST(StringObject) {
v8::HandleScope scope;
LocalContext env;
v8::Handle<Value> boxed_string = CompileRun("new String(\"test\")");
CHECK(boxed_string->IsStringObject());
v8::Handle<Value> unboxed_string = CompileRun("\"test\"");
CHECK(!unboxed_string->IsStringObject());
v8::Handle<Value> boxed_not_string = CompileRun("new Number(42)");
CHECK(!boxed_not_string->IsStringObject());
v8::Handle<Value> not_object = CompileRun("0");
CHECK(!not_object->IsStringObject());
v8::Handle<v8::StringObject> as_boxed = boxed_string.As<v8::StringObject>();
CHECK(!as_boxed.IsEmpty());
Local<v8::String> the_string = as_boxed->StringValue();
CHECK(!the_string.IsEmpty());
ExpectObject("\"test\"", the_string);
v8::Handle<v8::Value> new_boxed_string = v8::StringObject::New(the_string);
CHECK(new_boxed_string->IsStringObject());
as_boxed = new_boxed_string.As<v8::StringObject>();
the_string = as_boxed->StringValue();
CHECK(!the_string.IsEmpty());
ExpectObject("\"test\"", the_string);
}
THREADED_TEST(NumberObject) {
v8::HandleScope scope;
LocalContext env;
v8::Handle<Value> boxed_number = CompileRun("new Number(42)");
CHECK(boxed_number->IsNumberObject());
v8::Handle<Value> unboxed_number = CompileRun("42");
CHECK(!unboxed_number->IsNumberObject());
v8::Handle<Value> boxed_not_number = CompileRun("new Boolean(false)");
CHECK(!boxed_not_number->IsNumberObject());
v8::Handle<v8::NumberObject> as_boxed = boxed_number.As<v8::NumberObject>();
CHECK(!as_boxed.IsEmpty());
double the_number = as_boxed->NumberValue();
CHECK_EQ(42.0, the_number);
v8::Handle<v8::Value> new_boxed_number = v8::NumberObject::New(43);
CHECK(new_boxed_number->IsNumberObject());
as_boxed = new_boxed_number.As<v8::NumberObject>();
the_number = as_boxed->NumberValue();
CHECK_EQ(43.0, the_number);
}
THREADED_TEST(BooleanObject) {
v8::HandleScope scope;
LocalContext env;
v8::Handle<Value> boxed_boolean = CompileRun("new Boolean(true)");
CHECK(boxed_boolean->IsBooleanObject());
v8::Handle<Value> unboxed_boolean = CompileRun("true");
CHECK(!unboxed_boolean->IsBooleanObject());
v8::Handle<Value> boxed_not_boolean = CompileRun("new Number(42)");
CHECK(!boxed_not_boolean->IsBooleanObject());
v8::Handle<v8::BooleanObject> as_boxed =
boxed_boolean.As<v8::BooleanObject>();
CHECK(!as_boxed.IsEmpty());
bool the_boolean = as_boxed->BooleanValue();
CHECK_EQ(true, the_boolean);
v8::Handle<v8::Value> boxed_true = v8::BooleanObject::New(true);
v8::Handle<v8::Value> boxed_false = v8::BooleanObject::New(false);
CHECK(boxed_true->IsBooleanObject());
CHECK(boxed_false->IsBooleanObject());
as_boxed = boxed_true.As<v8::BooleanObject>();
CHECK_EQ(true, as_boxed->BooleanValue());
as_boxed = boxed_false.As<v8::BooleanObject>();
CHECK_EQ(false, as_boxed->BooleanValue());
}
THREADED_TEST(Number) {
v8::HandleScope scope;
LocalContext env;
@ -2048,10 +2132,15 @@ THREADED_TEST(GetSetProperty) {
THREADED_TEST(PropertyAttributes) {
v8::HandleScope scope;
LocalContext context;
// none
Local<String> prop = v8_str("none");
context->Global()->Set(prop, v8_num(7));
CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
// read-only
Local<String> prop = v8_str("read_only");
prop = v8_str("read_only");
context->Global()->Set(prop, v8_num(7), v8::ReadOnly);
CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
CHECK_EQ(v8::ReadOnly, context->Global()->GetPropertyAttributes(prop));
Script::Compile(v8_str("read_only = 9"))->Run();
CHECK_EQ(7, context->Global()->Get(prop)->Int32Value());
context->Global()->Set(prop, v8_num(10));
@ -2062,6 +2151,25 @@ THREADED_TEST(PropertyAttributes) {
CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
Script::Compile(v8_str("delete dont_delete"))->Run();
CHECK_EQ(13, context->Global()->Get(prop)->Int32Value());
CHECK_EQ(v8::DontDelete, context->Global()->GetPropertyAttributes(prop));
// dont-enum
prop = v8_str("dont_enum");
context->Global()->Set(prop, v8_num(28), v8::DontEnum);
CHECK_EQ(v8::DontEnum, context->Global()->GetPropertyAttributes(prop));
// absent
prop = v8_str("absent");
CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(prop));
Local<Value> fake_prop = v8_num(1);
CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(fake_prop));
// exception
TryCatch try_catch;
Local<Value> exception =
CompileRun("({ toString: function() { throw 'exception';} })");
CHECK_EQ(v8::None, context->Global()->GetPropertyAttributes(exception));
CHECK(try_catch.HasCaught());
String::AsciiValue exception_value(try_catch.Exception());
CHECK_EQ("exception", *exception_value);
try_catch.Reset();
}

2
deps/v8/test/cctest/test-ast.cc

@ -40,7 +40,7 @@ TEST(List) {
CHECK_EQ(0, list->length());
ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
AstNode* node = new EmptyStatement();
AstNode* node = new(ZONE) EmptyStatement();
list->Add(node);
CHECK_EQ(1, list->length());
CHECK_EQ(node, list->at(0));

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save