Browse Source

Upgrade V8 to 2.5.2

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
268bcbde7c
  1. 14
      deps/v8/ChangeLog
  2. 2
      deps/v8/SConstruct
  3. 11
      deps/v8/include/v8.h
  4. 86
      deps/v8/src/accessors.cc
  5. 60
      deps/v8/src/accessors.h
  6. 52
      deps/v8/src/api.cc
  7. 35
      deps/v8/src/api.h
  8. 55
      deps/v8/src/arm/codegen-arm.cc
  9. 7
      deps/v8/src/arm/cpu-arm.cc
  10. 7
      deps/v8/src/arm/ic-arm.cc
  11. 22
      deps/v8/src/arm/macro-assembler-arm.cc
  12. 2
      deps/v8/src/arm/regexp-macro-assembler-arm.cc
  13. 4
      deps/v8/src/arm/simulator-arm.cc
  14. 66
      deps/v8/src/arm/simulator-arm.h
  15. 324
      deps/v8/src/arm/stub-cache-arm.cc
  16. 10
      deps/v8/src/assembler.cc
  17. 3
      deps/v8/src/assembler.h
  18. 15
      deps/v8/src/bootstrapper.cc
  19. 193
      deps/v8/src/builtins.cc
  20. 57
      deps/v8/src/cached-powers.cc
  21. 30
      deps/v8/src/cached-powers.h
  22. 14
      deps/v8/src/code-stubs.cc
  23. 4
      deps/v8/src/code-stubs.h
  24. 16
      deps/v8/src/compilation-cache.cc
  25. 12
      deps/v8/src/debug.cc
  26. 61
      deps/v8/src/double.h
  27. 22
      deps/v8/src/execution.cc
  28. 2
      deps/v8/src/execution.h
  29. 30
      deps/v8/src/factory.cc
  30. 14
      deps/v8/src/fast-dtoa.cc
  31. 5
      deps/v8/src/global-handles.cc
  32. 5
      deps/v8/src/global-handles.h
  33. 19
      deps/v8/src/globals.h
  34. 10
      deps/v8/src/handles-inl.h
  35. 25
      deps/v8/src/handles.cc
  36. 45
      deps/v8/src/handles.h
  37. 76
      deps/v8/src/heap-inl.h
  38. 1089
      deps/v8/src/heap.cc
  39. 219
      deps/v8/src/heap.h
  40. 11
      deps/v8/src/ia32/assembler-ia32.cc
  41. 1
      deps/v8/src/ia32/assembler-ia32.h
  42. 72
      deps/v8/src/ia32/code-stubs-ia32.cc
  43. 214
      deps/v8/src/ia32/macro-assembler-ia32.cc
  44. 36
      deps/v8/src/ia32/macro-assembler-ia32.h
  45. 2
      deps/v8/src/ia32/regexp-macro-assembler-ia32.cc
  46. 21
      deps/v8/src/ia32/simulator-ia32.h
  47. 394
      deps/v8/src/ia32/stub-cache-ia32.cc
  48. 330
      deps/v8/src/ic.cc
  49. 32
      deps/v8/src/ic.h
  50. 43
      deps/v8/src/liveedit.cc
  51. 7
      deps/v8/src/liveedit.h
  52. 13
      deps/v8/src/log.cc
  53. 48
      deps/v8/src/mark-compact.cc
  54. 3
      deps/v8/src/mark-compact.h
  55. 4
      deps/v8/src/messages.cc
  56. 32
      deps/v8/src/objects-debug.cc
  57. 103
      deps/v8/src/objects-inl.h
  58. 1307
      deps/v8/src/objects.cc
  59. 515
      deps/v8/src/objects.h
  60. 4
      deps/v8/src/parser.cc
  61. 5
      deps/v8/src/platform-freebsd.cc
  62. 93
      deps/v8/src/platform-linux.cc
  63. 6
      deps/v8/src/platform-macos.cc
  64. 4
      deps/v8/src/profile-generator.cc
  65. 8
      deps/v8/src/property.h
  66. 1393
      deps/v8/src/runtime.cc
  67. 45
      deps/v8/src/runtime.h
  68. 35
      deps/v8/src/serialize.cc
  69. 8
      deps/v8/src/spaces-inl.h
  70. 30
      deps/v8/src/spaces.cc
  71. 50
      deps/v8/src/spaces.h
  72. 205
      deps/v8/src/strtod.cc
  73. 827
      deps/v8/src/stub-cache.cc
  74. 460
      deps/v8/src/stub-cache.h
  75. 63
      deps/v8/src/top.cc
  76. 26
      deps/v8/src/top.h
  77. 6
      deps/v8/src/v8.cc
  78. 2
      deps/v8/src/version.cc
  79. 8
      deps/v8/src/x64/assembler-x64.cc
  80. 36
      deps/v8/src/x64/code-stubs-x64.cc
  81. 199
      deps/v8/src/x64/macro-assembler-x64.cc
  82. 29
      deps/v8/src/x64/macro-assembler-x64.h
  83. 2
      deps/v8/src/x64/regexp-macro-assembler-x64.cc
  84. 23
      deps/v8/src/x64/simulator-x64.h
  85. 343
      deps/v8/src/x64/stub-cache-x64.cc
  86. 7
      deps/v8/test/cctest/test-alloc.cc
  87. 80
      deps/v8/test/cctest/test-api.cc
  88. 49
      deps/v8/test/cctest/test-assembler-arm.cc
  89. 62
      deps/v8/test/cctest/test-assembler-ia32.cc
  90. 22
      deps/v8/test/cctest/test-compiler.cc
  91. 7
      deps/v8/test/cctest/test-disasm-ia32.cc
  92. 159
      deps/v8/test/cctest/test-heap.cc
  93. 36
      deps/v8/test/cctest/test-log-stack-tracer.cc
  94. 4
      deps/v8/test/cctest/test-log.cc
  95. 95
      deps/v8/test/cctest/test-mark-compact.cc
  96. 14
      deps/v8/test/cctest/test-serialize.cc
  97. 18
      deps/v8/test/cctest/test-spaces.cc
  98. 2
      deps/v8/test/cctest/test-strings.cc
  99. 48
      deps/v8/test/cctest/test-strtod.cc
  100. 44
      deps/v8/test/mjsunit/bugs/bug-617.js

14
deps/v8/ChangeLog

@ -1,3 +1,17 @@
2010-10-27: Version 2.5.2
Improved sampler resolution on Linux.
Allowed forcing the use of a simulator from the build script
independently of the host architecture.
Fixed FreeBSD port (Issue 912).
Made windows-tick-processor respect D8_PATH.
Implemented --noinline-new flag fully on IA32, X64 and ARM platforms.
2010-10-20: Version 2.5.1 2010-10-20: Version 2.5.1
Fixed bug causing spurious out of memory exceptions Fixed bug causing spurious out of memory exceptions

2
deps/v8/SConstruct

@ -207,7 +207,6 @@ LIBRARY_FLAGS = {
'simulator:arm': { 'simulator:arm': {
'CCFLAGS': ['-m32'], 'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32'], 'LINKFLAGS': ['-m32'],
'CPPDEFINES': ['USE_SIMULATOR']
}, },
'arch:mips': { 'arch:mips': {
'CPPDEFINES': ['V8_TARGET_ARCH_MIPS'], 'CPPDEFINES': ['V8_TARGET_ARCH_MIPS'],
@ -219,7 +218,6 @@ LIBRARY_FLAGS = {
'simulator:mips': { 'simulator:mips': {
'CCFLAGS': ['-m32'], 'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32'], 'LINKFLAGS': ['-m32'],
'CPPDEFINES': ['USE_SIMULATOR']
}, },
'arch:x64': { 'arch:x64': {
'CPPDEFINES': ['V8_TARGET_ARCH_X64'], 'CPPDEFINES': ['V8_TARGET_ARCH_X64'],

11
deps/v8/include/v8.h

@ -467,16 +467,21 @@ class V8EXPORT HandleScope {
// typedef in the ImplementationUtilities class. // typedef in the ImplementationUtilities class.
class V8EXPORT Data { class V8EXPORT Data {
public: public:
int extensions;
internal::Object** next; internal::Object** next;
internal::Object** limit; internal::Object** limit;
int level;
inline void Initialize() { inline void Initialize() {
extensions = -1;
next = limit = NULL; next = limit = NULL;
level = 0;
} }
}; };
void Leave();
Data previous_;
internal::Object** prev_next_;
internal::Object** prev_limit_;
// Allow for the active closing of HandleScopes which allows to pass a handle // Allow for the active closing of HandleScopes which allows to pass a handle
// from the HandleScope being closed to the next top most HandleScope. // from the HandleScope being closed to the next top most HandleScope.

86
deps/v8/src/accessors.cc

@ -50,7 +50,7 @@ static C* FindInPrototypeChain(Object* obj, bool* found_it) {
// Entry point that never should be called. // Entry point that never should be called.
Object* Accessors::IllegalSetter(JSObject*, Object*, void*) { MaybeObject* Accessors::IllegalSetter(JSObject*, Object*, void*) {
UNREACHABLE(); UNREACHABLE();
return NULL; return NULL;
} }
@ -62,7 +62,7 @@ Object* Accessors::IllegalGetAccessor(Object* object, void*) {
} }
Object* Accessors::ReadOnlySetAccessor(JSObject*, Object* value, void*) { MaybeObject* Accessors::ReadOnlySetAccessor(JSObject*, Object* value, void*) {
// According to ECMA-262, section 8.6.2.2, page 28, setting // According to ECMA-262, section 8.6.2.2, page 28, setting
// read-only properties must be silently ignored. // read-only properties must be silently ignored.
return value; return value;
@ -74,7 +74,7 @@ Object* Accessors::ReadOnlySetAccessor(JSObject*, Object* value, void*) {
// //
Object* Accessors::ArrayGetLength(Object* object, void*) { MaybeObject* Accessors::ArrayGetLength(Object* object, void*) {
// Traverse the prototype chain until we reach an array. // Traverse the prototype chain until we reach an array.
bool found_it = false; bool found_it = false;
JSArray* holder = FindInPrototypeChain<JSArray>(object, &found_it); JSArray* holder = FindInPrototypeChain<JSArray>(object, &found_it);
@ -96,7 +96,7 @@ Object* Accessors::FlattenNumber(Object* value) {
} }
Object* Accessors::ArraySetLength(JSObject* object, Object* value, void*) { MaybeObject* Accessors::ArraySetLength(JSObject* object, Object* value, void*) {
value = FlattenNumber(value); value = FlattenNumber(value);
// Need to call methods that may trigger GC. // Need to call methods that may trigger GC.
@ -144,7 +144,7 @@ const AccessorDescriptor Accessors::ArrayLength = {
// //
Object* Accessors::StringGetLength(Object* object, void*) { MaybeObject* Accessors::StringGetLength(Object* object, void*) {
Object* value = object; Object* value = object;
if (object->IsJSValue()) value = JSValue::cast(object)->value(); if (object->IsJSValue()) value = JSValue::cast(object)->value();
if (value->IsString()) return Smi::FromInt(String::cast(value)->length()); if (value->IsString()) return Smi::FromInt(String::cast(value)->length());
@ -166,7 +166,7 @@ const AccessorDescriptor Accessors::StringLength = {
// //
Object* Accessors::ScriptGetSource(Object* object, void*) { MaybeObject* Accessors::ScriptGetSource(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
return Script::cast(script)->source(); return Script::cast(script)->source();
} }
@ -184,7 +184,7 @@ const AccessorDescriptor Accessors::ScriptSource = {
// //
Object* Accessors::ScriptGetName(Object* object, void*) { MaybeObject* Accessors::ScriptGetName(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
return Script::cast(script)->name(); return Script::cast(script)->name();
} }
@ -202,7 +202,7 @@ const AccessorDescriptor Accessors::ScriptName = {
// //
Object* Accessors::ScriptGetId(Object* object, void*) { MaybeObject* Accessors::ScriptGetId(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
return Script::cast(script)->id(); return Script::cast(script)->id();
} }
@ -220,7 +220,7 @@ const AccessorDescriptor Accessors::ScriptId = {
// //
Object* Accessors::ScriptGetLineOffset(Object* object, void*) { MaybeObject* Accessors::ScriptGetLineOffset(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
return Script::cast(script)->line_offset(); return Script::cast(script)->line_offset();
} }
@ -238,7 +238,7 @@ const AccessorDescriptor Accessors::ScriptLineOffset = {
// //
Object* Accessors::ScriptGetColumnOffset(Object* object, void*) { MaybeObject* Accessors::ScriptGetColumnOffset(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
return Script::cast(script)->column_offset(); return Script::cast(script)->column_offset();
} }
@ -256,7 +256,7 @@ const AccessorDescriptor Accessors::ScriptColumnOffset = {
// //
Object* Accessors::ScriptGetData(Object* object, void*) { MaybeObject* Accessors::ScriptGetData(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
return Script::cast(script)->data(); return Script::cast(script)->data();
} }
@ -274,7 +274,7 @@ const AccessorDescriptor Accessors::ScriptData = {
// //
Object* Accessors::ScriptGetType(Object* object, void*) { MaybeObject* Accessors::ScriptGetType(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
return Script::cast(script)->type(); return Script::cast(script)->type();
} }
@ -292,7 +292,7 @@ const AccessorDescriptor Accessors::ScriptType = {
// //
Object* Accessors::ScriptGetCompilationType(Object* object, void*) { MaybeObject* Accessors::ScriptGetCompilationType(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
return Script::cast(script)->compilation_type(); return Script::cast(script)->compilation_type();
} }
@ -310,7 +310,7 @@ const AccessorDescriptor Accessors::ScriptCompilationType = {
// //
Object* Accessors::ScriptGetLineEnds(Object* object, void*) { MaybeObject* Accessors::ScriptGetLineEnds(Object* object, void*) {
HandleScope scope; HandleScope scope;
Handle<Script> script(Script::cast(JSValue::cast(object)->value())); Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
InitScriptLineEnds(script); InitScriptLineEnds(script);
@ -334,7 +334,7 @@ const AccessorDescriptor Accessors::ScriptLineEnds = {
// //
Object* Accessors::ScriptGetContextData(Object* object, void*) { MaybeObject* Accessors::ScriptGetContextData(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
return Script::cast(script)->context_data(); return Script::cast(script)->context_data();
} }
@ -352,7 +352,7 @@ const AccessorDescriptor Accessors::ScriptContextData = {
// //
Object* Accessors::ScriptGetEvalFromScript(Object* object, void*) { MaybeObject* Accessors::ScriptGetEvalFromScript(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
if (!Script::cast(script)->eval_from_shared()->IsUndefined()) { if (!Script::cast(script)->eval_from_shared()->IsUndefined()) {
Handle<SharedFunctionInfo> eval_from_shared( Handle<SharedFunctionInfo> eval_from_shared(
@ -379,7 +379,7 @@ const AccessorDescriptor Accessors::ScriptEvalFromScript = {
// //
Object* Accessors::ScriptGetEvalFromScriptPosition(Object* object, void*) { MaybeObject* Accessors::ScriptGetEvalFromScriptPosition(Object* object, void*) {
HandleScope scope; HandleScope scope;
Handle<Script> script(Script::cast(JSValue::cast(object)->value())); Handle<Script> script(Script::cast(JSValue::cast(object)->value()));
@ -410,7 +410,7 @@ const AccessorDescriptor Accessors::ScriptEvalFromScriptPosition = {
// //
Object* Accessors::ScriptGetEvalFromFunctionName(Object* object, void*) { MaybeObject* Accessors::ScriptGetEvalFromFunctionName(Object* object, void*) {
Object* script = JSValue::cast(object)->value(); Object* script = JSValue::cast(object)->value();
Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast( Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(
Script::cast(script)->eval_from_shared())); Script::cast(script)->eval_from_shared()));
@ -437,35 +437,44 @@ const AccessorDescriptor Accessors::ScriptEvalFromFunctionName = {
// //
Object* Accessors::FunctionGetPrototype(Object* object, void*) { MaybeObject* Accessors::FunctionGetPrototype(Object* object, void*) {
bool found_it = false; bool found_it = false;
JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
if (!found_it) return Heap::undefined_value(); if (!found_it) return Heap::undefined_value();
if (!function->has_prototype()) { if (!function->has_prototype()) {
Object* prototype = Heap::AllocateFunctionPrototype(function); Object* prototype;
if (prototype->IsFailure()) return prototype; { MaybeObject* maybe_prototype = Heap::AllocateFunctionPrototype(function);
Object* result = function->SetPrototype(prototype); if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
if (result->IsFailure()) return result; }
Object* result;
{ MaybeObject* maybe_result = function->SetPrototype(prototype);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
} }
return function->prototype(); return function->prototype();
} }
Object* Accessors::FunctionSetPrototype(JSObject* object, MaybeObject* Accessors::FunctionSetPrototype(JSObject* object,
Object* value, Object* value,
void*) { void*) {
bool found_it = false; bool found_it = false;
JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
if (!found_it) return Heap::undefined_value(); if (!found_it) return Heap::undefined_value();
if (function->has_initial_map()) { if (function->has_initial_map()) {
// If the function has allocated the initial map // If the function has allocated the initial map
// replace it with a copy containing the new prototype. // replace it with a copy containing the new prototype.
Object* new_map = function->initial_map()->CopyDropTransitions(); Object* new_map;
if (new_map->IsFailure()) return new_map; { MaybeObject* maybe_new_map =
function->initial_map()->CopyDropTransitions();
if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
}
function->set_initial_map(Map::cast(new_map)); function->set_initial_map(Map::cast(new_map));
} }
Object* prototype = function->SetPrototype(value); Object* prototype;
if (prototype->IsFailure()) return prototype; { MaybeObject* maybe_prototype = function->SetPrototype(value);
if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype;
}
ASSERT(function->prototype() == value); ASSERT(function->prototype() == value);
return function; return function;
} }
@ -483,7 +492,7 @@ const AccessorDescriptor Accessors::FunctionPrototype = {
// //
Object* Accessors::FunctionGetLength(Object* object, void*) { MaybeObject* Accessors::FunctionGetLength(Object* object, void*) {
bool found_it = false; bool found_it = false;
JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
if (!found_it) return Smi::FromInt(0); if (!found_it) return Smi::FromInt(0);
@ -515,7 +524,7 @@ const AccessorDescriptor Accessors::FunctionLength = {
// //
Object* Accessors::FunctionGetName(Object* object, void*) { MaybeObject* Accessors::FunctionGetName(Object* object, void*) {
bool found_it = false; bool found_it = false;
JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
if (!found_it) return Heap::undefined_value(); if (!found_it) return Heap::undefined_value();
@ -535,7 +544,7 @@ const AccessorDescriptor Accessors::FunctionName = {
// //
Object* Accessors::FunctionGetArguments(Object* object, void*) { MaybeObject* Accessors::FunctionGetArguments(Object* object, void*) {
HandleScope scope; HandleScope scope;
bool found_it = false; bool found_it = false;
JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
@ -594,8 +603,9 @@ const AccessorDescriptor Accessors::FunctionArguments = {
// //
Object* Accessors::FunctionGetCaller(Object* object, void*) { MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
HandleScope scope; HandleScope scope;
AssertNoAllocation no_alloc;
bool found_it = false; bool found_it = false;
JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it);
if (!found_it) return Heap::undefined_value(); if (!found_it) return Heap::undefined_value();
@ -633,7 +643,7 @@ const AccessorDescriptor Accessors::FunctionCaller = {
// //
Object* Accessors::ObjectGetPrototype(Object* receiver, void*) { MaybeObject* Accessors::ObjectGetPrototype(Object* receiver, void*) {
Object* current = receiver->GetPrototype(); Object* current = receiver->GetPrototype();
while (current->IsJSObject() && while (current->IsJSObject() &&
JSObject::cast(current)->map()->is_hidden_prototype()) { JSObject::cast(current)->map()->is_hidden_prototype()) {
@ -643,9 +653,9 @@ Object* Accessors::ObjectGetPrototype(Object* receiver, void*) {
} }
Object* Accessors::ObjectSetPrototype(JSObject* receiver, MaybeObject* Accessors::ObjectSetPrototype(JSObject* receiver,
Object* value, Object* value,
void*) { void*) {
const bool skip_hidden_prototypes = true; const bool skip_hidden_prototypes = true;
// To be consistent with other Set functions, return the value. // To be consistent with other Set functions, return the value.
return receiver->SetPrototype(value, skip_hidden_prototypes); return receiver->SetPrototype(value, skip_hidden_prototypes);

60
deps/v8/src/accessors.h

@ -75,40 +75,44 @@ class Accessors : public AllStatic {
}; };
// Accessor functions called directly from the runtime system. // Accessor functions called directly from the runtime system.
MUST_USE_RESULT static Object* FunctionGetPrototype(Object* object, void*); MUST_USE_RESULT static MaybeObject* FunctionGetPrototype(Object* object,
MUST_USE_RESULT static Object* FunctionSetPrototype(JSObject* object, void*);
Object* value, MUST_USE_RESULT static MaybeObject* FunctionSetPrototype(JSObject* object,
void*); Object* value,
void*);
private: private:
// Accessor functions only used through the descriptor. // Accessor functions only used through the descriptor.
static Object* FunctionGetLength(Object* object, void*); static MaybeObject* FunctionGetLength(Object* object, void*);
static Object* FunctionGetName(Object* object, void*); static MaybeObject* FunctionGetName(Object* object, void*);
static Object* FunctionGetArguments(Object* object, void*); static MaybeObject* FunctionGetArguments(Object* object, void*);
static Object* FunctionGetCaller(Object* object, void*); static MaybeObject* FunctionGetCaller(Object* object, void*);
static Object* ArraySetLength(JSObject* object, Object* value, void*); MUST_USE_RESULT static MaybeObject* ArraySetLength(JSObject* object,
static Object* ArrayGetLength(Object* object, void*); Object* value, void*);
static Object* StringGetLength(Object* object, void*); static MaybeObject* ArrayGetLength(Object* object, void*);
static Object* ScriptGetName(Object* object, void*); static MaybeObject* StringGetLength(Object* object, void*);
static Object* ScriptGetId(Object* object, void*); static MaybeObject* ScriptGetName(Object* object, void*);
static Object* ScriptGetSource(Object* object, void*); static MaybeObject* ScriptGetId(Object* object, void*);
static Object* ScriptGetLineOffset(Object* object, void*); static MaybeObject* ScriptGetSource(Object* object, void*);
static Object* ScriptGetColumnOffset(Object* object, void*); static MaybeObject* ScriptGetLineOffset(Object* object, void*);
static Object* ScriptGetData(Object* object, void*); static MaybeObject* ScriptGetColumnOffset(Object* object, void*);
static Object* ScriptGetType(Object* object, void*); static MaybeObject* ScriptGetData(Object* object, void*);
static Object* ScriptGetCompilationType(Object* object, void*); static MaybeObject* ScriptGetType(Object* object, void*);
static Object* ScriptGetLineEnds(Object* object, void*); static MaybeObject* ScriptGetCompilationType(Object* object, void*);
static Object* ScriptGetContextData(Object* object, void*); static MaybeObject* ScriptGetLineEnds(Object* object, void*);
static Object* ScriptGetEvalFromScript(Object* object, void*); static MaybeObject* ScriptGetContextData(Object* object, void*);
static Object* ScriptGetEvalFromScriptPosition(Object* object, void*); static MaybeObject* ScriptGetEvalFromScript(Object* object, void*);
static Object* ScriptGetEvalFromFunctionName(Object* object, void*); static MaybeObject* ScriptGetEvalFromScriptPosition(Object* object, void*);
static Object* ObjectGetPrototype(Object* receiver, void*); static MaybeObject* ScriptGetEvalFromFunctionName(Object* object, void*);
static Object* ObjectSetPrototype(JSObject* receiver, Object* value, void*); static MaybeObject* ObjectGetPrototype(Object* receiver, void*);
static MaybeObject* ObjectSetPrototype(JSObject* receiver,
Object* value,
void*);
// Helper functions. // Helper functions.
static Object* FlattenNumber(Object* value); static Object* FlattenNumber(Object* value);
static Object* IllegalSetter(JSObject*, Object*, void*); static MaybeObject* IllegalSetter(JSObject*, Object*, void*);
static Object* IllegalGetAccessor(Object* object, void*); static Object* IllegalGetAccessor(Object* object, void*);
static Object* ReadOnlySetAccessor(JSObject*, Object* value, void*); static MaybeObject* ReadOnlySetAccessor(JSObject*, Object* value, void*);
}; };
} } // namespace v8::internal } } // namespace v8::internal

52
deps/v8/src/api.cc

@ -457,19 +457,37 @@ void V8::DisposeGlobal(i::Object** obj) {
// --- H a n d l e s --- // --- H a n d l e s ---
HandleScope::HandleScope() : is_closed_(false) { HandleScope::HandleScope()
: prev_next_(i::HandleScope::current_.next),
prev_limit_(i::HandleScope::current_.limit),
is_closed_(false) {
API_ENTRY_CHECK("HandleScope::HandleScope"); API_ENTRY_CHECK("HandleScope::HandleScope");
i::HandleScope::Enter(&previous_); i::HandleScope::current_.level++;
} }
HandleScope::~HandleScope() { HandleScope::~HandleScope() {
if (!is_closed_) { if (!is_closed_) {
i::HandleScope::Leave(&previous_); Leave();
} }
} }
void HandleScope::Leave() {
i::HandleScope::current_.level--;
ASSERT(i::HandleScope::current_.level >= 0);
i::HandleScope::current_.next = prev_next_;
if (i::HandleScope::current_.limit != prev_limit_) {
i::HandleScope::current_.limit = prev_limit_;
i::HandleScope::DeleteExtensions();
}
#ifdef DEBUG
i::HandleScope::ZapRange(prev_next_, prev_limit_);
#endif
}
int HandleScope::NumberOfHandles() { int HandleScope::NumberOfHandles() {
return i::HandleScope::NumberOfHandles(); return i::HandleScope::NumberOfHandles();
} }
@ -553,7 +571,7 @@ i::Object** v8::HandleScope::RawClose(i::Object** value) {
result = *value; result = *value;
} }
is_closed_ = true; is_closed_ = true;
i::HandleScope::Leave(&previous_); Leave();
if (value == NULL) { if (value == NULL) {
return NULL; return NULL;
@ -1489,7 +1507,8 @@ static i::Handle<i::Object> CallV8HeapFunction(const char* name,
i::Object** argv[], i::Object** argv[],
bool* has_pending_exception) { bool* has_pending_exception) {
i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name); i::Handle<i::String> fmt_str = i::Factory::LookupAsciiSymbol(name);
i::Object* object_fun = i::Top::builtins()->GetProperty(*fmt_str); i::Object* object_fun =
i::Top::builtins()->GetPropertyNoExceptionThrown(*fmt_str);
i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction> fun =
i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun)); i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
i::Handle<i::Object> value = i::Handle<i::Object> value =
@ -1605,7 +1624,8 @@ Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
ENTER_V8; ENTER_V8;
HandleScope scope; HandleScope scope;
i::Handle<i::JSArray> self = Utils::OpenHandle(this); i::Handle<i::JSArray> self = Utils::OpenHandle(this);
i::Handle<i::JSObject> obj(i::JSObject::cast(self->GetElement(index))); i::Object* raw_object = self->GetElementNoExceptionThrown(index);
i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object));
return scope.Close(Utils::StackFrameToLocal(obj)); return scope.Close(Utils::StackFrameToLocal(obj));
} }
@ -2521,10 +2541,12 @@ Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup); self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
if (lookup.IsProperty()) { if (lookup.IsProperty()) {
PropertyAttributes attributes; PropertyAttributes attributes;
i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, i::Object* property =
&lookup, self_obj->GetProperty(*self_obj,
*key_obj, &lookup,
&attributes)); *key_obj,
&attributes)->ToObjectUnchecked();
i::Handle<i::Object> result(property);
return Utils::ToLocal(result); return Utils::ToLocal(result);
} }
return Local<Value>(); // No real property was found in prototype chain. return Local<Value>(); // No real property was found in prototype chain.
@ -2540,10 +2562,12 @@ Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
self_obj->LookupRealNamedProperty(*key_obj, &lookup); self_obj->LookupRealNamedProperty(*key_obj, &lookup);
if (lookup.IsProperty()) { if (lookup.IsProperty()) {
PropertyAttributes attributes; PropertyAttributes attributes;
i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, i::Object* property =
&lookup, self_obj->GetProperty(*self_obj,
*key_obj, &lookup,
&attributes)); *key_obj,
&attributes)->ToObjectUnchecked();
i::Handle<i::Object> result(property);
return Utils::ToLocal(result); return Utils::ToLocal(result);
} }
return Local<Value>(); // No real property was found in prototype chain. return Local<Value>(); // No real property was found in prototype chain.

35
deps/v8/src/api.h

@ -353,7 +353,7 @@ class HandleScopeImplementer {
inline internal::Object** GetSpareOrNewBlock(); inline internal::Object** GetSpareOrNewBlock();
inline void DeleteExtensions(int extensions); inline void DeleteExtensions(internal::Object** prev_limit);
inline void IncrementCallDepth() {call_depth_++;} inline void IncrementCallDepth() {call_depth_++;}
inline void DecrementCallDepth() {call_depth_--;} inline void DecrementCallDepth() {call_depth_--;}
@ -465,25 +465,28 @@ internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() {
} }
void HandleScopeImplementer::DeleteExtensions(int extensions) { void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) {
if (spare_ != NULL) { while (!blocks_.is_empty()) {
DeleteArray(spare_); internal::Object** block_start = blocks_.last();
spare_ = NULL; internal::Object** block_limit = block_start + kHandleBlockSize;
}
for (int i = extensions; i > 1; --i) {
internal::Object** block = blocks_.RemoveLast();
#ifdef DEBUG #ifdef DEBUG
v8::ImplementationUtilities::ZapHandleRange(block, // NoHandleAllocation may make the prev_limit to point inside the block.
&block[kHandleBlockSize]); if (block_start <= prev_limit && prev_limit <= block_limit) break;
#else
if (prev_limit == block_limit) break;
#endif #endif
DeleteArray(block);
} blocks_.RemoveLast();
spare_ = blocks_.RemoveLast();
#ifdef DEBUG #ifdef DEBUG
v8::ImplementationUtilities::ZapHandleRange( v8::ImplementationUtilities::ZapHandleRange(block_start, block_limit);
spare_,
&spare_[kHandleBlockSize]);
#endif #endif
if (spare_ != NULL) {
DeleteArray(spare_);
}
spare_ = block_start;
}
ASSERT((blocks_.is_empty() && prev_limit == NULL) ||
(!blocks_.is_empty() && prev_limit != NULL));
} }
} } // namespace v8::internal } } // namespace v8::internal

55
deps/v8/src/arm/codegen-arm.cc

@ -1180,20 +1180,23 @@ void DeferredInlineSmiOperation::GenerateNonSmiInput() {
void DeferredInlineSmiOperation::GenerateAnswerOutOfRange() { void DeferredInlineSmiOperation::GenerateAnswerOutOfRange() {
// The input from a bitwise operation were Smis but the result cannot fit // The input from a bitwise operation were Smis but the result cannot fit
// into a Smi, so we store it into a heap number. tos_resgiter_ holds the // into a Smi, so we store it into a heap number. VirtualFrame::scratch0()
// result to be converted. // holds the untagged result to be converted. tos_register_ contains the
// input. See the calls to JumpToAnswerOutOfRange to see how we got here.
ASSERT(Token::IsBitOp(op_)); ASSERT(Token::IsBitOp(op_));
ASSERT(!reversed_); ASSERT(!reversed_);
Register untagged_result = VirtualFrame::scratch0();
if (FLAG_debug_code) { if (FLAG_debug_code) {
__ Abort("Should not fall through!"); __ Abort("Should not fall through!");
} }
__ bind(&answer_out_of_range_); __ bind(&answer_out_of_range_);
if (((value_ & 0x1f) == 0) && (op_ == Token::SHR)) { if (((value_ & 0x1f) == 0) && (op_ == Token::SHR)) {
// >>> 0 is a special case where the result is already tagged but wrong // >>> 0 is a special case where the untagged_result register is not set up
// because the Smi is negative. We untag it. // yet. We untag the input to get it.
__ mov(tos_register_, Operand(tos_register_, ASR, kSmiTagSize)); __ mov(untagged_result, Operand(tos_register_, ASR, kSmiTagSize));
} }
// This routine uses the registers from r2 to r6. At the moment they are // This routine uses the registers from r2 to r6. At the moment they are
@ -1201,12 +1204,12 @@ void DeferredInlineSmiOperation::GenerateAnswerOutOfRange() {
// SpillAll and MergeTo like DeferredInlineSmiOperation::Generate() above. // SpillAll and MergeTo like DeferredInlineSmiOperation::Generate() above.
// Allocate the result heap number. // Allocate the result heap number.
Register heap_number_map = r7; Register heap_number_map = VirtualFrame::scratch1();
Register heap_number = r4; Register heap_number = r4;
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
// If the allocation fails, fall back to the GenericBinaryOpStub. // If the allocation fails, fall back to the GenericBinaryOpStub.
__ AllocateHeapNumber(heap_number, r5, r6, heap_number_map, entry_label()); __ AllocateHeapNumber(heap_number, r5, r6, heap_number_map, entry_label());
WriteNonSmiAnswer(tos_register_, heap_number, r3); WriteNonSmiAnswer(untagged_result, heap_number, r3);
__ mov(tos_register_, Operand(heap_number)); __ mov(tos_register_, Operand(heap_number));
Exit(); Exit();
@ -1474,25 +1477,29 @@ void CodeGenerator::SmiOperation(Token::Value op,
switch (op) { switch (op) {
case Token::SHL: { case Token::SHL: {
if (shift_value != 0) { if (shift_value != 0) {
Register scratch = VirtualFrame::scratch0(); Register untagged_result = VirtualFrame::scratch0();
Register scratch = VirtualFrame::scratch1();
int adjusted_shift = shift_value - kSmiTagSize; int adjusted_shift = shift_value - kSmiTagSize;
ASSERT(adjusted_shift >= 0); ASSERT(adjusted_shift >= 0);
if (adjusted_shift != 0) { if (adjusted_shift != 0) {
__ mov(tos, Operand(tos, LSL, adjusted_shift)); __ mov(untagged_result, Operand(tos, LSL, adjusted_shift));
} else {
__ mov(untagged_result, Operand(tos));
} }
// Check that the *signed* result fits in a smi. // Check that the *signed* result fits in a smi.
__ add(scratch, tos, Operand(0x40000000), SetCC); __ add(scratch, untagged_result, Operand(0x40000000), SetCC);
deferred->JumpToAnswerOutOfRange(mi); deferred->JumpToAnswerOutOfRange(mi);
__ mov(tos, Operand(tos, LSL, kSmiTagSize)); __ mov(tos, Operand(untagged_result, LSL, kSmiTagSize));
} }
break; break;
} }
case Token::SHR: { case Token::SHR: {
if (shift_value != 0) { if (shift_value != 0) {
Register scratch = VirtualFrame::scratch0(); Register untagged_result = VirtualFrame::scratch0();
__ mov(scratch, Operand(tos, ASR, kSmiTagSize)); // Remove tag. // Remove tag.
__ mov(tos, Operand(scratch, LSR, shift_value)); __ mov(untagged_result, Operand(tos, ASR, kSmiTagSize));
__ mov(untagged_result, Operand(untagged_result, LSR, shift_value));
if (shift_value == 1) { if (shift_value == 1) {
// Check that the *unsigned* result fits in a smi. // Check that the *unsigned* result fits in a smi.
// Neither of the two high-order bits can be set: // Neither of the two high-order bits can be set:
@ -1501,17 +1508,10 @@ void CodeGenerator::SmiOperation(Token::Value op,
// tagging. // tagging.
// These two cases can only happen with shifts by 0 or 1 when // These two cases can only happen with shifts by 0 or 1 when
// handed a valid smi. // handed a valid smi.
__ tst(tos, Operand(0xc0000000)); __ tst(untagged_result, Operand(0xc0000000));
if (!CpuFeatures::IsSupported(VFP3)) {
// If the unsigned result does not fit in a Smi, we require an
// unsigned to double conversion. Without VFP V8 has to fall
// back to the runtime. The deferred code will expect tos
// to hold the original Smi to be shifted.
__ mov(tos, Operand(scratch, LSL, kSmiTagSize), LeaveCC, ne);
}
deferred->JumpToAnswerOutOfRange(ne); deferred->JumpToAnswerOutOfRange(ne);
} }
__ mov(tos, Operand(tos, LSL, kSmiTagSize)); __ mov(tos, Operand(untagged_result, LSL, kSmiTagSize));
} else { } else {
__ cmp(tos, Operand(0, RelocInfo::NONE)); __ cmp(tos, Operand(0, RelocInfo::NONE));
deferred->JumpToAnswerOutOfRange(mi); deferred->JumpToAnswerOutOfRange(mi);
@ -4733,6 +4733,7 @@ void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
runtime.set_entry_frame(frame_); runtime.set_entry_frame(frame_);
Register heap_number_map = r6; Register heap_number_map = r6;
Register new_heap_number = r5;
__ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
// Get the double value from the heap number into vfp register d0. // Get the double value from the heap number into vfp register d0.
@ -4742,8 +4743,12 @@ void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) {
// Calculate the square root of d0 and place result in a heap number object. // Calculate the square root of d0 and place result in a heap number object.
__ vsqrt(d0, d0); __ vsqrt(d0, d0);
__ AllocateHeapNumberWithValue( __ AllocateHeapNumberWithValue(new_heap_number,
tos, d0, scratch1, scratch2, heap_number_map, runtime.entry_label()); d0,
scratch1, scratch2,
heap_number_map,
runtime.entry_label());
__ mov(tos, Operand(new_heap_number));
done.Jump(); done.Jump();
runtime.Bind(); runtime.Bind();

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

@ -36,10 +36,7 @@
#include "cpu.h" #include "cpu.h"
#include "macro-assembler.h" #include "macro-assembler.h"
#include "simulator.h" // for cache flushing.
#ifndef __arm__
#include "simulator-arm.h" // for cache flushing.
#endif
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -50,7 +47,7 @@ void CPU::Setup() {
void CPU::FlushICache(void* start, size_t size) { void CPU::FlushICache(void* start, size_t size) {
#if !defined (__arm__) #if defined (USE_SIMULATOR)
// Not generating ARM instructions for C-code. This means that we are // Not generating ARM instructions for C-code. This means that we are
// building an ARM emulator based target. We should notify the simulator // building an ARM emulator based target. We should notify the simulator
// that the Icache was flushed. // that the Icache was flushed.

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

@ -1410,9 +1410,12 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
__ bind(&box_int); __ bind(&box_int);
// Allocate a HeapNumber for the result and perform int-to-double // Allocate a HeapNumber for the result and perform int-to-double
// conversion. Use r0 for result as key is not needed any more. // conversion. Don't touch r0 or r1 as they are needed if allocation
// fails.
__ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
__ AllocateHeapNumber(r0, r3, r4, r6, &slow); __ AllocateHeapNumber(r5, r3, r4, r6, &slow);
// Now we can use r0 for the result as key is not needed any more.
__ mov(r0, r5);
if (CpuFeatures::IsSupported(VFP3)) { if (CpuFeatures::IsSupported(VFP3)) {
CpuFeatures::Scope scope(VFP3); CpuFeatures::Scope scope(VFP3);

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

@ -908,6 +908,17 @@ void MacroAssembler::AllocateInNewSpace(int object_size,
Register scratch2, Register scratch2,
Label* gc_required, Label* gc_required,
AllocationFlags flags) { AllocationFlags flags) {
if (!FLAG_inline_new) {
if (FLAG_debug_code) {
// Trash the registers to simulate an allocation failure.
mov(result, Operand(0x7091));
mov(scratch1, Operand(0x7191));
mov(scratch2, Operand(0x7291));
}
jmp(gc_required);
return;
}
ASSERT(!result.is(scratch1)); ASSERT(!result.is(scratch1));
ASSERT(!scratch1.is(scratch2)); ASSERT(!scratch1.is(scratch2));
@ -959,6 +970,17 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
Register scratch2, Register scratch2,
Label* gc_required, Label* gc_required,
AllocationFlags flags) { AllocationFlags flags) {
if (!FLAG_inline_new) {
if (FLAG_debug_code) {
// Trash the registers to simulate an allocation failure.
mov(result, Operand(0x7091));
mov(scratch1, Operand(0x7191));
mov(scratch2, Operand(0x7291));
}
jmp(gc_required);
return;
}
ASSERT(!result.is(scratch1)); ASSERT(!result.is(scratch1));
ASSERT(!scratch1.is(scratch2)); ASSERT(!scratch1.is(scratch2));

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

@ -1030,7 +1030,7 @@ int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address,
ASSERT(*return_address <= ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size()); re_code->instruction_start() + re_code->instruction_size());
Object* result = Execution::HandleStackGuardInterrupt(); MaybeObject* result = Execution::HandleStackGuardInterrupt();
if (*code_handle != re_code) { // Return address no longer valid if (*code_handle != re_code) { // Return address no longer valid
int delta = *code_handle - re_code; int delta = *code_handle - re_code;

4
deps/v8/src/arm/simulator-arm.cc

@ -37,7 +37,7 @@
#include "arm/constants-arm.h" #include "arm/constants-arm.h"
#include "arm/simulator-arm.h" #include "arm/simulator-arm.h"
#if !defined(__arm__) || defined(USE_SIMULATOR) #if defined(USE_SIMULATOR)
// Only build the simulator if not compiling for real ARM hardware. // Only build the simulator if not compiling for real ARM hardware.
namespace assembler { namespace assembler {
@ -2840,6 +2840,6 @@ uintptr_t Simulator::PopAddress() {
} } // namespace assembler::arm } } // namespace assembler::arm
#endif // !__arm__ || USE_SIMULATOR #endif // USE_SIMULATOR
#endif // V8_TARGET_ARCH_ARM #endif // V8_TARGET_ARCH_ARM

66
deps/v8/src/arm/simulator-arm.h

@ -38,12 +38,24 @@
#include "allocation.h" #include "allocation.h"
#if defined(__arm__) && !defined(USE_SIMULATOR) #if !defined(USE_SIMULATOR)
// Running without a simulator on a native arm platform.
namespace v8 {
namespace internal {
// When running without a simulator we call the entry directly. // When running without a simulator we call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
(entry(p0, p1, p2, p3, p4)) (entry(p0, p1, p2, p3, p4))
// Call the generated regexp code directly. The entry function pointer should
// expect seven int/pointer sized arguments and return an int.
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
(entry(p0, p1, p2, p3, p4, p5, p6))
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
(reinterpret_cast<TryCatch*>(try_catch_address))
// The stack limit beyond which we will throw stack overflow errors in // The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on arm uses the C stack, we // generated code. Because generated code on arm uses the C stack, we
// just use the C stack limit. // just use the C stack limit.
@ -60,38 +72,14 @@ class SimulatorStack : public v8::internal::AllStatic {
static inline void UnregisterCTryCatch() { } static inline void UnregisterCTryCatch() { }
}; };
} } // namespace v8::internal
// Call the generated regexp code directly. The entry function pointer should #else // !defined(USE_SIMULATOR)
// expect eight int/pointer sized arguments and return an int. // Running with a simulator.
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
entry(p0, p1, p2, p3, p4, p5, p6)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
#else // !defined(__arm__) || defined(USE_SIMULATOR)
// When running with the simulator transition into simulated execution at this
// point.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
reinterpret_cast<Object*>( \
assembler::arm::Simulator::current()->Call(FUNCTION_ADDR(entry), 5, \
p0, p1, p2, p3, p4))
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
assembler::arm::Simulator::current()->Call( \
FUNCTION_ADDR(entry), 7, p0, p1, p2, p3, p4, p5, p6)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
try_catch_address == NULL ? \
NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
#include "constants-arm.h" #include "constants-arm.h"
#include "hashmap.h" #include "hashmap.h"
namespace assembler { namespace assembler {
namespace arm { namespace arm {
@ -334,6 +322,24 @@ class Simulator {
} } // namespace assembler::arm } } // namespace assembler::arm
namespace v8 {
namespace internal {
// When running with the simulator transition into simulated execution at this
// point.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
reinterpret_cast<Object*>(assembler::arm::Simulator::current()->Call( \
FUNCTION_ADDR(entry), 5, p0, p1, p2, p3, p4))
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
assembler::arm::Simulator::current()->Call( \
FUNCTION_ADDR(entry), 7, p0, p1, p2, p3, p4, p5, p6)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
try_catch_address == \
NULL ? NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
// The simulator has its own stack. Thus it has a different stack limit from // The simulator has its own stack. Thus it has a different stack limit from
// the C-based native code. Setting the c_limit to indicate a very small // the C-based native code. Setting the c_limit to indicate a very small
// stack cause stack overflow errors, since the simulator ignores the input. // stack cause stack overflow errors, since the simulator ignores the input.
@ -355,7 +361,7 @@ class SimulatorStack : public v8::internal::AllStatic {
} }
}; };
} } // namespace v8::internal
#endif // !defined(__arm__) || defined(USE_SIMULATOR) #endif // !defined(USE_SIMULATOR)
#endif // V8_ARM_SIMULATOR_ARM_H_ #endif // V8_ARM_SIMULATOR_ARM_H_

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

@ -834,13 +834,16 @@ class CallInterceptorCompiler BASE_EMBEDDED {
// Generate code to check that a global property cell is empty. Create // Generate code to check that a global property cell is empty. Create
// the property cell at compilation time if no cell exists for the // the property cell at compilation time if no cell exists for the
// property. // property.
static Object* GenerateCheckPropertyCell(MacroAssembler* masm, MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
GlobalObject* global, MacroAssembler* masm,
String* name, GlobalObject* global,
Register scratch, String* name,
Label* miss) { Register scratch,
Object* probe = global->EnsurePropertyCell(name); Label* miss) {
if (probe->IsFailure()) return probe; Object* probe;
{ MaybeObject* maybe_probe = global->EnsurePropertyCell(name);
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
}
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
ASSERT(cell->value()->IsTheHole()); ASSERT(cell->value()->IsTheHole());
__ mov(scratch, Operand(Handle<Object>(cell))); __ mov(scratch, Operand(Handle<Object>(cell)));
@ -894,12 +897,12 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
!current->IsJSGlobalObject() && !current->IsJSGlobalObject() &&
!current->IsJSGlobalProxy()) { !current->IsJSGlobalProxy()) {
if (!name->IsSymbol()) { if (!name->IsSymbol()) {
Object* lookup_result = Heap::LookupSymbol(name); MaybeObject* lookup_result = Heap::LookupSymbol(name);
if (lookup_result->IsFailure()) { if (lookup_result->IsFailure()) {
set_failure(Failure::cast(lookup_result)); set_failure(Failure::cast(lookup_result));
return reg; return reg;
} else { } else {
name = String::cast(lookup_result); name = String::cast(lookup_result->ToObjectUnchecked());
} }
} }
ASSERT(current->property_dictionary()->FindEntry(name) == ASSERT(current->property_dictionary()->FindEntry(name) ==
@ -974,11 +977,11 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
current = object; current = object;
while (current != holder) { while (current != holder) {
if (current->IsGlobalObject()) { if (current->IsGlobalObject()) {
Object* cell = GenerateCheckPropertyCell(masm(), MaybeObject* cell = GenerateCheckPropertyCell(masm(),
GlobalObject::cast(current), GlobalObject::cast(current),
name, name,
scratch1, scratch1,
miss); miss);
if (cell->IsFailure()) { if (cell->IsFailure()) {
set_failure(Failure::cast(cell)); set_failure(Failure::cast(cell));
return reg; return reg;
@ -1281,18 +1284,21 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
} }
Object* CallStubCompiler::GenerateMissBranch() { MaybeObject* CallStubCompiler::GenerateMissBranch() {
Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj =
StubCache::ComputeCallMiss(arguments().immediate(), kind_);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
__ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
return obj; return obj;
} }
Object* CallStubCompiler::CompileCallField(JSObject* object, MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
JSObject* holder, JSObject* holder,
int index, int index,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : name // -- r2 : name
// -- lr : return address // -- lr : return address
@ -1317,19 +1323,21 @@ Object* CallStubCompiler::CompileCallField(JSObject* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(FIELD, name); return GetCode(FIELD, name);
} }
Object* CallStubCompiler::CompileArrayPushCall(Object* object, MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : name // -- r2 : name
// -- lr : return address // -- lr : return address
@ -1361,19 +1369,21 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileArrayPopCall(Object* object, MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : name // -- r2 : name
// -- lr : return address // -- lr : return address
@ -1405,15 +1415,17 @@ Object* CallStubCompiler::CompileArrayPopCall(Object* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileStringCharCodeAtCall( MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
@ -1477,19 +1489,22 @@ Object* CallStubCompiler::CompileStringCharCodeAtCall(
__ Ret(); __ Ret();
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileStringCharAtCall(Object* object, MaybeObject* CallStubCompiler::CompileStringCharAtCall(
JSObject* holder, Object* object,
JSGlobalPropertyCell* cell, JSObject* holder,
JSFunction* function, JSGlobalPropertyCell* cell,
String* name) { JSFunction* function,
String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : function name // -- r2 : function name
// -- lr : return address // -- lr : return address
@ -1551,15 +1566,17 @@ Object* CallStubCompiler::CompileStringCharAtCall(Object* object,
__ Ret(); __ Ret();
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileStringFromCharCodeCall( MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
@ -1625,29 +1642,31 @@ Object* CallStubCompiler::CompileStringFromCharCodeCall(
__ bind(&miss); __ bind(&miss);
// r2: function name. // r2: function name.
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
} }
Object* CallStubCompiler::CompileMathFloorCall(Object* object, MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// TODO(872): implement this. // TODO(872): implement this.
return Heap::undefined_value(); return Heap::undefined_value();
} }
Object* CallStubCompiler::CompileMathAbsCall(Object* object, MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : function name // -- r2 : function name
// -- lr : return address // -- lr : return address
@ -1737,19 +1756,21 @@ Object* CallStubCompiler::CompileMathAbsCall(Object* object,
__ bind(&miss); __ bind(&miss);
// r2: function name. // r2: function name.
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
} }
Object* CallStubCompiler::CompileCallConstant(Object* object, MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder, JSObject* holder,
JSFunction* function, JSFunction* function,
String* name, String* name,
CheckType check) { CheckType check) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : name // -- r2 : name
// -- lr : return address // -- lr : return address
@ -1757,8 +1778,10 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
SharedFunctionInfo* function_info = function->shared(); SharedFunctionInfo* function_info = function->shared();
if (function_info->HasCustomCallGenerator()) { if (function_info->HasCustomCallGenerator()) {
const int id = function_info->custom_call_generator_id(); const int id = function_info->custom_call_generator_id();
Object* result = CompileCustomCall( MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, NULL, function, name); id, object, holder, NULL, function, name);
Object* result;
if (!maybe_result->ToObject(&result)) return maybe_result;
// undefined means bail out to regular compiler. // undefined means bail out to regular compiler.
if (!result->IsUndefined()) { if (!result->IsUndefined()) {
return result; return result;
@ -1891,17 +1914,19 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
} }
__ bind(&miss_in_smi_check); __ bind(&miss_in_smi_check);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : name // -- r2 : name
// -- lr : return address // -- lr : return address
@ -1941,19 +1966,21 @@ Object* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(INTERCEPTOR, name); return GetCode(INTERCEPTOR, name);
} }
Object* CallStubCompiler::CompileCallGlobal(JSObject* object, MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
GlobalObject* holder, GlobalObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : name // -- r2 : name
// -- lr : return address // -- lr : return address
@ -1962,8 +1989,10 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
SharedFunctionInfo* function_info = function->shared(); SharedFunctionInfo* function_info = function->shared();
if (function_info->HasCustomCallGenerator()) { if (function_info->HasCustomCallGenerator()) {
const int id = function_info->custom_call_generator_id(); const int id = function_info->custom_call_generator_id();
Object* result = CompileCustomCall( MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, cell, function, name); id, object, holder, cell, function, name);
Object* result;
if (!maybe_result->ToObject(&result)) return maybe_result;
// undefined means bail out to regular compiler. // undefined means bail out to regular compiler.
if (!result->IsUndefined()) return result; if (!result->IsUndefined()) return result;
} }
@ -2000,18 +2029,20 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
__ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3); __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(NORMAL, name); return GetCode(NORMAL, name);
} }
Object* StoreStubCompiler::CompileStoreField(JSObject* object, MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object,
int index, int index,
Map* transition, Map* transition,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : value // -- r0 : value
// -- r1 : receiver // -- r1 : receiver
@ -2035,9 +2066,9 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
} }
Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
AccessorInfo* callback, AccessorInfo* callback,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : value // -- r0 : value
// -- r1 : receiver // -- r1 : receiver
@ -2083,8 +2114,8 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
} }
Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : value // -- r0 : value
// -- r1 : receiver // -- r1 : receiver
@ -2128,9 +2159,9 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
} }
Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : value // -- r0 : value
// -- r1 : receiver // -- r1 : receiver
@ -2162,9 +2193,9 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
} }
Object* LoadStubCompiler::CompileLoadNonexistent(String* name, MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
JSObject* object, JSObject* object,
JSObject* last) { JSObject* last) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : receiver // -- r0 : receiver
// -- lr : return address // -- lr : return address
@ -2181,11 +2212,11 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name,
// If the last object in the prototype chain is a global object, // If the last object in the prototype chain is a global object,
// check that the global property cell is empty. // check that the global property cell is empty.
if (last->IsGlobalObject()) { if (last->IsGlobalObject()) {
Object* cell = GenerateCheckPropertyCell(masm(), MaybeObject* cell = GenerateCheckPropertyCell(masm(),
GlobalObject::cast(last), GlobalObject::cast(last),
name, name,
r1, r1,
&miss); &miss);
if (cell->IsFailure()) { if (cell->IsFailure()) {
miss.Unuse(); miss.Unuse();
return cell; return cell;
@ -2205,10 +2236,10 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name,
} }
Object* LoadStubCompiler::CompileLoadField(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* holder, JSObject* holder,
int index, int index,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : receiver // -- r0 : receiver
// -- r2 : name // -- r2 : name
@ -2225,10 +2256,10 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object,
} }
Object* LoadStubCompiler::CompileLoadCallback(String* name, MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
JSObject* object, JSObject* object,
JSObject* holder, JSObject* holder,
AccessorInfo* callback) { AccessorInfo* callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : receiver // -- r0 : receiver
// -- r2 : name // -- r2 : name
@ -2252,10 +2283,10 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name,
} }
Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
JSObject* holder, JSObject* holder,
Object* value, Object* value,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : receiver // -- r0 : receiver
// -- r2 : name // -- r2 : name
@ -2272,9 +2303,9 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
} }
Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : receiver // -- r0 : receiver
// -- r2 : name // -- r2 : name
@ -2302,11 +2333,11 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
} }
Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
GlobalObject* holder, GlobalObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
String* name, String* name,
bool is_dont_delete) { bool is_dont_delete) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : receiver // -- r0 : receiver
// -- r2 : name // -- r2 : name
@ -2349,10 +2380,10 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
} }
Object* KeyedLoadStubCompiler::CompileLoadField(String* name, MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder, JSObject* holder,
int index) { int index) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr : return address // -- lr : return address
// -- r0 : key // -- r0 : key
@ -2372,10 +2403,11 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
} }
Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
JSObject* receiver, String* name,
JSObject* holder, JSObject* receiver,
AccessorInfo* callback) { JSObject* holder,
AccessorInfo* callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr : return address // -- lr : return address
// -- r0 : key // -- r0 : key
@ -2402,10 +2434,10 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
} }
Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder, JSObject* holder,
Object* value) { Object* value) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr : return address // -- lr : return address
// -- r0 : key // -- r0 : key
@ -2426,9 +2458,9 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
} }
Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr : return address // -- lr : return address
// -- r0 : key // -- r0 : key
@ -2459,7 +2491,7 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
} }
Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr : return address // -- lr : return address
// -- r0 : key // -- r0 : key
@ -2479,7 +2511,7 @@ Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
} }
Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr : return address // -- lr : return address
// -- r0 : key // -- r0 : key
@ -2503,7 +2535,7 @@ Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
// TODO(1224671): implement the fast case. // TODO(1224671): implement the fast case.
Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr : return address // -- lr : return address
// -- r0 : key // -- r0 : key
@ -2515,10 +2547,10 @@ Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
} }
Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
int index, int index,
Map* transition, Map* transition,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : value // -- r0 : value
// -- r1 : key // -- r1 : key
@ -2553,7 +2585,7 @@ Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
} }
Object* ConstructStubCompiler::CompileConstructStub( MaybeObject* ConstructStubCompiler::CompileConstructStub(
SharedFunctionInfo* shared) { SharedFunctionInfo* shared) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : argc // -- r0 : argc

10
deps/v8/src/assembler.cc

@ -583,6 +583,12 @@ ExternalReference ExternalReference::fill_heap_number_with_random_function() {
} }
ExternalReference ExternalReference::delete_handle_scope_extensions() {
return ExternalReference(Redirect(FUNCTION_ADDR(
HandleScope::DeleteExtensions)));
}
ExternalReference ExternalReference::random_uint32_function() { ExternalReference ExternalReference::random_uint32_function() {
return ExternalReference(Redirect(FUNCTION_ADDR(V8::Random))); return ExternalReference(Redirect(FUNCTION_ADDR(V8::Random)));
} }
@ -653,8 +659,8 @@ ExternalReference ExternalReference::new_space_allocation_limit_address() {
} }
ExternalReference ExternalReference::handle_scope_extensions_address() { ExternalReference ExternalReference::handle_scope_level_address() {
return ExternalReference(HandleScope::current_extensions_address()); return ExternalReference(HandleScope::current_level_address());
} }

3
deps/v8/src/assembler.h

@ -482,6 +482,7 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference fill_heap_number_with_random_function(); static ExternalReference fill_heap_number_with_random_function();
static ExternalReference random_uint32_function(); static ExternalReference random_uint32_function();
static ExternalReference transcendental_cache_array_address(); static ExternalReference transcendental_cache_array_address();
static ExternalReference delete_handle_scope_extensions();
// Static data in the keyed lookup cache. // Static data in the keyed lookup cache.
static ExternalReference keyed_lookup_cache_keys(); static ExternalReference keyed_lookup_cache_keys();
@ -519,9 +520,9 @@ class ExternalReference BASE_EMBEDDED {
static ExternalReference double_fp_operation(Token::Value operation); static ExternalReference double_fp_operation(Token::Value operation);
static ExternalReference compare_doubles(); static ExternalReference compare_doubles();
static ExternalReference handle_scope_extensions_address();
static ExternalReference handle_scope_next_address(); static ExternalReference handle_scope_next_address();
static ExternalReference handle_scope_limit_address(); static ExternalReference handle_scope_limit_address();
static ExternalReference handle_scope_level_address();
static ExternalReference scheduled_exception_address(); static ExternalReference scheduled_exception_address();

15
deps/v8/src/bootstrapper.cc

@ -1009,11 +1009,10 @@ bool Genesis::CompileScriptCached(Vector<const char> name,
} }
#define INSTALL_NATIVE(Type, name, var) \ #define INSTALL_NATIVE(Type, name, var) \
Handle<String> var##_name = Factory::LookupAsciiSymbol(name); \ Handle<String> var##_name = Factory::LookupAsciiSymbol(name); \
global_context()->set_##var(Type::cast(global_context()-> \ global_context()->set_##var(Type::cast( \
builtins()-> \ global_context()->builtins()->GetPropertyNoExceptionThrown(*var##_name)));
GetProperty(*var##_name)));
void Genesis::InstallNativeFunctions() { void Genesis::InstallNativeFunctions() {
HandleScope scope; HandleScope scope;
@ -1369,7 +1368,8 @@ static void InstallCustomCallGenerator(Handle<JSObject> holder,
const char* function_name, const char* function_name,
int id) { int id) {
Handle<String> name = Factory::LookupAsciiSymbol(function_name); Handle<String> name = Factory::LookupAsciiSymbol(function_name);
Handle<JSFunction> function(JSFunction::cast(holder->GetProperty(*name))); Object* function_object = holder->GetProperty(*name)->ToObjectUnchecked();
Handle<JSFunction> function(JSFunction::cast(function_object));
function->shared()->set_function_data(Smi::FromInt(id)); function->shared()->set_function_data(Smi::FromInt(id));
} }
@ -1584,8 +1584,9 @@ bool Genesis::InstallJSBuiltins(Handle<JSBuiltinsObject> builtins) {
for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) { for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i); Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id)); Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id));
Object* function_object = builtins->GetPropertyNoExceptionThrown(*name);
Handle<JSFunction> function Handle<JSFunction> function
= Handle<JSFunction>(JSFunction::cast(builtins->GetProperty(*name))); = Handle<JSFunction>(JSFunction::cast(function_object));
builtins->set_javascript_builtin(id, *function); builtins->set_javascript_builtin(id, *function);
Handle<SharedFunctionInfo> shared Handle<SharedFunctionInfo> shared
= Handle<SharedFunctionInfo>(function->shared()); = Handle<SharedFunctionInfo>(function->shared());

193
deps/v8/src/builtins.cc

@ -121,18 +121,21 @@ BUILTIN_LIST_C(DEF_ARG_TYPE)
#ifdef DEBUG #ifdef DEBUG
#define BUILTIN(name) \ #define BUILTIN(name) \
static Object* Builtin_Impl_##name(name##ArgumentsType args); \ MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
static Object* Builtin_##name(name##ArgumentsType args) { \ name##ArgumentsType args); \
args.Verify(); \ MUST_USE_RESULT static MaybeObject* Builtin_##name( \
return Builtin_Impl_##name(args); \ name##ArgumentsType args) { \
} \ args.Verify(); \
static Object* Builtin_Impl_##name(name##ArgumentsType args) return Builtin_Impl_##name(args); \
} \
MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
name##ArgumentsType args)
#else // For release mode. #else // For release mode.
#define BUILTIN(name) \ #define BUILTIN(name) \
static Object* Builtin_##name(name##ArgumentsType args) static MaybeObject* Builtin_##name(name##ArgumentsType args)
#endif #endif
@ -189,8 +192,10 @@ BUILTIN(ArrayCodeGeneric) {
// Allocate the JS Array // Allocate the JS Array
JSFunction* constructor = JSFunction* constructor =
Top::context()->global_context()->array_function(); Top::context()->global_context()->array_function();
Object* obj = Heap::AllocateJSObject(constructor); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = Heap::AllocateJSObject(constructor);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
array = JSArray::cast(obj); array = JSArray::cast(obj);
} }
@ -204,15 +209,18 @@ BUILTIN(ArrayCodeGeneric) {
if (obj->IsSmi()) { if (obj->IsSmi()) {
int len = Smi::cast(obj)->value(); int len = Smi::cast(obj)->value();
if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
Object* obj = Heap::AllocateFixedArrayWithHoles(len); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
array->SetContent(FixedArray::cast(obj)); array->SetContent(FixedArray::cast(obj));
return array; return array;
} }
} }
// Take the argument as the length. // Take the argument as the length.
obj = array->Initialize(0); { MaybeObject* maybe_obj = array->Initialize(0);
if (obj->IsFailure()) return obj; if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
return array->SetElementsLength(args[1]); return array->SetElementsLength(args[1]);
} }
@ -224,8 +232,10 @@ BUILTIN(ArrayCodeGeneric) {
// Take the arguments as elements. // Take the arguments as elements.
int number_of_elements = args.length() - 1; int number_of_elements = args.length() - 1;
Smi* len = Smi::FromInt(number_of_elements); Smi* len = Smi::FromInt(number_of_elements);
Object* obj = Heap::AllocateFixedArrayWithHoles(len->value()); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len->value());
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
FixedArray* elms = FixedArray::cast(obj); FixedArray* elms = FixedArray::cast(obj);
@ -243,18 +253,22 @@ BUILTIN(ArrayCodeGeneric) {
} }
MUST_USE_RESULT static Object* AllocateJSArray() { MUST_USE_RESULT static MaybeObject* AllocateJSArray() {
JSFunction* array_function = JSFunction* array_function =
Top::context()->global_context()->array_function(); Top::context()->global_context()->array_function();
Object* result = Heap::AllocateJSObject(array_function); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result = Heap::AllocateJSObject(array_function);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
return result; return result;
} }
MUST_USE_RESULT static Object* AllocateEmptyJSArray() { MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray() {
Object* result = AllocateJSArray(); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result = AllocateJSArray();
if (!maybe_result->ToObject(&result)) return maybe_result;
}
JSArray* result_array = JSArray::cast(result); JSArray* result_array = JSArray::cast(result);
result_array->set_length(Smi::FromInt(0)); result_array->set_length(Smi::FromInt(0));
result_array->set_elements(Heap::empty_fixed_array()); result_array->set_elements(Heap::empty_fixed_array());
@ -360,7 +374,9 @@ static bool ArrayPrototypeHasNoElements(Context* global_context,
} }
static inline Object* EnsureJSArrayWithWritableFastElements(Object* receiver) { MUST_USE_RESULT
static inline MaybeObject* EnsureJSArrayWithWritableFastElements(
Object* receiver) {
if (!receiver->IsJSArray()) return NULL; if (!receiver->IsJSArray()) return NULL;
JSArray* array = JSArray::cast(receiver); JSArray* array = JSArray::cast(receiver);
HeapObject* elms = HeapObject::cast(array->elements()); HeapObject* elms = HeapObject::cast(array->elements());
@ -381,8 +397,9 @@ static inline bool IsJSArrayFastElementMovingAllowed(JSArray* receiver) {
} }
static Object* CallJsBuiltin(const char* name, MUST_USE_RESULT static MaybeObject* CallJsBuiltin(
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { const char* name,
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
HandleScope handleScope; HandleScope handleScope;
Handle<Object> js_builtin = Handle<Object> js_builtin =
@ -408,9 +425,12 @@ static Object* CallJsBuiltin(const char* name,
BUILTIN(ArrayPush) { BUILTIN(ArrayPush) {
Object* receiver = *args.receiver(); Object* receiver = *args.receiver();
Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); Object* elms_obj;
if (elms_obj == NULL) return CallJsBuiltin("ArrayPush", args); { MaybeObject* maybe_elms_obj =
if (elms_obj->IsFailure()) return elms_obj; EnsureJSArrayWithWritableFastElements(receiver);
if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayPush", args);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
FixedArray* elms = FixedArray::cast(elms_obj); FixedArray* elms = FixedArray::cast(elms_obj);
JSArray* array = JSArray::cast(receiver); JSArray* array = JSArray::cast(receiver);
@ -428,8 +448,10 @@ BUILTIN(ArrayPush) {
if (new_length > elms->length()) { if (new_length > elms->length()) {
// New backing storage is needed. // New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16; int capacity = new_length + (new_length >> 1) + 16;
Object* obj = Heap::AllocateUninitializedFixedArray(capacity); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
FixedArray* new_elms = FixedArray::cast(obj); FixedArray* new_elms = FixedArray::cast(obj);
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
@ -457,9 +479,12 @@ BUILTIN(ArrayPush) {
BUILTIN(ArrayPop) { BUILTIN(ArrayPop) {
Object* receiver = *args.receiver(); Object* receiver = *args.receiver();
Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); Object* elms_obj;
if (elms_obj == NULL) return CallJsBuiltin("ArrayPop", args); { MaybeObject* maybe_elms_obj =
if (elms_obj->IsFailure()) return elms_obj; EnsureJSArrayWithWritableFastElements(receiver);
if (maybe_elms_obj == NULL) return CallJsBuiltin("ArrayPop", args);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
FixedArray* elms = FixedArray::cast(elms_obj); FixedArray* elms = FixedArray::cast(elms_obj);
JSArray* array = JSArray::cast(receiver); JSArray* array = JSArray::cast(receiver);
@ -467,7 +492,7 @@ BUILTIN(ArrayPop) {
if (len == 0) return Heap::undefined_value(); if (len == 0) return Heap::undefined_value();
// Get top element // Get top element
Object* top = elms->get(len - 1); MaybeObject* top = elms->get(len - 1);
// Set the length. // Set the length.
array->set_length(Smi::FromInt(len - 1)); array->set_length(Smi::FromInt(len - 1));
@ -486,8 +511,11 @@ BUILTIN(ArrayPop) {
BUILTIN(ArrayShift) { BUILTIN(ArrayShift) {
Object* receiver = *args.receiver(); Object* receiver = *args.receiver();
Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); Object* elms_obj;
if (elms_obj->IsFailure()) return elms_obj; { MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
if (elms_obj == NULL || if (elms_obj == NULL ||
!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArrayShift", args); return CallJsBuiltin("ArrayShift", args);
@ -525,8 +553,11 @@ BUILTIN(ArrayShift) {
BUILTIN(ArrayUnshift) { BUILTIN(ArrayUnshift) {
Object* receiver = *args.receiver(); Object* receiver = *args.receiver();
Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); Object* elms_obj;
if (elms_obj->IsFailure()) return elms_obj; { MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
if (elms_obj == NULL || if (elms_obj == NULL ||
!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArrayUnshift", args); return CallJsBuiltin("ArrayUnshift", args);
@ -545,8 +576,10 @@ BUILTIN(ArrayUnshift) {
if (new_length > elms->length()) { if (new_length > elms->length()) {
// New backing storage is needed. // New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16; int capacity = new_length + (new_length >> 1) + 16;
Object* obj = Heap::AllocateUninitializedFixedArray(capacity); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
FixedArray* new_elms = FixedArray::cast(obj); FixedArray* new_elms = FixedArray::cast(obj);
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
@ -577,8 +610,11 @@ BUILTIN(ArrayUnshift) {
BUILTIN(ArraySlice) { BUILTIN(ArraySlice) {
Object* receiver = *args.receiver(); Object* receiver = *args.receiver();
Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); Object* elms_obj;
if (elms_obj->IsFailure()) return elms_obj; { MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
if (elms_obj == NULL || if (elms_obj == NULL ||
!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArraySlice", args); return CallJsBuiltin("ArraySlice", args);
@ -627,12 +663,16 @@ BUILTIN(ArraySlice) {
return AllocateEmptyJSArray(); return AllocateEmptyJSArray();
} }
Object* result = AllocateJSArray(); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result = AllocateJSArray();
if (!maybe_result->ToObject(&result)) return maybe_result;
}
JSArray* result_array = JSArray::cast(result); JSArray* result_array = JSArray::cast(result);
result = Heap::AllocateUninitializedFixedArray(result_len); { MaybeObject* maybe_result =
if (result->IsFailure()) return result; Heap::AllocateUninitializedFixedArray(result_len);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
FixedArray* result_elms = FixedArray::cast(result); FixedArray* result_elms = FixedArray::cast(result);
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
@ -649,8 +689,11 @@ BUILTIN(ArraySlice) {
BUILTIN(ArraySplice) { BUILTIN(ArraySplice) {
Object* receiver = *args.receiver(); Object* receiver = *args.receiver();
Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); Object* elms_obj;
if (elms_obj->IsFailure()) return elms_obj; { MaybeObject* maybe_elms_obj =
EnsureJSArrayWithWritableFastElements(receiver);
if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj;
}
if (elms_obj == NULL || if (elms_obj == NULL ||
!IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) {
return CallJsBuiltin("ArraySplice", args); return CallJsBuiltin("ArraySplice", args);
@ -695,17 +738,23 @@ BUILTIN(ArraySplice) {
JSArray* result_array = NULL; JSArray* result_array = NULL;
if (actual_delete_count == 0) { if (actual_delete_count == 0) {
Object* result = AllocateEmptyJSArray(); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result = AllocateEmptyJSArray();
if (!maybe_result->ToObject(&result)) return maybe_result;
}
result_array = JSArray::cast(result); result_array = JSArray::cast(result);
} else { } else {
// Allocate result array. // Allocate result array.
Object* result = AllocateJSArray(); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result = AllocateJSArray();
if (!maybe_result->ToObject(&result)) return maybe_result;
}
result_array = JSArray::cast(result); result_array = JSArray::cast(result);
result = Heap::AllocateUninitializedFixedArray(actual_delete_count); { MaybeObject* maybe_result =
if (result->IsFailure()) return result; Heap::AllocateUninitializedFixedArray(actual_delete_count);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
FixedArray* result_elms = FixedArray::cast(result); FixedArray* result_elms = FixedArray::cast(result);
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
@ -758,8 +807,11 @@ BUILTIN(ArraySplice) {
if (new_length > elms->length()) { if (new_length > elms->length()) {
// New backing storage is needed. // New backing storage is needed.
int capacity = new_length + (new_length >> 1) + 16; int capacity = new_length + (new_length >> 1) + 16;
Object* obj = Heap::AllocateUninitializedFixedArray(capacity); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj =
Heap::AllocateUninitializedFixedArray(capacity);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
FixedArray* new_elms = FixedArray::cast(obj); FixedArray* new_elms = FixedArray::cast(obj);
AssertNoAllocation no_gc; AssertNoAllocation no_gc;
@ -838,12 +890,16 @@ BUILTIN(ArrayConcat) {
} }
// Allocate result. // Allocate result.
Object* result = AllocateJSArray(); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result = AllocateJSArray();
if (!maybe_result->ToObject(&result)) return maybe_result;
}
JSArray* result_array = JSArray::cast(result); JSArray* result_array = JSArray::cast(result);
result = Heap::AllocateUninitializedFixedArray(result_len); { MaybeObject* maybe_result =
if (result->IsFailure()) return result; Heap::AllocateUninitializedFixedArray(result_len);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
FixedArray* result_elms = FixedArray::cast(result); FixedArray* result_elms = FixedArray::cast(result);
// Copy data. // Copy data.
@ -921,7 +977,7 @@ static inline Object* TypeCheck(int argc,
template <bool is_construct> template <bool is_construct>
static Object* HandleApiCallHelper( MUST_USE_RESULT static MaybeObject* HandleApiCallHelper(
BuiltinArguments<NEEDS_CALLED_FUNCTION> args) { BuiltinArguments<NEEDS_CALLED_FUNCTION> args) {
ASSERT(is_construct == CalledAsConstructor()); ASSERT(is_construct == CalledAsConstructor());
@ -1079,7 +1135,7 @@ BUILTIN(FastHandleApiCall) {
// Helper function to handle calls to non-function objects created through the // Helper function to handle calls to non-function objects created through the
// API. The object can be called as either a constructor (using new) or just as // API. The object can be called as either a constructor (using new) or just as
// a function (without new). // a function (without new).
static Object* HandleApiCallAsFunctionOrConstructor( MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor(
bool is_construct_call, bool is_construct_call,
BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
// Non-functions are never called as constructors. Even if this is an object // Non-functions are never called as constructors. Even if this is an object
@ -1481,14 +1537,16 @@ void Builtins::Setup(bool create_heap_objects) {
CodeDesc desc; CodeDesc desc;
masm.GetCode(&desc); masm.GetCode(&desc);
Code::Flags flags = functions[i].flags; Code::Flags flags = functions[i].flags;
Object* code; Object* code = 0;
{ {
// During startup it's OK to always allocate and defer GC to later. // During startup it's OK to always allocate and defer GC to later.
// This simplifies things because we don't need to retry. // This simplifies things because we don't need to retry.
AlwaysAllocateScope __scope__; AlwaysAllocateScope __scope__;
code = Heap::CreateCode(desc, flags, masm.CodeObject()); { MaybeObject* maybe_code =
if (code->IsFailure()) { Heap::CreateCode(desc, flags, masm.CodeObject());
v8::internal::V8::FatalProcessOutOfMemory("CreateCode"); if (!maybe_code->ToObject(&code)) {
v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
}
} }
} }
// Log the event and add the code to the builtins array. // Log the event and add the code to the builtins array.
@ -1536,5 +1594,4 @@ const char* Builtins::Lookup(byte* pc) {
return NULL; return NULL;
} }
} } // namespace v8::internal } } // namespace v8::internal

57
deps/v8/src/cached-powers.cc

@ -42,6 +42,11 @@ struct CachedPower {
}; };
static const CachedPower kCachedPowers[] = { static const CachedPower kCachedPowers[] = {
{V8_2PART_UINT64_C(0xfa8fd5a0, 081c0288), -1220, -348},
{V8_2PART_UINT64_C(0xbaaee17f, a23ebf76), -1193, -340},
{V8_2PART_UINT64_C(0x8b16fb20, 3055ac76), -1166, -332},
{V8_2PART_UINT64_C(0xcf42894a, 5dce35ea), -1140, -324},
{V8_2PART_UINT64_C(0x9a6bb0aa, 55653b2d), -1113, -316},
{V8_2PART_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308}, {V8_2PART_UINT64_C(0xe61acf03, 3d1a45df), -1087, -308},
{V8_2PART_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300}, {V8_2PART_UINT64_C(0xab70fe17, c79ac6ca), -1060, -300},
{V8_2PART_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292}, {V8_2PART_UINT64_C(0xff77b1fc, bebcdc4f), -1034, -292},
@ -129,24 +134,44 @@ static const CachedPower kCachedPowers[] = {
static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers); static const int kCachedPowersLength = ARRAY_SIZE(kCachedPowers);
static const int kCachedPowersOffset = -kCachedPowers[0].decimal_exponent; static const int kCachedPowersOffset = -kCachedPowers[0].decimal_exponent;
static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10) static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10)
static const int kCachedPowersDecimalDistance = const int PowersOfTenCache::kDecimalExponentDistance =
kCachedPowers[1].decimal_exponent - kCachedPowers[0].decimal_exponent; kCachedPowers[1].decimal_exponent - kCachedPowers[0].decimal_exponent;
const int PowersOfTenCache::kMinDecimalExponent =
kCachedPowers[0].decimal_exponent;
const int PowersOfTenCache::kMaxDecimalExponent =
kCachedPowers[kCachedPowersLength - 1].decimal_exponent;
void GetCachedPowerForBinaryExponentRange(int min_exponent, void PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
int max_exponent, int min_exponent,
DiyFp* power, int max_exponent,
int* decimal_exponent) { DiyFp* power,
int kQ = DiyFp::kSignificandSize; int* decimal_exponent) {
double k = ceiling((min_exponent + kQ - 1) * kD_1_LOG2_10); int kQ = DiyFp::kSignificandSize;
int foo = kCachedPowersOffset; double k = ceiling((min_exponent + kQ - 1) * kD_1_LOG2_10);
int index = int foo = kCachedPowersOffset;
(foo + static_cast<int>(k) - 1) / kCachedPowersDecimalDistance + 1; int index =
ASSERT(0 <= index && index < kCachedPowersLength); (foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1;
CachedPower cached_power = kCachedPowers[index]; ASSERT(0 <= index && index < kCachedPowersLength);
ASSERT(min_exponent <= cached_power.binary_exponent); CachedPower cached_power = kCachedPowers[index];
ASSERT(cached_power.binary_exponent <= max_exponent); ASSERT(min_exponent <= cached_power.binary_exponent);
*decimal_exponent = cached_power.decimal_exponent; ASSERT(cached_power.binary_exponent <= max_exponent);
*power = DiyFp(cached_power.significand, cached_power.binary_exponent); *decimal_exponent = cached_power.decimal_exponent;
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
}
void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent,
DiyFp* power,
int* found_exponent) {
ASSERT(kMinDecimalExponent <= requested_exponent);
ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance);
int index =
(requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance;
CachedPower cached_power = kCachedPowers[index];
*power = DiyFp(cached_power.significand, cached_power.binary_exponent);
*found_exponent = cached_power.decimal_exponent;
ASSERT(*found_exponent <= requested_exponent);
ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance);
} }
} } // namespace v8::internal } } // namespace v8::internal

30
deps/v8/src/cached-powers.h

@ -33,10 +33,32 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
void GetCachedPowerForBinaryExponentRange(int min_exponent, class PowersOfTenCache {
int max_exponent, public:
DiyFp* power,
int* decimal_exponent); // Not all powers of ten are cached. The decimal exponent of two neighboring
// cached numbers will differ by kDecimalExponentDistance.
static const int kDecimalExponentDistance;
static const int kMinDecimalExponent;
static const int kMaxDecimalExponent;
// Returns a cached power-of-ten with a binary exponent in the range
// [min_exponent; max_exponent] (boundaries included).
static void GetCachedPowerForBinaryExponentRange(int min_exponent,
int max_exponent,
DiyFp* power,
int* decimal_exponent);
// Returns a cached power of ten x ~= 10^k such that
// k <= decimal_exponent < k + kCachedPowersDecimalDistance.
// The given decimal_exponent must satisfy
// kMinDecimalExponent <= requested_exponent, and
// requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance.
static void GetCachedPowerForDecimalExponent(int requested_exponent,
DiyFp* power,
int* found_exponent);
};
} } // namespace v8::internal } } // namespace v8::internal

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

@ -123,7 +123,7 @@ Handle<Code> CodeStub::GetCode() {
} }
Object* CodeStub::TryGetCode() { MaybeObject* CodeStub::TryGetCode() {
Code* code; Code* code;
if (!FindCodeInCache(&code)) { if (!FindCodeInCache(&code)) {
// Generate the new code. // Generate the new code.
@ -139,8 +139,11 @@ Object* CodeStub::TryGetCode() {
static_cast<Code::Kind>(GetCodeKind()), static_cast<Code::Kind>(GetCodeKind()),
InLoop(), InLoop(),
GetICState()); GetICState());
Object* new_object = Heap::CreateCode(desc, flags, masm.CodeObject()); Object* new_object;
if (new_object->IsFailure()) return new_object; { MaybeObject* maybe_new_object =
Heap::CreateCode(desc, flags, masm.CodeObject());
if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
}
code = Code::cast(new_object); code = Code::cast(new_object);
RecordCodeGeneration(code, &masm); RecordCodeGeneration(code, &masm);
@ -148,8 +151,9 @@ Object* CodeStub::TryGetCode() {
SetCustomCache(code); SetCustomCache(code);
} else { } else {
// Try to update the code cache but do not fail if unable. // Try to update the code cache but do not fail if unable.
new_object = Heap::code_stubs()->AtNumberPut(GetKey(), code); MaybeObject* maybe_new_object =
if (!new_object->IsFailure()) { Heap::code_stubs()->AtNumberPut(GetKey(), code);
if (maybe_new_object->ToObject(&new_object)) {
Heap::public_set_code_stubs(NumberDictionary::cast(new_object)); Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
} }
} }

4
deps/v8/src/code-stubs.h

@ -106,7 +106,7 @@ class CodeStub BASE_EMBEDDED {
// Retrieve the code for the stub if already generated. Do not // Retrieve the code for the stub if already generated. Do not
// generate the code if not already generated and instead return a // generate the code if not already generated and instead return a
// retry after GC Failure object. // retry after GC Failure object.
Object* TryGetCode(); MUST_USE_RESULT MaybeObject* TryGetCode();
static Major MajorKeyFromKey(uint32_t key) { static Major MajorKeyFromKey(uint32_t key) {
return static_cast<Major>(MajorKeyBits::decode(key)); return static_cast<Major>(MajorKeyBits::decode(key));
@ -536,7 +536,7 @@ class ApiGetterEntryStub : public CodeStub {
virtual void SetCustomCache(Code* value); virtual void SetCustomCache(Code* value);
static const int kStackSpace = 5; static const int kStackSpace = 5;
static const int kArgc = 4; static const int kArgc = 2;
private: private:
Handle<AccessorInfo> info() { return info_; } Handle<AccessorInfo> info() { return info_; }
ApiFunction* fun() { return fun_; } ApiFunction* fun() { return fun_; }

16
deps/v8/src/compilation-cache.cc

@ -110,7 +110,7 @@ class CompilationCacheScript : public CompilationSubCache {
void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info); void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info);
private: private:
MUST_USE_RESULT Object* TryTablePut( MUST_USE_RESULT MaybeObject* TryTablePut(
Handle<String> source, Handle<SharedFunctionInfo> function_info); Handle<String> source, Handle<SharedFunctionInfo> function_info);
// Note: Returns a new hash table if operation results in expansion. // Note: Returns a new hash table if operation results in expansion.
@ -140,7 +140,7 @@ class CompilationCacheEval: public CompilationSubCache {
Handle<SharedFunctionInfo> function_info); Handle<SharedFunctionInfo> function_info);
private: private:
MUST_USE_RESULT Object* TryTablePut( MUST_USE_RESULT MaybeObject* TryTablePut(
Handle<String> source, Handle<String> source,
Handle<Context> context, Handle<Context> context,
Handle<SharedFunctionInfo> function_info); Handle<SharedFunctionInfo> function_info);
@ -168,9 +168,9 @@ class CompilationCacheRegExp: public CompilationSubCache {
JSRegExp::Flags flags, JSRegExp::Flags flags,
Handle<FixedArray> data); Handle<FixedArray> data);
private: private:
MUST_USE_RESULT Object* TryTablePut(Handle<String> source, MUST_USE_RESULT MaybeObject* TryTablePut(Handle<String> source,
JSRegExp::Flags flags, JSRegExp::Flags flags,
Handle<FixedArray> data); Handle<FixedArray> data);
// Note: Returns a new hash table if operation results in expansion. // Note: Returns a new hash table if operation results in expansion.
Handle<CompilationCacheTable> TablePut(Handle<String> source, Handle<CompilationCacheTable> TablePut(Handle<String> source,
@ -333,7 +333,7 @@ Handle<SharedFunctionInfo> CompilationCacheScript::Lookup(Handle<String> source,
} }
Object* CompilationCacheScript::TryTablePut( MaybeObject* CompilationCacheScript::TryTablePut(
Handle<String> source, Handle<String> source,
Handle<SharedFunctionInfo> function_info) { Handle<SharedFunctionInfo> function_info) {
Handle<CompilationCacheTable> table = GetFirstTable(); Handle<CompilationCacheTable> table = GetFirstTable();
@ -386,7 +386,7 @@ Handle<SharedFunctionInfo> CompilationCacheEval::Lookup(
} }
Object* CompilationCacheEval::TryTablePut( MaybeObject* CompilationCacheEval::TryTablePut(
Handle<String> source, Handle<String> source,
Handle<Context> context, Handle<Context> context,
Handle<SharedFunctionInfo> function_info) { Handle<SharedFunctionInfo> function_info) {
@ -442,7 +442,7 @@ Handle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source,
} }
Object* CompilationCacheRegExp::TryTablePut( MaybeObject* CompilationCacheRegExp::TryTablePut(
Handle<String> source, Handle<String> source,
JSRegExp::Flags flags, JSRegExp::Flags flags,
Handle<FixedArray> data) { Handle<FixedArray> data) {

12
deps/v8/src/debug.cc

@ -1038,7 +1038,7 @@ bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
Factory::LookupAsciiSymbol("IsBreakPointTriggered"); Factory::LookupAsciiSymbol("IsBreakPointTriggered");
Handle<JSFunction> check_break_point = Handle<JSFunction> check_break_point =
Handle<JSFunction>(JSFunction::cast( Handle<JSFunction>(JSFunction::cast(
debug_context()->global()->GetProperty( debug_context()->global()->GetPropertyNoExceptionThrown(
*is_break_point_triggered_symbol))); *is_break_point_triggered_symbol)));
// Get the break id as an object. // Get the break id as an object.
@ -1847,7 +1847,8 @@ void Debug::ClearMirrorCache() {
// Clear the mirror cache. // Clear the mirror cache.
Handle<String> function_name = Handle<String> function_name =
Factory::LookupSymbol(CStrVector("ClearMirrorCache")); Factory::LookupSymbol(CStrVector("ClearMirrorCache"));
Handle<Object> fun(Top::global()->GetProperty(*function_name)); Handle<Object> fun(Top::global()->GetPropertyNoExceptionThrown(
*function_name));
ASSERT(fun->IsJSFunction()); ASSERT(fun->IsJSFunction());
bool caught_exception; bool caught_exception;
Handle<Object> js_object = Execution::TryCall( Handle<Object> js_object = Execution::TryCall(
@ -1954,7 +1955,8 @@ Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
// Create the execution state object. // Create the execution state object.
Handle<String> constructor_str = Factory::LookupSymbol(constructor_name); Handle<String> constructor_str = Factory::LookupSymbol(constructor_name);
Handle<Object> constructor(Top::global()->GetProperty(*constructor_str)); Handle<Object> constructor(Top::global()->GetPropertyNoExceptionThrown(
*constructor_str));
ASSERT(constructor->IsJSFunction()); ASSERT(constructor->IsJSFunction());
if (!constructor->IsJSFunction()) { if (!constructor->IsJSFunction()) {
*caught_exception = true; *caught_exception = true;
@ -2181,8 +2183,8 @@ void Debugger::OnAfterCompile(Handle<Script> script,
Handle<String> update_script_break_points_symbol = Handle<String> update_script_break_points_symbol =
Factory::LookupAsciiSymbol("UpdateScriptBreakPoints"); Factory::LookupAsciiSymbol("UpdateScriptBreakPoints");
Handle<Object> update_script_break_points = Handle<Object> update_script_break_points =
Handle<Object>(Debug::debug_context()->global()->GetProperty( Handle<Object>(Debug::debug_context()->global()->
*update_script_break_points_symbol)); GetPropertyNoExceptionThrown(*update_script_break_points_symbol));
if (!update_script_break_points->IsJSFunction()) { if (!update_script_break_points->IsJSFunction()) {
return; return;
} }

61
deps/v8/src/double.h

@ -45,10 +45,14 @@ class Double {
static const uint64_t kSignificandMask = static const uint64_t kSignificandMask =
V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF); V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF);
static const uint64_t kHiddenBit = V8_2PART_UINT64_C(0x00100000, 00000000); static const uint64_t kHiddenBit = V8_2PART_UINT64_C(0x00100000, 00000000);
static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit.
static const int kSignificandSize = 53;
Double() : d64_(0) {} Double() : d64_(0) {}
explicit Double(double d) : d64_(double_to_uint64(d)) {} explicit Double(double d) : d64_(double_to_uint64(d)) {}
explicit Double(uint64_t d64) : d64_(d64) {} explicit Double(uint64_t d64) : d64_(d64) {}
explicit Double(DiyFp diy_fp)
: d64_(DiyFpToUint64(diy_fp)) {}
DiyFp AsDiyFp() const { DiyFp AsDiyFp() const {
ASSERT(!IsSpecial()); ASSERT(!IsSpecial());
@ -67,9 +71,9 @@ class Double {
f <<= 1; f <<= 1;
e--; e--;
} }
// Do the final shifts in one go. Don't forget the hidden bit (the '-1'). // Do the final shifts in one go.
f <<= DiyFp::kSignificandSize - kSignificandSize - 1; f <<= DiyFp::kSignificandSize - kSignificandSize;
e -= DiyFp::kSignificandSize - kSignificandSize - 1; e -= DiyFp::kSignificandSize - kSignificandSize;
return DiyFp(f, e); return DiyFp(f, e);
} }
@ -82,7 +86,8 @@ class Double {
if (IsDenormal()) return kDenormalExponent; if (IsDenormal()) return kDenormalExponent;
uint64_t d64 = AsUint64(); uint64_t d64 = AsUint64();
int biased_e = static_cast<int>((d64 & kExponentMask) >> kSignificandSize); int biased_e =
static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize);
return biased_e - kExponentBias; return biased_e - kExponentBias;
} }
@ -156,12 +161,54 @@ class Double {
double value() const { return uint64_to_double(d64_); } double value() const { return uint64_to_double(d64_); }
// Returns the significand size for a given order of magnitude.
// If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude.
// This function returns the number of significant binary digits v will have
// once its encoded into a double. In almost all cases this is equal to
// kSignificandSize. The only exception are denormals. They start with leading
// zeroes and their effective significand-size is hence smaller.
static int SignificandSizeForOrderOfMagnitude(int order) {
if (order >= (kDenormalExponent + kSignificandSize)) {
return kSignificandSize;
}
if (order <= kDenormalExponent) return 0;
return order - kDenormalExponent;
}
private: private:
static const int kSignificandSize = 52; // Excludes the hidden bit. static const int kExponentBias = 0x3FF + kPhysicalSignificandSize;
static const int kExponentBias = 0x3FF + kSignificandSize;
static const int kDenormalExponent = -kExponentBias + 1; static const int kDenormalExponent = -kExponentBias + 1;
static const int kMaxExponent = 0x7FF - kExponentBias;
static const uint64_t kInfinity = V8_2PART_UINT64_C(0x7FF00000, 00000000);
uint64_t d64_; const uint64_t d64_;
static uint64_t DiyFpToUint64(DiyFp diy_fp) {
uint64_t significand = diy_fp.f();
int exponent = diy_fp.e();
while (significand > kHiddenBit + kSignificandMask) {
significand >>= 1;
exponent++;
}
if (exponent >= kMaxExponent) {
return kInfinity;
}
if (exponent < kDenormalExponent) {
return 0;
}
while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) {
significand <<= 1;
exponent--;
}
uint64_t biased_exponent;
if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) {
biased_exponent = 0;
} else {
biased_exponent = static_cast<uint64_t>(exponent + kExponentBias);
}
return (significand & kSignificandMask) |
(biased_exponent << kPhysicalSignificandSize);
}
}; };
} } // namespace v8::internal } } // namespace v8::internal

22
deps/v8/src/execution.cc

@ -50,7 +50,7 @@ static Handle<Object> Invoke(bool construct,
VMState state(JS); VMState state(JS);
// Placeholder for return value. // Placeholder for return value.
Object* value = reinterpret_cast<Object*>(kZapValue); MaybeObject* value = reinterpret_cast<Object*>(kZapValue);
typedef Object* (*JSEntryFunction)( typedef Object* (*JSEntryFunction)(
byte* entry, byte* entry,
@ -109,7 +109,7 @@ static Handle<Object> Invoke(bool construct,
Top::clear_pending_message(); Top::clear_pending_message();
} }
return Handle<Object>(value); return Handle<Object>(value->ToObjectUnchecked());
} }
@ -172,7 +172,17 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
// and Safari so we allow it too. // and Safari so we allow it too.
if (object->IsJSRegExp()) { if (object->IsJSRegExp()) {
Handle<String> exec = Factory::exec_symbol(); Handle<String> exec = Factory::exec_symbol();
return Handle<Object>(object->GetProperty(*exec)); // TODO(lrn): Bug 617. We should use the default function here, not the
// one on the RegExp object.
Object* exec_function;
{ MaybeObject* maybe_exec_function = object->GetProperty(*exec);
// This can lose an exception, but the alternative is to put a failure
// object in a handle, which is not GC safe.
if (!maybe_exec_function->ToObject(&exec_function)) {
return Factory::undefined_value();
}
}
return Handle<Object>(exec_function);
} }
// Objects created through the API can have an instance-call handler // Objects created through the API can have an instance-call handler
@ -517,8 +527,8 @@ Handle<JSFunction> Execution::InstantiateFunction(
Handle<FunctionTemplateInfo> data, bool* exc) { Handle<FunctionTemplateInfo> data, bool* exc) {
// Fast case: see if the function has already been instantiated // Fast case: see if the function has already been instantiated
int serial_number = Smi::cast(data->serial_number())->value(); int serial_number = Smi::cast(data->serial_number())->value();
Object* elm = Object* elm = Top::global_context()->function_cache()->
Top::global_context()->function_cache()->GetElement(serial_number); GetElementNoExceptionThrown(serial_number);
if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm)); if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
// The function has not yet been instantiated in this context; do it. // The function has not yet been instantiated in this context; do it.
Object** args[1] = { Handle<Object>::cast(data).location() }; Object** args[1] = { Handle<Object>::cast(data).location() };
@ -671,7 +681,7 @@ void Execution::ProcessDebugMesssages(bool debug_command_only) {
#endif #endif
Object* Execution::HandleStackGuardInterrupt() { MaybeObject* Execution::HandleStackGuardInterrupt() {
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) { if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
DebugBreakHelper(); DebugBreakHelper();

2
deps/v8/src/execution.h

@ -132,7 +132,7 @@ class Execution : public AllStatic {
// If the stack guard is triggered, but it is not an actual // If the stack guard is triggered, but it is not an actual
// stack overflow, then handle the interruption accordingly. // stack overflow, then handle the interruption accordingly.
static Object* HandleStackGuardInterrupt(); MUST_USE_RESULT static MaybeObject* HandleStackGuardInterrupt();
// Get a function delegate (or undefined) for the given non-function // Get a function delegate (or undefined) for the given non-function
// object. Used for support calling objects as functions. // object. Used for support calling objects as functions.

30
deps/v8/src/factory.cc

@ -431,7 +431,8 @@ Handle<Object> Factory::NewError(const char* maker,
const char* type, const char* type,
Handle<JSArray> args) { Handle<JSArray> args) {
Handle<String> make_str = Factory::LookupAsciiSymbol(maker); Handle<String> make_str = Factory::LookupAsciiSymbol(maker);
Handle<Object> fun_obj(Top::builtins()->GetProperty(*make_str)); Handle<Object> fun_obj(Top::builtins()->GetPropertyNoExceptionThrown(
*make_str));
// If the builtins haven't been properly configured yet this error // If the builtins haven't been properly configured yet this error
// constructor may not have been defined. Bail out. // constructor may not have been defined. Bail out.
if (!fun_obj->IsJSFunction()) if (!fun_obj->IsJSFunction())
@ -464,7 +465,7 @@ Handle<Object> Factory::NewError(const char* constructor,
Handle<JSFunction> fun = Handle<JSFunction> fun =
Handle<JSFunction>( Handle<JSFunction>(
JSFunction::cast( JSFunction::cast(
Top::builtins()->GetProperty(*constr))); Top::builtins()->GetPropertyNoExceptionThrown(*constr)));
Object** argv[1] = { Handle<Object>::cast(message).location() }; Object** argv[1] = { Handle<Object>::cast(message).location() };
// Invoke the JavaScript factory method. If an exception is thrown while // Invoke the JavaScript factory method. If an exception is thrown while
@ -567,12 +568,13 @@ Handle<Code> Factory::CopyCode(Handle<Code> code, Vector<byte> reloc_info) {
} }
static inline Object* DoCopyInsert(DescriptorArray* array, MUST_USE_RESULT static inline MaybeObject* DoCopyInsert(
String* key, DescriptorArray* array,
Object* value, String* key,
PropertyAttributes attributes) { Object* value,
PropertyAttributes attributes) {
CallbacksDescriptor desc(key, value, attributes); CallbacksDescriptor desc(key, value, attributes);
Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS); MaybeObject* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS);
return obj; return obj;
} }
@ -921,11 +923,15 @@ Handle<MapCache> Factory::NewMapCache(int at_least_space_for) {
} }
static Object* UpdateMapCacheWith(Context* context, MUST_USE_RESULT static MaybeObject* UpdateMapCacheWith(Context* context,
FixedArray* keys, FixedArray* keys,
Map* map) { Map* map) {
Object* result = MapCache::cast(context->map_cache())->Put(keys, map); Object* result;
if (!result->IsFailure()) context->set_map_cache(MapCache::cast(result)); { MaybeObject* maybe_result =
MapCache::cast(context->map_cache())->Put(keys, map);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
context->set_map_cache(MapCache::cast(result));
return result; return result;
} }

14
deps/v8/src/fast-dtoa.cc

@ -613,9 +613,10 @@ static bool Grisu3(double v,
kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize); kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
int ten_mk_maximal_binary_exponent = int ten_mk_maximal_binary_exponent =
kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize); kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent, PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
ten_mk_maximal_binary_exponent, ten_mk_minimal_binary_exponent,
&ten_mk, &mk); ten_mk_maximal_binary_exponent,
&ten_mk, &mk);
ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) && DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() + (kMaximalTargetExponent >= w.e() + ten_mk.e() +
@ -671,9 +672,10 @@ static bool Grisu3Counted(double v,
kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize); kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize);
int ten_mk_maximal_binary_exponent = int ten_mk_maximal_binary_exponent =
kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize); kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize);
GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent, PowersOfTenCache::GetCachedPowerForBinaryExponentRange(
ten_mk_maximal_binary_exponent, ten_mk_minimal_binary_exponent,
&ten_mk, &mk); ten_mk_maximal_binary_exponent,
&ten_mk, &mk);
ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() +
DiyFp::kSignificandSize) && DiyFp::kSignificandSize) &&
(kMaximalTargetExponent >= w.e() + ten_mk.e() + (kMaximalTargetExponent >= w.e() + ten_mk.e() +

5
deps/v8/src/global-handles.cc

@ -372,14 +372,13 @@ void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) {
int post_gc_processing_count = 0; int post_gc_processing_count = 0;
bool GlobalHandles::PostGarbageCollectionProcessing() { void GlobalHandles::PostGarbageCollectionProcessing() {
// Process weak global handle callbacks. This must be done after the // Process weak global handle callbacks. This must be done after the
// GC is completely done, because the callbacks may invoke arbitrary // GC is completely done, because the callbacks may invoke arbitrary
// API functions. // API functions.
// At the same time deallocate all DESTROYED nodes. // At the same time deallocate all DESTROYED nodes.
ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); ASSERT(Heap::gc_state() == Heap::NOT_IN_GC);
const int initial_post_gc_processing_count = ++post_gc_processing_count; const int initial_post_gc_processing_count = ++post_gc_processing_count;
bool weak_callback_invoked = false;
Node** p = &head_; Node** p = &head_;
while (*p != NULL) { while (*p != NULL) {
if ((*p)->PostGarbageCollectionProcessing()) { if ((*p)->PostGarbageCollectionProcessing()) {
@ -390,7 +389,6 @@ bool GlobalHandles::PostGarbageCollectionProcessing() {
// restart the processing). // restart the processing).
break; break;
} }
weak_callback_invoked = true;
} }
if ((*p)->state_ == Node::DESTROYED) { if ((*p)->state_ == Node::DESTROYED) {
// Delete the link. // Delete the link.
@ -409,7 +407,6 @@ bool GlobalHandles::PostGarbageCollectionProcessing() {
if (first_deallocated()) { if (first_deallocated()) {
first_deallocated()->set_next(head()); first_deallocated()->set_next(head());
} }
return weak_callback_invoked;
} }

5
deps/v8/src/global-handles.h

@ -95,9 +95,8 @@ class GlobalHandles : public AllStatic {
// Tells whether global handle is weak. // Tells whether global handle is weak.
static bool IsWeak(Object** location); static bool IsWeak(Object** location);
// Process pending weak handles. Returns true if any weak handle // Process pending weak handles.
// callback has been invoked. static void PostGarbageCollectionProcessing();
static bool PostGarbageCollectionProcessing();
// Iterates over all strong handles. // Iterates over all strong handles.
static void IterateStrongRoots(ObjectVisitor* v); static void IterateStrongRoots(ObjectVisitor* v);

19
deps/v8/src/globals.h

@ -93,6 +93,18 @@ namespace internal {
#error Target architecture mips is only supported on mips and ia32 host #error Target architecture mips is only supported on mips and ia32 host
#endif #endif
// Determine whether we are running in a simulated environment.
// Setting USE_SIMULATOR explicitly from the build script will force
// the use of a simulated environment.
#if !defined(USE_SIMULATOR)
#if (defined(V8_TARGET_ARCH_ARM) && !defined(V8_HOST_ARCH_ARM))
#define USE_SIMULATOR 1
#endif
#if (defined(V8_TARGET_ARCH_MIPS) && !defined(V8_HOST_ARCH_MIPS))
#define USE_SIMULATOR 1
#endif
#endif
// Define unaligned read for the target architectures supporting it. // Define unaligned read for the target architectures supporting it.
#if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_IA32) #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_IA32)
#define V8_TARGET_CAN_READ_UNALIGNED 1 #define V8_TARGET_CAN_READ_UNALIGNED 1
@ -189,9 +201,11 @@ const int kIntptrSize = sizeof(intptr_t); // NOLINT
#if V8_HOST_ARCH_64_BIT #if V8_HOST_ARCH_64_BIT
const int kPointerSizeLog2 = 3; const int kPointerSizeLog2 = 3;
const intptr_t kIntptrSignBit = V8_INT64_C(0x8000000000000000); const intptr_t kIntptrSignBit = V8_INT64_C(0x8000000000000000);
const uintptr_t kUintptrAllBitsSet = V8_UINT64_C(0xFFFFFFFFFFFFFFFF);
#else #else
const int kPointerSizeLog2 = 2; const int kPointerSizeLog2 = 2;
const intptr_t kIntptrSignBit = 0x80000000; const intptr_t kIntptrSignBit = 0x80000000;
const uintptr_t kUintptrAllBitsSet = 0xFFFFFFFFu;
#endif #endif
// Mask for the sign bit in a smi. // Mask for the sign bit in a smi.
@ -324,6 +338,7 @@ class MarkCompactCollector;
class NewSpace; class NewSpace;
class NodeVisitor; class NodeVisitor;
class Object; class Object;
class MaybeObject;
class OldSpace; class OldSpace;
class Property; class Property;
class Proxy; class Proxy;
@ -542,8 +557,8 @@ union IeeeDoubleBigEndianArchType {
// AccessorCallback // AccessorCallback
struct AccessorDescriptor { struct AccessorDescriptor {
Object* (*getter)(Object* object, void* data); MaybeObject* (*getter)(Object* object, void* data);
Object* (*setter)(JSObject* object, Object* value, void* data); MaybeObject* (*setter)(JSObject* object, Object* value, void* data);
void* data; void* data;
}; };

10
deps/v8/src/handles-inl.h

@ -55,18 +55,22 @@ inline T* Handle<T>::operator*() const {
inline NoHandleAllocation::NoHandleAllocation() { inline NoHandleAllocation::NoHandleAllocation() {
v8::ImplementationUtilities::HandleScopeData* current = v8::ImplementationUtilities::HandleScopeData* current =
v8::ImplementationUtilities::CurrentHandleScope(); v8::ImplementationUtilities::CurrentHandleScope();
extensions_ = current->extensions;
// Shrink the current handle scope to make it impossible to do // Shrink the current handle scope to make it impossible to do
// handle allocations without an explicit handle scope. // handle allocations without an explicit handle scope.
current->limit = current->next; current->limit = current->next;
current->extensions = -1;
level_ = current->level;
current->level = 0;
} }
inline NoHandleAllocation::~NoHandleAllocation() { inline NoHandleAllocation::~NoHandleAllocation() {
// Restore state in current handle scope to re-enable handle // Restore state in current handle scope to re-enable handle
// allocations. // allocations.
v8::ImplementationUtilities::CurrentHandleScope()->extensions = extensions_; v8::ImplementationUtilities::HandleScopeData* current =
v8::ImplementationUtilities::CurrentHandleScope();
ASSERT_EQ(0, current->level);
current->level = level_;
} }
#endif #endif

25
deps/v8/src/handles.cc

@ -44,7 +44,7 @@ namespace internal {
v8::ImplementationUtilities::HandleScopeData HandleScope::current_ = v8::ImplementationUtilities::HandleScopeData HandleScope::current_ =
{ -1, NULL, NULL }; { NULL, NULL, 0 };
int HandleScope::NumberOfHandles() { int HandleScope::NumberOfHandles() {
@ -61,7 +61,7 @@ Object** HandleScope::Extend() {
ASSERT(result == current_.limit); ASSERT(result == current_.limit);
// Make sure there's at least one scope on the stack and that the // Make sure there's at least one scope on the stack and that the
// top of the scope stack isn't a barrier. // top of the scope stack isn't a barrier.
if (current_.extensions < 0) { if (current_.level == 0) {
Utils::ReportApiFailure("v8::HandleScope::CreateHandle()", Utils::ReportApiFailure("v8::HandleScope::CreateHandle()",
"Cannot create a handle without a HandleScope"); "Cannot create a handle without a HandleScope");
return NULL; return NULL;
@ -73,6 +73,7 @@ Object** HandleScope::Extend() {
Object** limit = &impl->blocks()->last()[kHandleBlockSize]; Object** limit = &impl->blocks()->last()[kHandleBlockSize];
if (current_.limit != limit) { if (current_.limit != limit) {
current_.limit = limit; current_.limit = limit;
ASSERT(limit - current_.next < kHandleBlockSize);
} }
} }
@ -84,7 +85,6 @@ Object** HandleScope::Extend() {
// Add the extension to the global list of blocks, but count the // Add the extension to the global list of blocks, but count the
// extension as part of the current scope. // extension as part of the current scope.
impl->blocks()->Add(result); impl->blocks()->Add(result);
current_.extensions++;
current_.limit = &result[kHandleBlockSize]; current_.limit = &result[kHandleBlockSize];
} }
@ -93,21 +93,20 @@ Object** HandleScope::Extend() {
void HandleScope::DeleteExtensions() { void HandleScope::DeleteExtensions() {
ASSERT(current_.extensions != 0); HandleScopeImplementer::instance()->DeleteExtensions(current_.limit);
HandleScopeImplementer::instance()->DeleteExtensions(current_.extensions);
} }
void HandleScope::ZapRange(Object** start, Object** end) { void HandleScope::ZapRange(Object** start, Object** end) {
if (start == NULL) return; ASSERT(end - start <= kHandleBlockSize);
for (Object** p = start; p < end; p++) { for (Object** p = start; p != end; p++) {
*reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue; *reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue;
} }
} }
Address HandleScope::current_extensions_address() { Address HandleScope::current_level_address() {
return reinterpret_cast<Address>(&current_.extensions); return reinterpret_cast<Address>(&current_.level);
} }
@ -210,6 +209,14 @@ void TransformToFastProperties(Handle<JSObject> object,
} }
void NumberDictionarySet(Handle<NumberDictionary> dictionary,
uint32_t index,
Handle<Object> value,
PropertyDetails details) {
CALL_HEAP_FUNCTION_VOID(dictionary->Set(index, *value, details));
}
void FlattenString(Handle<String> string) { void FlattenString(Handle<String> string) {
CALL_HEAP_FUNCTION_VOID(string->TryFlatten()); CALL_HEAP_FUNCTION_VOID(string->TryFlatten());
} }

45
deps/v8/src/handles.h

@ -107,12 +107,20 @@ class Handle {
// for which the handle scope has been deleted is undefined. // for which the handle scope has been deleted is undefined.
class HandleScope { class HandleScope {
public: public:
HandleScope() : previous_(current_) { HandleScope() : prev_next_(current_.next), prev_limit_(current_.limit) {
current_.extensions = 0; current_.level++;
} }
~HandleScope() { ~HandleScope() {
Leave(&previous_); current_.next = prev_next_;
current_.level--;
if (current_.limit != prev_limit_) {
current_.limit = prev_limit_;
DeleteExtensions();
}
#ifdef DEBUG
ZapRange(prev_next_, prev_limit_);
#endif
} }
// Counts the number of allocated handles. // Counts the number of allocated handles.
@ -136,9 +144,9 @@ class HandleScope {
// Deallocates any extensions used by the current scope. // Deallocates any extensions used by the current scope.
static void DeleteExtensions(); static void DeleteExtensions();
static Address current_extensions_address();
static Address current_next_address(); static Address current_next_address();
static Address current_limit_address(); static Address current_limit_address();
static Address current_level_address();
private: private:
// Prevent heap allocation or illegal handle scopes. // Prevent heap allocation or illegal handle scopes.
@ -148,27 +156,8 @@ class HandleScope {
void operator delete(void* size_t); void operator delete(void* size_t);
static v8::ImplementationUtilities::HandleScopeData current_; static v8::ImplementationUtilities::HandleScopeData current_;
const v8::ImplementationUtilities::HandleScopeData previous_; Object** const prev_next_;
Object** const prev_limit_;
// Pushes a fresh handle scope to be used when allocating new handles.
static void Enter(
v8::ImplementationUtilities::HandleScopeData* previous) {
*previous = current_;
current_.extensions = 0;
}
// Re-establishes the previous scope state. Should be called only
// once, and only for the current scope.
static void Leave(
const v8::ImplementationUtilities::HandleScopeData* previous) {
if (current_.extensions > 0) {
DeleteExtensions();
}
current_ = *previous;
#ifdef DEBUG
ZapRange(current_.next, current_.limit);
#endif
}
// Extend the handle scope making room for more handles. // Extend the handle scope making room for more handles.
static internal::Object** Extend(); static internal::Object** Extend();
@ -193,6 +182,10 @@ void NormalizeProperties(Handle<JSObject> object,
void NormalizeElements(Handle<JSObject> object); void NormalizeElements(Handle<JSObject> object);
void TransformToFastProperties(Handle<JSObject> object, void TransformToFastProperties(Handle<JSObject> object,
int unused_property_fields); int unused_property_fields);
void NumberDictionarySet(Handle<NumberDictionary> dictionary,
uint32_t index,
Handle<Object> value,
PropertyDetails details);
// Flattens a string. // Flattens a string.
void FlattenString(Handle<String> str); void FlattenString(Handle<String> str);
@ -358,7 +351,7 @@ class NoHandleAllocation BASE_EMBEDDED {
inline NoHandleAllocation(); inline NoHandleAllocation();
inline ~NoHandleAllocation(); inline ~NoHandleAllocation();
private: private:
int extensions_; int level_;
#endif #endif
}; };

76
deps/v8/src/heap-inl.h

@ -35,38 +35,28 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
void Heap::UpdateOldSpaceLimits() {
intptr_t old_gen_size = PromotedSpaceSize();
old_gen_promotion_limit_ =
old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3);
old_gen_allocation_limit_ =
old_gen_size + Max(kMinimumAllocationLimit, old_gen_size / 2);
old_gen_exhausted_ = false;
}
int Heap::MaxObjectSizeInPagedSpace() { int Heap::MaxObjectSizeInPagedSpace() {
return Page::kMaxHeapObjectSize; return Page::kMaxHeapObjectSize;
} }
Object* Heap::AllocateSymbol(Vector<const char> str, MaybeObject* Heap::AllocateSymbol(Vector<const char> str,
int chars, int chars,
uint32_t hash_field) { uint32_t hash_field) {
unibrow::Utf8InputBuffer<> buffer(str.start(), unibrow::Utf8InputBuffer<> buffer(str.start(),
static_cast<unsigned>(str.length())); static_cast<unsigned>(str.length()));
return AllocateInternalSymbol(&buffer, chars, hash_field); return AllocateInternalSymbol(&buffer, chars, hash_field);
} }
Object* Heap::CopyFixedArray(FixedArray* src) { MaybeObject* Heap::CopyFixedArray(FixedArray* src) {
return CopyFixedArrayWithMap(src, src->map()); return CopyFixedArrayWithMap(src, src->map());
} }
Object* Heap::AllocateRaw(int size_in_bytes, MaybeObject* Heap::AllocateRaw(int size_in_bytes,
AllocationSpace space, AllocationSpace space,
AllocationSpace retry_space) { AllocationSpace retry_space) {
ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC);
ASSERT(space != NEW_SPACE || ASSERT(space != NEW_SPACE ||
retry_space == OLD_POINTER_SPACE || retry_space == OLD_POINTER_SPACE ||
@ -81,7 +71,7 @@ Object* Heap::AllocateRaw(int size_in_bytes,
Counters::objs_since_last_full.Increment(); Counters::objs_since_last_full.Increment();
Counters::objs_since_last_young.Increment(); Counters::objs_since_last_young.Increment();
#endif #endif
Object* result; MaybeObject* result;
if (NEW_SPACE == space) { if (NEW_SPACE == space) {
result = new_space_.AllocateRaw(size_in_bytes); result = new_space_.AllocateRaw(size_in_bytes);
if (always_allocate() && result->IsFailure()) { if (always_allocate() && result->IsFailure()) {
@ -110,14 +100,14 @@ Object* Heap::AllocateRaw(int size_in_bytes,
} }
Object* Heap::NumberFromInt32(int32_t value) { MaybeObject* Heap::NumberFromInt32(int32_t value) {
if (Smi::IsValid(value)) return Smi::FromInt(value); if (Smi::IsValid(value)) return Smi::FromInt(value);
// Bypass NumberFromDouble to avoid various redundant checks. // Bypass NumberFromDouble to avoid various redundant checks.
return AllocateHeapNumber(FastI2D(value)); return AllocateHeapNumber(FastI2D(value));
} }
Object* Heap::NumberFromUint32(uint32_t value) { MaybeObject* Heap::NumberFromUint32(uint32_t value) {
if ((int32_t)value >= 0 && Smi::IsValid((int32_t)value)) { if ((int32_t)value >= 0 && Smi::IsValid((int32_t)value)) {
return Smi::FromInt((int32_t)value); return Smi::FromInt((int32_t)value);
} }
@ -144,12 +134,12 @@ void Heap::FinalizeExternalString(String* string) {
} }
Object* Heap::AllocateRawMap() { MaybeObject* Heap::AllocateRawMap() {
#ifdef DEBUG #ifdef DEBUG
Counters::objs_since_last_full.Increment(); Counters::objs_since_last_full.Increment();
Counters::objs_since_last_young.Increment(); Counters::objs_since_last_young.Increment();
#endif #endif
Object* result = map_space_->AllocateRaw(Map::kSize); MaybeObject* result = map_space_->AllocateRaw(Map::kSize);
if (result->IsFailure()) old_gen_exhausted_ = true; if (result->IsFailure()) old_gen_exhausted_ = true;
#ifdef DEBUG #ifdef DEBUG
if (!result->IsFailure()) { if (!result->IsFailure()) {
@ -162,12 +152,12 @@ Object* Heap::AllocateRawMap() {
} }
Object* Heap::AllocateRawCell() { MaybeObject* Heap::AllocateRawCell() {
#ifdef DEBUG #ifdef DEBUG
Counters::objs_since_last_full.Increment(); Counters::objs_since_last_full.Increment();
Counters::objs_since_last_young.Increment(); Counters::objs_since_last_young.Increment();
#endif #endif
Object* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize); MaybeObject* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize);
if (result->IsFailure()) old_gen_exhausted_ = true; if (result->IsFailure()) old_gen_exhausted_ = true;
return result; return result;
} }
@ -340,14 +330,14 @@ void Heap::ScavengeObject(HeapObject** p, HeapObject* object) {
} }
Object* Heap::PrepareForCompare(String* str) { MaybeObject* Heap::PrepareForCompare(String* str) {
// Always flatten small strings and force flattening of long strings // Always flatten small strings and force flattening of long strings
// after we have accumulated a certain amount we failed to flatten. // after we have accumulated a certain amount we failed to flatten.
static const int kMaxAlwaysFlattenLength = 32; static const int kMaxAlwaysFlattenLength = 32;
static const int kFlattenLongThreshold = 16*KB; static const int kFlattenLongThreshold = 16*KB;
const int length = str->length(); const int length = str->length();
Object* obj = str->TryFlatten(); MaybeObject* obj = str->TryFlatten();
if (length <= kMaxAlwaysFlattenLength || if (length <= kMaxAlwaysFlattenLength ||
unflattened_strings_length_ >= kFlattenLongThreshold) { unflattened_strings_length_ >= kFlattenLongThreshold) {
return obj; return obj;
@ -401,34 +391,36 @@ void Heap::SetLastScriptId(Object* last_script_id) {
// to guarantee that any allocations performed during the call will // to guarantee that any allocations performed during the call will
// succeed if there's enough memory. // succeed if there's enough memory.
// Warning: Do not use the identifiers __object__ or __scope__ in a // Warning: Do not use the identifiers __object__, __maybe_object__ or
// call to this macro. // __scope__ in a call to this macro.
#define CALL_AND_RETRY(FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY) \ #define CALL_AND_RETRY(FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY) \
do { \ do { \
GC_GREEDY_CHECK(); \ GC_GREEDY_CHECK(); \
Object* __object__ = FUNCTION_CALL; \ MaybeObject* __maybe_object__ = FUNCTION_CALL; \
if (!__object__->IsFailure()) RETURN_VALUE; \ Object* __object__ = NULL; \
if (__object__->IsOutOfMemoryFailure()) { \ if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \
if (__maybe_object__->IsOutOfMemory()) { \
v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\ v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\
} \ } \
if (!__object__->IsRetryAfterGC()) RETURN_EMPTY; \ if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \
Heap::CollectGarbage(Failure::cast(__object__)->allocation_space()); \ Heap::CollectGarbage(Failure::cast(__maybe_object__)-> \
__object__ = FUNCTION_CALL; \ allocation_space()); \
if (!__object__->IsFailure()) RETURN_VALUE; \ __maybe_object__ = FUNCTION_CALL; \
if (__object__->IsOutOfMemoryFailure()) { \ if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \
if (__maybe_object__->IsOutOfMemory()) { \
v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1", true);\ v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1", true);\
} \ } \
if (!__object__->IsRetryAfterGC()) RETURN_EMPTY; \ if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \
Counters::gc_last_resort_from_handles.Increment(); \ Counters::gc_last_resort_from_handles.Increment(); \
Heap::CollectAllAvailableGarbage(); \ Heap::CollectAllGarbage(false); \
{ \ { \
AlwaysAllocateScope __scope__; \ AlwaysAllocateScope __scope__; \
__object__ = FUNCTION_CALL; \ __maybe_object__ = FUNCTION_CALL; \
} \ } \
if (!__object__->IsFailure()) RETURN_VALUE; \ if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \
if (__object__->IsOutOfMemoryFailure() || \ if (__maybe_object__->IsOutOfMemory() || \
__object__->IsRetryAfterGC()) { \ __maybe_object__->IsRetryAfterGC()) { \
/* TODO(1181417): Fix this. */ \ /* TODO(1181417): Fix this. */ \
v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2", true);\ v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2", true);\
} \ } \

1089
deps/v8/src/heap.cc

File diff suppressed because it is too large

219
deps/v8/src/heap.h

@ -316,32 +316,33 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateJSObject( MUST_USE_RESULT static MaybeObject* AllocateJSObject(
JSFunction* constructor, PretenureFlag pretenure = NOT_TENURED); JSFunction* constructor, PretenureFlag pretenure = NOT_TENURED);
// Allocates and initializes a new global object based on a constructor. // Allocates and initializes a new global object based on a constructor.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateGlobalObject(JSFunction* constructor); MUST_USE_RESULT static MaybeObject* AllocateGlobalObject(
JSFunction* constructor);
// Returns a deep copy of the JavaScript object. // Returns a deep copy of the JavaScript object.
// Properties and elements are copied too. // Properties and elements are copied too.
// Returns failure if allocation failed. // Returns failure if allocation failed.
MUST_USE_RESULT static Object* CopyJSObject(JSObject* source); MUST_USE_RESULT static MaybeObject* CopyJSObject(JSObject* source);
// Allocates the function prototype. // Allocates the function prototype.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateFunctionPrototype( MUST_USE_RESULT static MaybeObject* AllocateFunctionPrototype(
JSFunction* function); JSFunction* function);
// Reinitialize an JSGlobalProxy based on a constructor. The object // Reinitialize an JSGlobalProxy based on a constructor. The object
// must have the same size as objects allocated using the // must have the same size as objects allocated using the
// constructor. The object is reinitialized and behaves as an // constructor. The object is reinitialized and behaves as an
// object that has been freshly allocated using the constructor. // object that has been freshly allocated using the constructor.
MUST_USE_RESULT static Object* ReinitializeJSGlobalProxy( MUST_USE_RESULT static MaybeObject* ReinitializeJSGlobalProxy(
JSFunction* constructor, JSFunction* constructor,
JSGlobalProxy* global); JSGlobalProxy* global);
@ -349,31 +350,32 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateJSObjectFromMap( MUST_USE_RESULT static MaybeObject* AllocateJSObjectFromMap(
Map* map, PretenureFlag pretenure = NOT_TENURED); Map* map, PretenureFlag pretenure = NOT_TENURED);
// Allocates a heap object based on the map. // Allocates a heap object based on the map.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this function does not perform a garbage collection. // Please note this function does not perform a garbage collection.
MUST_USE_RESULT static Object* Allocate(Map* map, AllocationSpace space); MUST_USE_RESULT static MaybeObject* Allocate(Map* map, AllocationSpace space);
// Allocates a JS Map in the heap. // Allocates a JS Map in the heap.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this function does not perform a garbage collection. // Please note this function does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateMap(InstanceType instance_type, MUST_USE_RESULT static MaybeObject* AllocateMap(InstanceType instance_type,
int instance_size); int instance_size);
// Allocates a partial map for bootstrapping. // Allocates a partial map for bootstrapping.
MUST_USE_RESULT static Object* AllocatePartialMap(InstanceType instance_type, MUST_USE_RESULT static MaybeObject* AllocatePartialMap(
int instance_size); InstanceType instance_type,
int instance_size);
// Allocate a map for the specified function // Allocate a map for the specified function
MUST_USE_RESULT static Object* AllocateInitialMap(JSFunction* fun); MUST_USE_RESULT static MaybeObject* AllocateInitialMap(JSFunction* fun);
// Allocates an empty code cache. // Allocates an empty code cache.
MUST_USE_RESULT static Object* AllocateCodeCache(); MUST_USE_RESULT static MaybeObject* AllocateCodeCache();
// Clear the Instanceof cache (used when a prototype changes). // Clear the Instanceof cache (used when a prototype changes).
static void ClearInstanceofCache() { static void ClearInstanceofCache() {
@ -398,13 +400,13 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateStringFromAscii( MUST_USE_RESULT static MaybeObject* AllocateStringFromAscii(
Vector<const char> str, Vector<const char> str,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
MUST_USE_RESULT static Object* AllocateStringFromUtf8( MUST_USE_RESULT static MaybeObject* AllocateStringFromUtf8(
Vector<const char> str, Vector<const char> str,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
MUST_USE_RESULT static Object* AllocateStringFromTwoByte( MUST_USE_RESULT static MaybeObject* AllocateStringFromTwoByte(
Vector<const uc16> str, Vector<const uc16> str,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
@ -412,15 +414,17 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this function does not perform a garbage collection. // Please note this function does not perform a garbage collection.
MUST_USE_RESULT static inline Object* AllocateSymbol(Vector<const char> str, MUST_USE_RESULT static inline MaybeObject* AllocateSymbol(
int chars, Vector<const char> str,
uint32_t hash_field); int chars,
uint32_t hash_field);
MUST_USE_RESULT static Object* AllocateInternalSymbol( MUST_USE_RESULT static MaybeObject* AllocateInternalSymbol(
unibrow::CharacterStream* buffer, int chars, uint32_t hash_field); unibrow::CharacterStream* buffer, int chars, uint32_t hash_field);
MUST_USE_RESULT static Object* AllocateExternalSymbol(Vector<const char> str, MUST_USE_RESULT static MaybeObject* AllocateExternalSymbol(
int chars); Vector<const char> str,
int chars);
// Allocates and partially initializes a String. There are two String // Allocates and partially initializes a String. There are two String
@ -430,10 +434,10 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateRawAsciiString( MUST_USE_RESULT static MaybeObject* AllocateRawAsciiString(
int length, int length,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
MUST_USE_RESULT static Object* AllocateRawTwoByteString( MUST_USE_RESULT static MaybeObject* AllocateRawTwoByteString(
int length, int length,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
@ -441,27 +445,27 @@ class Heap : public AllStatic {
// A cache is used for ascii codes. // A cache is used for ascii codes.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. Please note this does not perform a garbage collection. // failed. Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* LookupSingleCharacterStringFromCode( MUST_USE_RESULT static MaybeObject* LookupSingleCharacterStringFromCode(
uint16_t code); uint16_t code);
// Allocate a byte array of the specified length // Allocate a byte array of the specified length
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateByteArray(int length, MUST_USE_RESULT static MaybeObject* AllocateByteArray(int length,
PretenureFlag pretenure); PretenureFlag pretenure);
// Allocate a non-tenured byte array of the specified length // Allocate a non-tenured byte array of the specified length
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateByteArray(int length); MUST_USE_RESULT static MaybeObject* AllocateByteArray(int length);
// Allocate a pixel array of the specified length // Allocate a pixel array of the specified length
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocatePixelArray(int length, MUST_USE_RESULT static MaybeObject* AllocatePixelArray(int length,
uint8_t* external_pointer, uint8_t* external_pointer,
PretenureFlag pretenure); PretenureFlag pretenure);
@ -469,7 +473,7 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateExternalArray( MUST_USE_RESULT static MaybeObject* AllocateExternalArray(
int length, int length,
ExternalArrayType array_type, ExternalArrayType array_type,
void* external_pointer, void* external_pointer,
@ -479,66 +483,71 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateJSGlobalPropertyCell(Object* value); MUST_USE_RESULT static MaybeObject* AllocateJSGlobalPropertyCell(
Object* value);
// Allocates a fixed array initialized with undefined values // Allocates a fixed array initialized with undefined values
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateFixedArray(int length, MUST_USE_RESULT static MaybeObject* AllocateFixedArray(
PretenureFlag pretenure); int length,
PretenureFlag pretenure);
// Allocates a fixed array initialized with undefined values // Allocates a fixed array initialized with undefined values
MUST_USE_RESULT static Object* AllocateFixedArray(int length); MUST_USE_RESULT static MaybeObject* AllocateFixedArray(int length);
// Allocates an uninitialized fixed array. It must be filled by the caller. // Allocates an uninitialized fixed array. It must be filled by the caller.
// //
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateUninitializedFixedArray(int length); MUST_USE_RESULT static MaybeObject* AllocateUninitializedFixedArray(
int length);
// Make a copy of src and return it. Returns // Make a copy of src and return it. Returns
// Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
MUST_USE_RESULT static inline Object* CopyFixedArray(FixedArray* src); MUST_USE_RESULT static inline MaybeObject* CopyFixedArray(FixedArray* src);
// Make a copy of src, set the map, and return the copy. Returns // Make a copy of src, set the map, and return the copy. Returns
// Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed.
MUST_USE_RESULT static Object* CopyFixedArrayWithMap(FixedArray* src, MUST_USE_RESULT static MaybeObject* CopyFixedArrayWithMap(FixedArray* src,
Map* map); Map* map);
// Allocates a fixed array initialized with the hole values. // Allocates a fixed array initialized with the hole values.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateFixedArrayWithHoles( MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithHoles(
int length, int length,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
// AllocateHashTable is identical to AllocateFixedArray except // AllocateHashTable is identical to AllocateFixedArray except
// that the resulting object has hash_table_map as map. // that the resulting object has hash_table_map as map.
MUST_USE_RESULT static Object* AllocateHashTable( MUST_USE_RESULT static MaybeObject* AllocateHashTable(
int length, PretenureFlag pretenure = NOT_TENURED); int length, PretenureFlag pretenure = NOT_TENURED);
// Allocate a global (but otherwise uninitialized) context. // Allocate a global (but otherwise uninitialized) context.
MUST_USE_RESULT static Object* AllocateGlobalContext(); MUST_USE_RESULT static MaybeObject* AllocateGlobalContext();
// Allocate a function context. // Allocate a function context.
MUST_USE_RESULT static Object* AllocateFunctionContext(int length, MUST_USE_RESULT static MaybeObject* AllocateFunctionContext(
JSFunction* closure); int length,
JSFunction* closure);
// Allocate a 'with' context. // Allocate a 'with' context.
MUST_USE_RESULT static Object* AllocateWithContext(Context* previous, MUST_USE_RESULT static MaybeObject* AllocateWithContext(
JSObject* extension, Context* previous,
bool is_catch_context); JSObject* extension,
bool is_catch_context);
// Allocates a new utility object in the old generation. // Allocates a new utility object in the old generation.
MUST_USE_RESULT static Object* AllocateStruct(InstanceType type); MUST_USE_RESULT static MaybeObject* AllocateStruct(InstanceType type);
// Allocates a function initialized with a shared part. // Allocates a function initialized with a shared part.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateFunction( MUST_USE_RESULT static MaybeObject* AllocateFunction(
Map* function_map, Map* function_map,
SharedFunctionInfo* shared, SharedFunctionInfo* shared,
Object* prototype, Object* prototype,
@ -554,37 +563,38 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateArgumentsObject(Object* callee, MUST_USE_RESULT static MaybeObject* AllocateArgumentsObject(Object* callee,
int length); int length);
// Same as NewNumberFromDouble, but may return a preallocated/immutable // Same as NewNumberFromDouble, but may return a preallocated/immutable
// number object (e.g., minus_zero_value_, nan_value_) // number object (e.g., minus_zero_value_, nan_value_)
MUST_USE_RESULT static Object* NumberFromDouble( MUST_USE_RESULT static MaybeObject* NumberFromDouble(
double value, PretenureFlag pretenure = NOT_TENURED); double value, PretenureFlag pretenure = NOT_TENURED);
// Allocated a HeapNumber from value. // Allocated a HeapNumber from value.
MUST_USE_RESULT static Object* AllocateHeapNumber(double value, MUST_USE_RESULT static MaybeObject* AllocateHeapNumber(
PretenureFlag pretenure); double value,
PretenureFlag pretenure);
// pretenure = NOT_TENURED. // pretenure = NOT_TENURED.
MUST_USE_RESULT static Object* AllocateHeapNumber(double value); MUST_USE_RESULT static MaybeObject* AllocateHeapNumber(double value);
// Converts an int into either a Smi or a HeapNumber object. // Converts an int into either a Smi or a HeapNumber object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static inline Object* NumberFromInt32(int32_t value); MUST_USE_RESULT static inline MaybeObject* NumberFromInt32(int32_t value);
// Converts an int into either a Smi or a HeapNumber object. // Converts an int into either a Smi or a HeapNumber object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static inline Object* NumberFromUint32(uint32_t value); MUST_USE_RESULT static inline MaybeObject* NumberFromUint32(uint32_t value);
// Allocates a new proxy object. // Allocates a new proxy object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateProxy( MUST_USE_RESULT static MaybeObject* AllocateProxy(
Address proxy, Address proxy,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
@ -592,14 +602,14 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateSharedFunctionInfo(Object* name); MUST_USE_RESULT static MaybeObject* AllocateSharedFunctionInfo(Object* name);
// Allocates a new cons string object. // Allocates a new cons string object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateConsString(String* first, MUST_USE_RESULT static MaybeObject* AllocateConsString(String* first,
String* second); String* second);
// Allocates a new sub string object which is a substring of an underlying // Allocates a new sub string object which is a substring of an underlying
// string buffer stretching from the index start (inclusive) to the index // string buffer stretching from the index start (inclusive) to the index
@ -607,7 +617,7 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateSubString( MUST_USE_RESULT static MaybeObject* AllocateSubString(
String* buffer, String* buffer,
int start, int start,
int end, int end,
@ -618,9 +628,9 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static Object* AllocateExternalStringFromAscii( MUST_USE_RESULT static MaybeObject* AllocateExternalStringFromAscii(
ExternalAsciiString::Resource* resource); ExternalAsciiString::Resource* resource);
MUST_USE_RESULT static Object* AllocateExternalStringFromTwoByte( MUST_USE_RESULT static MaybeObject* AllocateExternalStringFromTwoByte(
ExternalTwoByteString::Resource* resource); ExternalTwoByteString::Resource* resource);
// Finalizes an external string by deleting the associated external // Finalizes an external string by deleting the associated external
@ -632,7 +642,7 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this function does not perform a garbage collection. // Please note this function does not perform a garbage collection.
MUST_USE_RESULT static inline Object* AllocateRaw( MUST_USE_RESULT static inline MaybeObject* AllocateRaw(
int size_in_bytes, int size_in_bytes,
AllocationSpace space, AllocationSpace space,
AllocationSpace retry_space); AllocationSpace retry_space);
@ -647,26 +657,27 @@ class Heap : public AllStatic {
// self_reference. This allows generated code to reference its own Code // self_reference. This allows generated code to reference its own Code
// object by containing this pointer. // object by containing this pointer.
// Please note this function does not perform a garbage collection. // Please note this function does not perform a garbage collection.
MUST_USE_RESULT static Object* CreateCode(const CodeDesc& desc, MUST_USE_RESULT static MaybeObject* CreateCode(const CodeDesc& desc,
Code::Flags flags, Code::Flags flags,
Handle<Object> self_reference); Handle<Object> self_reference);
MUST_USE_RESULT static Object* CopyCode(Code* code); MUST_USE_RESULT static MaybeObject* CopyCode(Code* code);
// Copy the code and scope info part of the code object, but insert // Copy the code and scope info part of the code object, but insert
// the provided data as the relocation information. // the provided data as the relocation information.
MUST_USE_RESULT static Object* CopyCode(Code* code, Vector<byte> reloc_info); MUST_USE_RESULT static MaybeObject* CopyCode(Code* code,
Vector<byte> reloc_info);
// Finds the symbol for string in the symbol table. // Finds the symbol for string in the symbol table.
// If not found, a new symbol is added to the table and returned. // If not found, a new symbol is added to the table and returned.
// Returns Failure::RetryAfterGC(requested_bytes, space) if allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if allocation
// failed. // failed.
// Please note this function does not perform a garbage collection. // Please note this function does not perform a garbage collection.
MUST_USE_RESULT static Object* LookupSymbol(Vector<const char> str); MUST_USE_RESULT static MaybeObject* LookupSymbol(Vector<const char> str);
MUST_USE_RESULT static Object* LookupAsciiSymbol(const char* str) { MUST_USE_RESULT static MaybeObject* LookupAsciiSymbol(const char* str) {
return LookupSymbol(CStrVector(str)); return LookupSymbol(CStrVector(str));
} }
MUST_USE_RESULT static Object* LookupSymbol(String* str); MUST_USE_RESULT static MaybeObject* LookupSymbol(String* str);
static bool LookupSymbolIfExists(String* str, String** symbol); static bool LookupSymbolIfExists(String* str, String** symbol);
static bool LookupTwoCharsSymbolIfExists(String* str, String** symbol); static bool LookupTwoCharsSymbolIfExists(String* str, String** symbol);
@ -681,7 +692,7 @@ class Heap : public AllStatic {
// string might stay non-flat even when not a failure is returned. // string might stay non-flat even when not a failure is returned.
// //
// Please note this function does not perform a garbage collection. // Please note this function does not perform a garbage collection.
MUST_USE_RESULT static inline Object* PrepareForCompare(String* str); MUST_USE_RESULT static inline MaybeObject* PrepareForCompare(String* str);
// Converts the given boolean condition to JavaScript boolean value. // Converts the given boolean condition to JavaScript boolean value.
static Object* ToBoolean(bool condition) { static Object* ToBoolean(bool condition) {
@ -693,20 +704,13 @@ class Heap : public AllStatic {
static void GarbageCollectionPrologue(); static void GarbageCollectionPrologue();
static void GarbageCollectionEpilogue(); static void GarbageCollectionEpilogue();
enum CollectionPolicy { NORMAL, AGGRESSIVE };
// Performs garbage collection operation. // Performs garbage collection operation.
// Returns whether required_space bytes are available after the collection. // Returns whether required_space bytes are available after the collection.
static void CollectGarbage(AllocationSpace space, static void CollectGarbage(AllocationSpace space);
CollectionPolicy collectionPolicy = NORMAL);
// Performs a full garbage collection. Force compaction if the // Performs a full garbage collection. Force compaction if the
// parameter is true. // parameter is true.
static void CollectAllGarbage(bool force_compaction, static void CollectAllGarbage(bool force_compaction);
CollectionPolicy collectionPolicy = NORMAL);
// Last hope GC, should try to squeeze as much as possible.
static void CollectAllAvailableGarbage();
// Notify the heap that a context has been disposed. // Notify the heap that a context has been disposed.
static int NotifyContextDisposed() { return ++contexts_disposed_; } static int NotifyContextDisposed() { return ++contexts_disposed_; }
@ -904,10 +908,10 @@ class Heap : public AllStatic {
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
// Please note this function does not perform a garbage collection. // Please note this function does not perform a garbage collection.
MUST_USE_RESULT static Object* CreateSymbol(const char* str, MUST_USE_RESULT static MaybeObject* CreateSymbol(const char* str,
int length, int length,
int hash); int hash);
MUST_USE_RESULT static Object* CreateSymbol(String* str); MUST_USE_RESULT static MaybeObject* CreateSymbol(String* str);
// Write barrier support for address[offset] = o. // Write barrier support for address[offset] = o.
static inline void RecordWrite(Address address, int offset); static inline void RecordWrite(Address address, int offset);
@ -979,9 +983,10 @@ class Heap : public AllStatic {
static inline int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes); static inline int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes);
// Allocate uninitialized fixed array. // Allocate uninitialized fixed array.
MUST_USE_RESULT static Object* AllocateRawFixedArray(int length); MUST_USE_RESULT static MaybeObject* AllocateRawFixedArray(int length);
MUST_USE_RESULT static Object* AllocateRawFixedArray(int length, MUST_USE_RESULT static MaybeObject* AllocateRawFixedArray(
PretenureFlag pretenure); int length,
PretenureFlag pretenure);
// True if we have reached the allocation limit in the old generation that // True if we have reached the allocation limit in the old generation that
// should force the next GC (caused normally) to be a full one. // should force the next GC (caused normally) to be a full one.
@ -1024,7 +1029,7 @@ class Heap : public AllStatic {
kRootListLength kRootListLength
}; };
MUST_USE_RESULT static Object* NumberToString( MUST_USE_RESULT static MaybeObject* NumberToString(
Object* number, Object* number,
bool check_number_string_cache = true); bool check_number_string_cache = true);
@ -1242,22 +1247,16 @@ class Heap : public AllStatic {
// Performs garbage collection // Performs garbage collection
static void PerformGarbageCollection(GarbageCollector collector, static void PerformGarbageCollection(GarbageCollector collector,
GCTracer* tracer, GCTracer* tracer);
CollectionPolicy collectionPolicy);
static const intptr_t kMinimumPromotionLimit = 2 * MB;
static const intptr_t kMinimumAllocationLimit = 8 * MB;
inline static void UpdateOldSpaceLimits();
// Allocate an uninitialized object in map space. The behavior is identical // Allocate an uninitialized object in map space. The behavior is identical
// to Heap::AllocateRaw(size_in_bytes, MAP_SPACE), except that (a) it doesn't // to Heap::AllocateRaw(size_in_bytes, MAP_SPACE), except that (a) it doesn't
// have to test the allocation space argument and (b) can reduce code size // have to test the allocation space argument and (b) can reduce code size
// (since both AllocateRaw and AllocateRawMap are inlined). // (since both AllocateRaw and AllocateRawMap are inlined).
MUST_USE_RESULT static inline Object* AllocateRawMap(); MUST_USE_RESULT static inline MaybeObject* AllocateRawMap();
// Allocate an uninitialized object in the global property cell space. // Allocate an uninitialized object in the global property cell space.
MUST_USE_RESULT static inline Object* AllocateRawCell(); MUST_USE_RESULT static inline MaybeObject* AllocateRawCell();
// Initializes a JSObject based on its map. // Initializes a JSObject based on its map.
static void InitializeJSObjectFromMap(JSObject* obj, static void InitializeJSObjectFromMap(JSObject* obj,
@ -1276,10 +1275,11 @@ class Heap : public AllStatic {
static void CreateFixedStubs(); static void CreateFixedStubs();
static Object* CreateOddball(const char* to_string, Object* to_number); MUST_USE_RESULT static MaybeObject* CreateOddball(const char* to_string,
Object* to_number);
// Allocate empty fixed array. // Allocate empty fixed array.
static Object* AllocateEmptyFixedArray(); MUST_USE_RESULT static MaybeObject* AllocateEmptyFixedArray();
// Performs a minor collection in new generation. // Performs a minor collection in new generation.
static void Scavenge(); static void Scavenge();
@ -1318,7 +1318,7 @@ class Heap : public AllStatic {
// other parts of the VM could use it. Specifically, a function that creates // other parts of the VM could use it. Specifically, a function that creates
// instances of type JS_FUNCTION_TYPE benefit from the use of this function. // instances of type JS_FUNCTION_TYPE benefit from the use of this function.
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT static inline Object* InitializeFunction( MUST_USE_RESULT static inline MaybeObject* InitializeFunction(
JSFunction* function, JSFunction* function,
SharedFunctionInfo* shared, SharedFunctionInfo* shared,
Object* prototype); Object* prototype);
@ -1327,7 +1327,7 @@ class Heap : public AllStatic {
// Initializes the number to string cache based on the max semispace size. // Initializes the number to string cache based on the max semispace size.
static Object* InitializeNumberStringCache(); MUST_USE_RESULT static MaybeObject* InitializeNumberStringCache();
// Flush the number to string cache. // Flush the number to string cache.
static void FlushNumberStringCache(); static void FlushNumberStringCache();
@ -1935,7 +1935,7 @@ class TranscendentalCache {
// Returns a heap number with f(input), where f is a math function specified // Returns a heap number with f(input), where f is a math function specified
// by the 'type' argument. // by the 'type' argument.
MUST_USE_RESULT static inline Object* Get(Type type, double input) { MUST_USE_RESULT static inline MaybeObject* Get(Type type, double input) {
TranscendentalCache* cache = caches_[type]; TranscendentalCache* cache = caches_[type];
if (cache == NULL) { if (cache == NULL) {
caches_[type] = cache = new TranscendentalCache(type); caches_[type] = cache = new TranscendentalCache(type);
@ -1948,7 +1948,7 @@ class TranscendentalCache {
static void Clear(); static void Clear();
private: private:
MUST_USE_RESULT inline Object* Get(double input) { MUST_USE_RESULT inline MaybeObject* Get(double input) {
Converter c; Converter c;
c.dbl = input; c.dbl = input;
int hash = Hash(c); int hash = Hash(c);
@ -1960,13 +1960,14 @@ class TranscendentalCache {
return e.output; return e.output;
} }
double answer = Calculate(input); double answer = Calculate(input);
Object* heap_number = Heap::AllocateHeapNumber(answer);
if (!heap_number->IsFailure()) {
elements_[hash].in[0] = c.integers[0];
elements_[hash].in[1] = c.integers[1];
elements_[hash].output = heap_number;
}
Counters::transcendental_cache_miss.Increment(); Counters::transcendental_cache_miss.Increment();
Object* heap_number;
{ MaybeObject* maybe_heap_number = Heap::AllocateHeapNumber(answer);
if (!maybe_heap_number->ToObject(&heap_number)) return maybe_heap_number;
}
elements_[hash].in[0] = c.integers[0];
elements_[hash].in[1] = c.integers[1];
elements_[hash].output = heap_number;
return heap_number; return heap_number;
} }

11
deps/v8/src/ia32/assembler-ia32.cc

@ -120,10 +120,15 @@ void CpuFeatures::Probe() {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc,
Code::ComputeFlags(Code::STUB), Object* code;
Handle<Code>::null()); { MaybeObject* maybe_code = Heap::CreateCode(desc,
Code::ComputeFlags(Code::STUB),
Handle<Code>::null());
if (!maybe_code->ToObject(&code)) return;
}
if (!code->IsCode()) return; if (!code->IsCode()) return;
PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG, PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), "CpuFeatures::Probe")); Code::cast(code), "CpuFeatures::Probe"));
typedef uint64_t (*F0)(); typedef uint64_t (*F0)();

1
deps/v8/src/ia32/assembler-ia32.h

@ -695,7 +695,6 @@ class Assembler : public Malloced {
void call(Label* L); void call(Label* L);
void call(byte* entry, RelocInfo::Mode rmode); void call(byte* entry, RelocInfo::Mode rmode);
void call(const Operand& adr); void call(const Operand& adr);
void call(const ExternalReference& target);
void call(Handle<Code> code, RelocInfo::Mode rmode); void call(Handle<Code> code, RelocInfo::Mode rmode);
// Jumps // Jumps

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

@ -3058,74 +3058,12 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
} }
// If true, a Handle<T> passed by value is passed and returned by
// using the location_ field directly. If false, it is passed and
// returned as a pointer to a handle.
#ifdef USING_BSD_ABI
static const bool kPassHandlesDirectly = true;
#else
static const bool kPassHandlesDirectly = false;
#endif
void ApiGetterEntryStub::Generate(MacroAssembler* masm) { void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
Label empty_handle; __ PrepareCallApiFunction(kStackSpace, kArgc);
Label prologue; STATIC_ASSERT(kArgc == 2);
Label promote_scheduled_exception; __ mov(ApiParameterOperand(0), ebx); // name.
__ EnterApiExitFrame(kStackSpace, kArgc); __ mov(ApiParameterOperand(1), eax); // arguments pointer.
STATIC_ASSERT(kArgc == 4); __ CallApiFunctionAndReturn(fun(), kArgc);
if (kPassHandlesDirectly) {
// When handles as passed directly we don't have to allocate extra
// space for and pass an out parameter.
__ mov(Operand(esp, 0 * kPointerSize), ebx); // name.
__ mov(Operand(esp, 1 * kPointerSize), eax); // arguments pointer.
} else {
// The function expects three arguments to be passed but we allocate
// four to get space for the output cell. The argument slots are filled
// as follows:
//
// 3: output cell
// 2: arguments pointer
// 1: name
// 0: pointer to the output cell
//
// Note that this is one more "argument" than the function expects
// so the out cell will have to be popped explicitly after returning
// from the function.
__ mov(Operand(esp, 1 * kPointerSize), ebx); // name.
__ mov(Operand(esp, 2 * kPointerSize), eax); // arguments pointer.
__ mov(ebx, esp);
__ add(Operand(ebx), Immediate(3 * kPointerSize));
__ mov(Operand(esp, 0 * kPointerSize), ebx); // output
__ mov(Operand(esp, 3 * kPointerSize), Immediate(0)); // out cell.
}
// Call the api function!
__ call(fun()->address(), RelocInfo::RUNTIME_ENTRY);
// Check if the function scheduled an exception.
ExternalReference scheduled_exception_address =
ExternalReference::scheduled_exception_address();
__ cmp(Operand::StaticVariable(scheduled_exception_address),
Immediate(Factory::the_hole_value()));
__ j(not_equal, &promote_scheduled_exception, not_taken);
if (!kPassHandlesDirectly) {
// The returned value is a pointer to the handle holding the result.
// Dereference this to get to the location.
__ mov(eax, Operand(eax, 0));
}
// Check if the result handle holds 0.
__ test(eax, Operand(eax));
__ j(zero, &empty_handle, not_taken);
// It was non-zero. Dereference to get the result value.
__ mov(eax, Operand(eax, 0));
__ bind(&prologue);
__ LeaveExitFrame();
__ ret(0);
__ bind(&promote_scheduled_exception);
__ TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
__ bind(&empty_handle);
// It was zero; the result is undefined.
__ mov(eax, Factory::undefined_value());
__ jmp(&prologue);
} }

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

@ -584,6 +584,20 @@ void MacroAssembler::AllocateInNewSpace(int object_size,
Register scratch, Register scratch,
Label* gc_required, Label* gc_required,
AllocationFlags flags) { AllocationFlags flags) {
if (!FLAG_inline_new) {
if (FLAG_debug_code) {
// Trash the registers to simulate an allocation failure.
mov(result, Immediate(0x7091));
if (result_end.is_valid()) {
mov(result_end, Immediate(0x7191));
}
if (scratch.is_valid()) {
mov(scratch, Immediate(0x7291));
}
}
jmp(gc_required);
return;
}
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
@ -627,6 +641,19 @@ void MacroAssembler::AllocateInNewSpace(int header_size,
Register scratch, Register scratch,
Label* gc_required, Label* gc_required,
AllocationFlags flags) { AllocationFlags flags) {
if (!FLAG_inline_new) {
if (FLAG_debug_code) {
// Trash the registers to simulate an allocation failure.
mov(result, Immediate(0x7091));
mov(result_end, Immediate(0x7191));
if (scratch.is_valid()) {
mov(scratch, Immediate(0x7291));
}
// Register element_count is not modified by the function.
}
jmp(gc_required);
return;
}
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
@ -655,6 +682,19 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
Register scratch, Register scratch,
Label* gc_required, Label* gc_required,
AllocationFlags flags) { AllocationFlags flags) {
if (!FLAG_inline_new) {
if (FLAG_debug_code) {
// Trash the registers to simulate an allocation failure.
mov(result, Immediate(0x7091));
mov(result_end, Immediate(0x7191));
if (scratch.is_valid()) {
mov(scratch, Immediate(0x7291));
}
// object_size is left unchanged by this function.
}
jmp(gc_required);
return;
}
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
@ -936,12 +976,13 @@ void MacroAssembler::CallStub(CodeStub* stub) {
} }
Object* MacroAssembler::TryCallStub(CodeStub* stub) { MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) {
ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
Object* result = stub->TryGetCode(); Object* result;
if (!result->IsFailure()) { { MaybeObject* maybe_result = stub->TryGetCode();
call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); if (!maybe_result->ToObject(&result)) return maybe_result;
} }
call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
return result; return result;
} }
@ -952,12 +993,13 @@ void MacroAssembler::TailCallStub(CodeStub* stub) {
} }
Object* MacroAssembler::TryTailCallStub(CodeStub* stub) { MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub) {
ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
Object* result = stub->TryGetCode(); Object* result;
if (!result->IsFailure()) { { MaybeObject* maybe_result = stub->TryGetCode();
jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); if (!maybe_result->ToObject(&result)) return maybe_result;
} }
jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
return result; return result;
} }
@ -1000,8 +1042,8 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
} }
Object* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id,
int num_arguments) { int num_arguments) {
return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); return TryCallRuntime(Runtime::FunctionForId(id), num_arguments);
} }
@ -1026,8 +1068,8 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
} }
Object* MacroAssembler::TryCallRuntime(Runtime::Function* f, MaybeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f,
int num_arguments) { int num_arguments) {
if (f->nargs >= 0 && f->nargs != num_arguments) { if (f->nargs >= 0 && f->nargs != num_arguments) {
IllegalOperation(num_arguments); IllegalOperation(num_arguments);
// Since we did not call the stub, there was no allocation failure. // Since we did not call the stub, there was no allocation failure.
@ -1075,66 +1117,116 @@ void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
} }
void MacroAssembler::PushHandleScope(Register scratch) { // If true, a Handle<T> passed by value is passed and returned by
// Push the number of extensions, smi-tagged so the gc will ignore it. // using the location_ field directly. If false, it is passed and
ExternalReference extensions_address = // returned as a pointer to a handle.
ExternalReference::handle_scope_extensions_address(); #ifdef USING_BSD_ABI
mov(scratch, Operand::StaticVariable(extensions_address)); static const bool kPassHandlesDirectly = true;
SmiTag(scratch); #else
push(scratch); static const bool kPassHandlesDirectly = false;
mov(Operand::StaticVariable(extensions_address), Immediate(0)); #endif
// Push next and limit pointers which will be wordsize aligned and
// hence automatically smi tagged.
ExternalReference next_address = Operand ApiParameterOperand(int index) {
ExternalReference::handle_scope_next_address(); return Operand(esp, (index + (kPassHandlesDirectly ? 0 : 1)) * kPointerSize);
push(Operand::StaticVariable(next_address));
ExternalReference limit_address =
ExternalReference::handle_scope_limit_address();
push(Operand::StaticVariable(limit_address));
} }
Object* MacroAssembler::PopHandleScopeHelper(Register saved, void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) {
Register scratch, if (kPassHandlesDirectly) {
bool gc_allowed) { EnterApiExitFrame(stack_space, argc);
Object* result = NULL; // When handles as passed directly we don't have to allocate extra
ExternalReference extensions_address = // space for and pass an out parameter.
ExternalReference::handle_scope_extensions_address();
Label write_back;
mov(scratch, Operand::StaticVariable(extensions_address));
cmp(Operand(scratch), Immediate(0));
j(equal, &write_back);
push(saved);
if (gc_allowed) {
CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
} else { } else {
result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); // We allocate two additional slots: return value and pointer to it.
if (result->IsFailure()) return result; EnterApiExitFrame(stack_space, argc + 2);
} }
pop(saved); }
bind(&write_back);
ExternalReference limit_address =
ExternalReference::handle_scope_limit_address();
pop(Operand::StaticVariable(limit_address));
ExternalReference next_address =
ExternalReference::handle_scope_next_address();
pop(Operand::StaticVariable(next_address));
pop(scratch);
SmiUntag(scratch);
mov(Operand::StaticVariable(extensions_address), scratch);
return result; void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function, int argc) {
} if (!kPassHandlesDirectly) {
// The argument slots are filled as follows:
//
// n + 1: output cell
// n: arg n
// ...
// 1: arg1
// 0: pointer to the output cell
//
// Note that this is one more "argument" than the function expects
// so the out cell will have to be popped explicitly after returning
// from the function. The out cell contains Handle.
lea(eax, Operand(esp, (argc + 1) * kPointerSize)); // pointer to out cell.
mov(Operand(esp, 0 * kPointerSize), eax); // output.
mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell.
}
ExternalReference next_address =
ExternalReference::handle_scope_next_address();
ExternalReference limit_address =
ExternalReference::handle_scope_limit_address();
ExternalReference level_address =
ExternalReference::handle_scope_level_address();
void MacroAssembler::PopHandleScope(Register saved, Register scratch) { // Allocate HandleScope in callee-save registers.
PopHandleScopeHelper(saved, scratch, true); mov(ebx, Operand::StaticVariable(next_address));
} mov(edi, Operand::StaticVariable(limit_address));
add(Operand::StaticVariable(level_address), Immediate(1));
// Call the api function!
call(function->address(), RelocInfo::RUNTIME_ENTRY);
if (!kPassHandlesDirectly) {
// The returned value is a pointer to the handle holding the result.
// Dereference this to get to the location.
mov(eax, Operand(eax, 0));
}
Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { Label empty_handle;
return PopHandleScopeHelper(saved, scratch, false); Label prologue;
Label promote_scheduled_exception;
Label delete_allocated_handles;
Label leave_exit_frame;
// Check if the result handle holds 0.
test(eax, Operand(eax));
j(zero, &empty_handle, not_taken);
// It was non-zero. Dereference to get the result value.
mov(eax, Operand(eax, 0));
bind(&prologue);
// No more valid handles (the result handle was the last one). Restore
// previous handle scope.
mov(Operand::StaticVariable(next_address), ebx);
sub(Operand::StaticVariable(level_address), Immediate(1));
Assert(above_equal, "Invalid HandleScope level");
cmp(edi, Operand::StaticVariable(limit_address));
j(not_equal, &delete_allocated_handles, not_taken);
bind(&leave_exit_frame);
// Check if the function scheduled an exception.
ExternalReference scheduled_exception_address =
ExternalReference::scheduled_exception_address();
cmp(Operand::StaticVariable(scheduled_exception_address),
Immediate(Factory::the_hole_value()));
j(not_equal, &promote_scheduled_exception, not_taken);
LeaveExitFrame();
ret(0);
bind(&promote_scheduled_exception);
TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
bind(&empty_handle);
// It was zero; the result is undefined.
mov(eax, Factory::undefined_value());
jmp(&prologue);
// HandleScope limit has changed. Delete allocated extensions.
bind(&delete_allocated_handles);
mov(Operand::StaticVariable(limit_address), edi);
mov(edi, eax);
mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions()));
call(Operand(eax));
mov(eax, edi);
jmp(&leave_exit_frame);
} }

36
deps/v8/src/ia32/macro-assembler-ia32.h

@ -421,7 +421,7 @@ class MacroAssembler: public Assembler {
// Call a code stub and return the code object called. Try to generate // Call a code stub and return the code object called. Try to generate
// the code if necessary. Do not perform a GC but instead return a retry // the code if necessary. Do not perform a GC but instead return a retry
// after GC failure. // after GC failure.
Object* TryCallStub(CodeStub* stub); MUST_USE_RESULT MaybeObject* TryCallStub(CodeStub* stub);
// Tail call a code stub (jump). Generate the code if necessary. // Tail call a code stub (jump). Generate the code if necessary.
void TailCallStub(CodeStub* stub); void TailCallStub(CodeStub* stub);
@ -429,7 +429,7 @@ class MacroAssembler: public Assembler {
// Tail call a code stub (jump) and return the code object called. Try to // Tail call a code stub (jump) and return the code object called. Try to
// generate the code if necessary. Do not perform a GC but instead return // generate the code if necessary. Do not perform a GC but instead return
// a retry after GC failure. // a retry after GC failure.
Object* TryTailCallStub(CodeStub* stub); MUST_USE_RESULT MaybeObject* TryTailCallStub(CodeStub* stub);
// Return from a code stub after popping its arguments. // Return from a code stub after popping its arguments.
void StubReturn(int argc); void StubReturn(int argc);
@ -440,13 +440,15 @@ class MacroAssembler: public Assembler {
// Call a runtime function, returning the CodeStub object called. // Call a runtime function, returning the CodeStub object called.
// Try to generate the stub code if necessary. Do not perform a GC // Try to generate the stub code if necessary. Do not perform a GC
// but instead return a retry after GC failure. // but instead return a retry after GC failure.
Object* TryCallRuntime(Runtime::Function* f, int num_arguments); MUST_USE_RESULT MaybeObject* TryCallRuntime(Runtime::Function* f,
int num_arguments);
// Convenience function: Same as above, but takes the fid instead. // Convenience function: Same as above, but takes the fid instead.
void CallRuntime(Runtime::FunctionId id, int num_arguments); void CallRuntime(Runtime::FunctionId id, int num_arguments);
// Convenience function: Same as above, but takes the fid instead. // Convenience function: Same as above, but takes the fid instead.
Object* TryCallRuntime(Runtime::FunctionId id, int num_arguments); MUST_USE_RESULT MaybeObject* TryCallRuntime(Runtime::FunctionId id,
int num_arguments);
// Convenience function: call an external reference. // Convenience function: call an external reference.
void CallExternalReference(ExternalReference ref, int num_arguments); void CallExternalReference(ExternalReference ref, int num_arguments);
@ -480,15 +482,16 @@ class MacroAssembler: public Assembler {
void CallCFunction(ExternalReference function, int num_arguments); void CallCFunction(ExternalReference function, int num_arguments);
void CallCFunction(Register function, int num_arguments); void CallCFunction(Register function, int num_arguments);
void PushHandleScope(Register scratch); // Prepares stack to put arguments (aligns and so on). Reserves
// space for return value if needed (assumes the return value is a handle).
// Uses callee-saved esi to restore stack state after call. Arguments must be
// stored in ApiParameterOperand(0), ApiParameterOperand(1) etc.
void PrepareCallApiFunction(int stack_space, int argc);
// Pops a handle scope using the specified scratch register and // Tail call an API function (jump). Allocates HandleScope, extracts
// ensuring that saved register is left unchanged. // returned value from handle and propagates exceptions.
void PopHandleScope(Register saved, Register scratch); // Clobbers ebx, esi, edi and caller-save registers.
void CallApiFunctionAndReturn(ApiFunction* function, int argc);
// As PopHandleScope, but does not perform a GC. Instead, returns a
// retry after GC failure object if GC is necessary.
Object* TryPopHandleScope(Register saved, Register scratch);
// Jump to a runtime routine. // Jump to a runtime routine.
void JumpToExternalReference(const ExternalReference& ext); void JumpToExternalReference(const ExternalReference& ext);
@ -596,9 +599,9 @@ class MacroAssembler: public Assembler {
// Helper for PopHandleScope. Allowed to perform a GC and returns // Helper for PopHandleScope. Allowed to perform a GC and returns
// NULL if gc_allowed. Does not perform a GC if !gc_allowed, and // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and
// possibly returns a failure object indicating an allocation failure. // possibly returns a failure object indicating an allocation failure.
Object* PopHandleScopeHelper(Register saved, MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved,
Register scratch, Register scratch,
bool gc_allowed); bool gc_allowed);
}; };
@ -639,6 +642,9 @@ static inline Operand FieldOperand(Register object,
return Operand(object, index, scale, offset - kHeapObjectTag); return Operand(object, index, scale, offset - kHeapObjectTag);
} }
// Generates an Operand for saving parameters after PrepareCallApiFunction.
Operand ApiParameterOperand(int index);
#ifdef GENERATED_CODE_COVERAGE #ifdef GENERATED_CODE_COVERAGE
extern void LogGeneratedCodeCoverage(const char* file_line); extern void LogGeneratedCodeCoverage(const char* file_line);

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

@ -1067,7 +1067,7 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
ASSERT(*return_address <= ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size()); re_code->instruction_start() + re_code->instruction_size());
Object* result = Execution::HandleStackGuardInterrupt(); MaybeObject* result = Execution::HandleStackGuardInterrupt();
if (*code_handle != re_code) { // Return address no longer valid if (*code_handle != re_code) { // Return address no longer valid
int delta = *code_handle - re_code; int delta = *code_handle - re_code;

21
deps/v8/src/ia32/simulator-ia32.h

@ -30,10 +30,21 @@
#include "allocation.h" #include "allocation.h"
namespace v8 {
namespace internal {
// Since there is no simulator for the ia32 architecture the only thing we can // Since there is no simulator for the ia32 architecture the only thing we can
// do is to call the entry directly. // do is to call the entry directly.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
entry(p0, p1, p2, p3, p4); (entry(p0, p1, p2, p3, p4))
// Call the generated regexp code directly. The entry function pointer should
// expect seven int/pointer sized arguments and return an int.
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
(entry(p0, p1, p2, p3, p4, p5, p6))
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
(reinterpret_cast<TryCatch*>(try_catch_address))
// The stack limit beyond which we will throw stack overflow errors in // The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on ia32 uses the C stack, we // generated code. Because generated code on ia32 uses the C stack, we
@ -51,12 +62,6 @@ class SimulatorStack : public v8::internal::AllStatic {
static inline void UnregisterCTryCatch() { } static inline void UnregisterCTryCatch() { }
}; };
// Call the generated regexp code directly. The entry function pointer should } } // namespace v8::internal
// expect eight int/pointer sized arguments and return an int.
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
entry(p0, p1, p2, p3, p4, p5, p6)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
#endif // V8_IA32_SIMULATOR_IA32_H_ #endif // V8_IA32_SIMULATOR_IA32_H_

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

@ -807,13 +807,16 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
// Generate code to check that a global property cell is empty. Create // Generate code to check that a global property cell is empty. Create
// the property cell at compilation time if no cell exists for the // the property cell at compilation time if no cell exists for the
// property. // property.
static Object* GenerateCheckPropertyCell(MacroAssembler* masm, MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
GlobalObject* global, MacroAssembler* masm,
String* name, GlobalObject* global,
Register scratch, String* name,
Label* miss) { Register scratch,
Object* probe = global->EnsurePropertyCell(name); Label* miss) {
if (probe->IsFailure()) return probe; Object* probe;
{ MaybeObject* maybe_probe = global->EnsurePropertyCell(name);
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
}
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
ASSERT(cell->value()->IsTheHole()); ASSERT(cell->value()->IsTheHole());
__ mov(scratch, Immediate(Handle<Object>(cell))); __ mov(scratch, Immediate(Handle<Object>(cell)));
@ -826,23 +829,24 @@ static Object* GenerateCheckPropertyCell(MacroAssembler* masm,
// Calls GenerateCheckPropertyCell for each global object in the prototype chain // Calls GenerateCheckPropertyCell for each global object in the prototype chain
// from object to (but not including) holder. // from object to (but not including) holder.
static Object* GenerateCheckPropertyCells(MacroAssembler* masm, MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells(
JSObject* object, MacroAssembler* masm,
JSObject* holder, JSObject* object,
String* name, JSObject* holder,
Register scratch, String* name,
Label* miss) { Register scratch,
Label* miss) {
JSObject* current = object; JSObject* current = object;
while (current != holder) { while (current != holder) {
if (current->IsGlobalObject()) { if (current->IsGlobalObject()) {
Object* cell = GenerateCheckPropertyCell(masm, // Returns a cell or a failure.
GlobalObject::cast(current), MaybeObject* result = GenerateCheckPropertyCell(
name, masm,
scratch, GlobalObject::cast(current),
miss); name,
if (cell->IsFailure()) { scratch,
return cell; miss);
} if (result->IsFailure()) return result;
} }
ASSERT(current->IsJSObject()); ASSERT(current->IsJSObject());
current = JSObject::cast(current->GetPrototype()); current = JSObject::cast(current->GetPrototype());
@ -892,13 +896,13 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
!current->IsJSGlobalObject() && !current->IsJSGlobalObject() &&
!current->IsJSGlobalProxy()) { !current->IsJSGlobalProxy()) {
if (!name->IsSymbol()) { if (!name->IsSymbol()) {
Object* lookup_result = Heap::LookupSymbol(name); MaybeObject* maybe_lookup_result = Heap::LookupSymbol(name);
if (lookup_result->IsFailure()) { Object* lookup_result = NULL; // Initialization to please compiler.
if (!maybe_lookup_result->ToObject(&lookup_result)) {
set_failure(Failure::cast(lookup_result)); set_failure(Failure::cast(lookup_result));
return reg; return reg;
} else {
name = String::cast(lookup_result);
} }
name = String::cast(lookup_result);
} }
ASSERT(current->property_dictionary()->FindEntry(name) == ASSERT(current->property_dictionary()->FindEntry(name) ==
StringDictionary::kNotFound); StringDictionary::kNotFound);
@ -975,12 +979,12 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
// If we've skipped any global objects, it's not enough to verify // If we've skipped any global objects, it's not enough to verify
// that their maps haven't changed. We also need to check that the // that their maps haven't changed. We also need to check that the
// property cell for the property is still empty. // property cell for the property is still empty.
Object* result = GenerateCheckPropertyCells(masm(), MaybeObject* result = GenerateCheckPropertyCells(masm(),
object, object,
holder, holder,
name, name,
scratch1, scratch1,
miss); miss);
if (result->IsFailure()) set_failure(Failure::cast(result)); if (result->IsFailure()) set_failure(Failure::cast(result));
// Return the register containing the holder. // Return the register containing the holder.
@ -1035,7 +1039,6 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
Handle<AccessorInfo> callback_handle(callback); Handle<AccessorInfo> callback_handle(callback);
__ EnterInternalFrame(); __ EnterInternalFrame();
__ PushHandleScope(scratch2);
// Push the stack address where the list of arguments ends. // Push the stack address where the list of arguments ends.
__ mov(scratch2, esp); __ mov(scratch2, esp);
__ sub(Operand(scratch2), Immediate(2 * kPointerSize)); __ sub(Operand(scratch2), Immediate(2 * kPointerSize));
@ -1065,21 +1068,12 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
// already generated). Do not allow the assembler to perform a // already generated). Do not allow the assembler to perform a
// garbage collection but instead return the allocation failure // garbage collection but instead return the allocation failure
// object. // object.
Object* result = masm()->TryCallStub(&stub); Object* result = NULL; // Initialization to please compiler.
if (result->IsFailure()) { { MaybeObject* try_call_result = masm()->TryCallStub(&stub);
*failure = Failure::cast(result); if (!try_call_result->ToObject(&result)) {
return false; *failure = Failure::cast(result);
} return false;
}
// We need to avoid using eax since that now holds the result.
Register tmp = scratch2.is(eax) ? reg : scratch2;
// Emitting PopHandleScope may try to allocate. Do not allow the
// assembler to perform a garbage collection but instead return a
// failure object.
result = masm()->TryPopHandleScope(eax, tmp);
if (result->IsFailure()) {
*failure = Failure::cast(result);
return false;
} }
__ LeaveInternalFrame(); __ LeaveInternalFrame();
@ -1314,18 +1308,22 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
} }
Object* CallStubCompiler::GenerateMissBranch() { MaybeObject* CallStubCompiler::GenerateMissBranch() {
Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj =
StubCache::ComputeCallMiss(arguments().immediate(), kind_);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
__ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
return obj; return obj;
} }
Object* CallStubCompiler::CompileCallField(JSObject* object, MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField(
JSObject* holder, JSObject* object,
int index, JSObject* holder,
String* name) { int index,
String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
@ -1369,19 +1367,21 @@ Object* CallStubCompiler::CompileCallField(JSObject* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(FIELD, name); return GetCode(FIELD, name);
} }
Object* CallStubCompiler::CompileArrayPushCall(Object* object, MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
@ -1465,6 +1465,10 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object,
__ ret((argc + 1) * kPointerSize); __ ret((argc + 1) * kPointerSize);
__ bind(&attempt_to_grow_elements); __ bind(&attempt_to_grow_elements);
if (!FLAG_inline_new) {
__ jmp(&call_builtin);
}
ExternalReference new_space_allocation_top = ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address(); ExternalReference::new_space_allocation_top_address();
ExternalReference new_space_allocation_limit = ExternalReference new_space_allocation_limit =
@ -1515,19 +1519,21 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object,
} }
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileArrayPopCall(Object* object, MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
@ -1596,15 +1602,17 @@ Object* CallStubCompiler::CompileArrayPopCall(Object* object,
1); 1);
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileStringCharCodeAtCall( MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
@ -1666,19 +1674,22 @@ Object* CallStubCompiler::CompileStringCharCodeAtCall(
__ ret((argc + 1) * kPointerSize); __ ret((argc + 1) * kPointerSize);
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileStringCharAtCall(Object* object, MaybeObject* CallStubCompiler::CompileStringCharAtCall(
JSObject* holder, Object* object,
JSGlobalPropertyCell* cell, JSObject* holder,
JSFunction* function, JSGlobalPropertyCell* cell,
String* name) { JSFunction* function,
String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : function name // -- ecx : function name
// -- esp[0] : return address // -- esp[0] : return address
@ -1738,15 +1749,17 @@ Object* CallStubCompiler::CompileStringCharAtCall(Object* object,
__ ret((argc + 1) * kPointerSize); __ ret((argc + 1) * kPointerSize);
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileStringFromCharCodeCall( MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
@ -1811,19 +1824,21 @@ Object* CallStubCompiler::CompileStringFromCharCodeCall(
__ bind(&miss); __ bind(&miss);
// ecx: function name. // ecx: function name.
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
} }
Object* CallStubCompiler::CompileMathFloorCall(Object* object, MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
@ -1936,19 +1951,21 @@ Object* CallStubCompiler::CompileMathFloorCall(Object* object,
__ bind(&miss); __ bind(&miss);
// ecx: function name. // ecx: function name.
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
} }
Object* CallStubCompiler::CompileMathAbsCall(Object* object, MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
@ -2039,19 +2056,21 @@ Object* CallStubCompiler::CompileMathAbsCall(Object* object,
__ bind(&miss); __ bind(&miss);
// ecx: function name. // ecx: function name.
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
} }
Object* CallStubCompiler::CompileCallConstant(Object* object, MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder, JSObject* holder,
JSFunction* function, JSFunction* function,
String* name, String* name,
CheckType check) { CheckType check) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
@ -2063,8 +2082,10 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
SharedFunctionInfo* function_info = function->shared(); SharedFunctionInfo* function_info = function->shared();
if (function_info->HasCustomCallGenerator()) { if (function_info->HasCustomCallGenerator()) {
const int id = function_info->custom_call_generator_id(); const int id = function_info->custom_call_generator_id();
Object* result = CompileCustomCall( MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, NULL, function, name); id, object, holder, NULL, function, name);
Object* result;
if (!maybe_result->ToObject(&result)) return maybe_result;
// undefined means bail out to regular compiler. // undefined means bail out to regular compiler.
if (!result->IsUndefined()) return result; if (!result->IsUndefined()) return result;
} }
@ -2192,17 +2213,19 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
FreeSpaceForFastApiCall(masm(), eax); FreeSpaceForFastApiCall(masm(), eax);
} }
__ bind(&miss_in_smi_check); __ bind(&miss_in_smi_check);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
@ -2257,19 +2280,21 @@ Object* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Handle load cache miss. // Handle load cache miss.
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(INTERCEPTOR, name); return GetCode(INTERCEPTOR, name);
} }
Object* CallStubCompiler::CompileCallGlobal(JSObject* object, MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
GlobalObject* holder, GlobalObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- ecx : name // -- ecx : name
// -- esp[0] : return address // -- esp[0] : return address
@ -2281,8 +2306,10 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
SharedFunctionInfo* function_info = function->shared(); SharedFunctionInfo* function_info = function->shared();
if (function_info->HasCustomCallGenerator()) { if (function_info->HasCustomCallGenerator()) {
const int id = function_info->custom_call_generator_id(); const int id = function_info->custom_call_generator_id();
Object* result = CompileCustomCall( MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, cell, function, name); id, object, holder, cell, function, name);
Object* result;
if (!maybe_result->ToObject(&result)) return maybe_result;
// undefined means bail out to regular compiler. // undefined means bail out to regular compiler.
if (!result->IsUndefined()) return result; if (!result->IsUndefined()) return result;
} }
@ -2318,18 +2345,20 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
__ IncrementCounter(&Counters::call_global_inline_miss, 1); __ IncrementCounter(&Counters::call_global_inline_miss, 1);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(NORMAL, name); return GetCode(NORMAL, name);
} }
Object* StoreStubCompiler::CompileStoreField(JSObject* object, MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object,
int index, int index,
Map* transition, Map* transition,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : value // -- eax : value
// -- ecx : name // -- ecx : name
@ -2357,9 +2386,9 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
} }
Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
AccessorInfo* callback, AccessorInfo* callback,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : value // -- eax : value
// -- ecx : name // -- ecx : name
@ -2408,8 +2437,8 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
} }
Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : value // -- eax : value
// -- ecx : name // -- ecx : name
@ -2457,9 +2486,9 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
} }
Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : value // -- eax : value
// -- ecx : name // -- ecx : name
@ -2492,10 +2521,10 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
} }
Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
int index, int index,
Map* transition, Map* transition,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : value // -- eax : value
// -- ecx : key // -- ecx : key
@ -2529,9 +2558,9 @@ Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
} }
Object* LoadStubCompiler::CompileLoadNonexistent(String* name, MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
JSObject* object, JSObject* object,
JSObject* last) { JSObject* last) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver // -- eax : receiver
// -- ecx : name // -- ecx : name
@ -2553,11 +2582,11 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name,
// If the last object in the prototype chain is a global object, // If the last object in the prototype chain is a global object,
// check that the global property cell is empty. // check that the global property cell is empty.
if (last->IsGlobalObject()) { if (last->IsGlobalObject()) {
Object* cell = GenerateCheckPropertyCell(masm(), MaybeObject* cell = GenerateCheckPropertyCell(masm(),
GlobalObject::cast(last), GlobalObject::cast(last),
name, name,
edx, edx,
&miss); &miss);
if (cell->IsFailure()) { if (cell->IsFailure()) {
miss.Unuse(); miss.Unuse();
return cell; return cell;
@ -2577,10 +2606,10 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name,
} }
Object* LoadStubCompiler::CompileLoadField(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* holder, JSObject* holder,
int index, int index,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver // -- eax : receiver
// -- ecx : name // -- ecx : name
@ -2597,10 +2626,10 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object,
} }
Object* LoadStubCompiler::CompileLoadCallback(String* name, MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
JSObject* object, JSObject* object,
JSObject* holder, JSObject* holder,
AccessorInfo* callback) { AccessorInfo* callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver // -- eax : receiver
// -- ecx : name // -- ecx : name
@ -2624,10 +2653,10 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name,
} }
Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
JSObject* holder, JSObject* holder,
Object* value, Object* value,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver // -- eax : receiver
// -- ecx : name // -- ecx : name
@ -2644,9 +2673,9 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
} }
Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver // -- eax : receiver
// -- ecx : name // -- ecx : name
@ -2678,11 +2707,11 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
} }
Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
GlobalObject* holder, GlobalObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
String* name, String* name,
bool is_dont_delete) { bool is_dont_delete) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : receiver // -- eax : receiver
// -- ecx : name // -- ecx : name
@ -2727,10 +2756,10 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
} }
Object* KeyedLoadStubCompiler::CompileLoadField(String* name, MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder, JSObject* holder,
int index) { int index) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : key // -- eax : key
// -- edx : receiver // -- edx : receiver
@ -2755,10 +2784,11 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
} }
Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
JSObject* receiver, String* name,
JSObject* holder, JSObject* receiver,
AccessorInfo* callback) { JSObject* holder,
AccessorInfo* callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : key // -- eax : key
// -- edx : receiver // -- edx : receiver
@ -2790,10 +2820,10 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
} }
Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder, JSObject* holder,
Object* value) { Object* value) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : key // -- eax : key
// -- edx : receiver // -- edx : receiver
@ -2818,9 +2848,9 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
} }
Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : key // -- eax : key
// -- edx : receiver // -- edx : receiver
@ -2855,9 +2885,7 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
} }
MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : key // -- eax : key
// -- edx : receiver // -- edx : receiver
@ -2881,7 +2909,7 @@ Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
} }
Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : key // -- eax : key
// -- edx : receiver // -- edx : receiver
@ -2905,7 +2933,7 @@ Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
} }
Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : key // -- eax : key
// -- edx : receiver // -- edx : receiver
@ -2931,7 +2959,7 @@ Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
// Specialized stub for constructing objects from functions which only have only // Specialized stub for constructing objects from functions which only have only
// simple assignments of the form this.x = ...; in their body. // simple assignments of the form this.x = ...; in their body.
Object* ConstructStubCompiler::CompileConstructStub( MaybeObject* ConstructStubCompiler::CompileConstructStub(
SharedFunctionInfo* shared) { SharedFunctionInfo* shared) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : argc // -- eax : argc

330
deps/v8/src/ic.cc

@ -476,9 +476,9 @@ void CallICBase::ReceiverToObject(Handle<Object> object) {
} }
Object* CallICBase::LoadFunction(State state, MaybeObject* CallICBase::LoadFunction(State state,
Handle<Object> object, Handle<Object> object,
Handle<String> name) { Handle<String> name) {
// If the object is undefined or null it's illegal to try to get any // If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case. // of its properties; throw a TypeError in that case.
if (object->IsUndefined() || object->IsNull()) { if (object->IsUndefined() || object->IsNull()) {
@ -493,7 +493,11 @@ Object* CallICBase::LoadFunction(State state,
// the element if so. // the element if so.
uint32_t index; uint32_t index;
if (name->AsArrayIndex(&index)) { if (name->AsArrayIndex(&index)) {
Object* result = object->GetElement(index); Object* result;
{ MaybeObject* maybe_result = object->GetElement(index);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
if (result->IsJSFunction()) return result; if (result->IsJSFunction()) return result;
// Try to find a suitable function delegate for the object at hand. // Try to find a suitable function delegate for the object at hand.
@ -523,8 +527,11 @@ Object* CallICBase::LoadFunction(State state,
// Get the property. // Get the property.
PropertyAttributes attr; PropertyAttributes attr;
Object* result = object->GetProperty(*object, &lookup, *name, &attr); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result =
object->GetProperty(*object, &lookup, *name, &attr);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
if (lookup.type() == INTERCEPTOR) { if (lookup.type() == INTERCEPTOR) {
// If the object does not have the requested property, check which // If the object does not have the requested property, check which
// exception we need to throw. // exception we need to throw.
@ -556,8 +563,11 @@ Object* CallICBase::LoadFunction(State state,
// Try to find a suitable function delegate for the object at hand. // Try to find a suitable function delegate for the object at hand.
result = TryCallAsFunction(result); result = TryCallAsFunction(result);
return result->IsJSFunction() ? MaybeObject* answer = result;
result : TypeError("property_not_function", object, name); if (!result->IsJSFunction()) {
answer = TypeError("property_not_function", object, name);
}
return answer;
} }
@ -578,27 +588,27 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
// Compute the number of arguments. // Compute the number of arguments.
int argc = target()->arguments_count(); int argc = target()->arguments_count();
InLoopFlag in_loop = target()->ic_in_loop(); InLoopFlag in_loop = target()->ic_in_loop();
Object* code = NULL; MaybeObject* maybe_code = NULL;
Object* code;
if (state == UNINITIALIZED) { if (state == UNINITIALIZED) {
// This is the first time we execute this inline cache. // This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay // Set the target to the pre monomorphic stub to delay
// setting the monomorphic state. // setting the monomorphic state.
code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_);
} else if (state == MONOMORPHIC) { } else if (state == MONOMORPHIC) {
code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_);
} else { } else {
// Compute monomorphic stub. // Compute monomorphic stub.
switch (lookup->type()) { switch (lookup->type()) {
case FIELD: { case FIELD: {
int index = lookup->GetFieldIndex(); int index = lookup->GetFieldIndex();
code = StubCache::ComputeCallField(argc, maybe_code = StubCache::ComputeCallField(argc,
in_loop, in_loop,
kind_, kind_,
*name, *name,
*object, *object,
lookup->holder(), lookup->holder(),
index); index);
break; break;
} }
case CONSTANT_FUNCTION: { case CONSTANT_FUNCTION: {
@ -606,13 +616,13 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
// call; used for rewriting to monomorphic state and making sure // call; used for rewriting to monomorphic state and making sure
// that the code stub is in the stub cache. // that the code stub is in the stub cache.
JSFunction* function = lookup->GetConstantFunction(); JSFunction* function = lookup->GetConstantFunction();
code = StubCache::ComputeCallConstant(argc, maybe_code = StubCache::ComputeCallConstant(argc,
in_loop, in_loop,
kind_, kind_,
*name, *name,
*object, *object,
lookup->holder(), lookup->holder(),
function); function);
break; break;
} }
case NORMAL: { case NORMAL: {
@ -625,35 +635,35 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
if (!cell->value()->IsJSFunction()) return; if (!cell->value()->IsJSFunction()) return;
JSFunction* function = JSFunction::cast(cell->value()); JSFunction* function = JSFunction::cast(cell->value());
code = StubCache::ComputeCallGlobal(argc, maybe_code = StubCache::ComputeCallGlobal(argc,
in_loop, in_loop,
kind_, kind_,
*name, *name,
*receiver, *receiver,
global, global,
cell, cell,
function); function);
} else { } else {
// There is only one shared stub for calling normalized // There is only one shared stub for calling normalized
// properties. It does not traverse the prototype chain, so the // properties. It does not traverse the prototype chain, so the
// property must be found in the receiver for the stub to be // property must be found in the receiver for the stub to be
// applicable. // applicable.
if (lookup->holder() != *receiver) return; if (lookup->holder() != *receiver) return;
code = StubCache::ComputeCallNormal(argc, maybe_code = StubCache::ComputeCallNormal(argc,
in_loop, in_loop,
kind_, kind_,
*name, *name,
*receiver); *receiver);
} }
break; break;
} }
case INTERCEPTOR: { case INTERCEPTOR: {
ASSERT(HasInterceptorGetter(lookup->holder())); ASSERT(HasInterceptorGetter(lookup->holder()));
code = StubCache::ComputeCallInterceptor(argc, maybe_code = StubCache::ComputeCallInterceptor(argc,
kind_, kind_,
*name, *name,
*object, *object,
lookup->holder()); lookup->holder());
break; break;
} }
default: default:
@ -663,7 +673,7 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
// If we're unable to compute the stub (not enough memory left), we // If we're unable to compute the stub (not enough memory left), we
// simply avoid updating the caches. // simply avoid updating the caches.
if (code == NULL || code->IsFailure()) return; if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
// Patch the call site depending on the state of the cache. // Patch the call site depending on the state of the cache.
if (state == UNINITIALIZED || if (state == UNINITIALIZED ||
@ -688,9 +698,9 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
} }
Object* KeyedCallIC::LoadFunction(State state, MaybeObject* KeyedCallIC::LoadFunction(State state,
Handle<Object> object, Handle<Object> object,
Handle<Object> key) { Handle<Object> key) {
if (key->IsSymbol()) { if (key->IsSymbol()) {
return CallICBase::LoadFunction(state, object, Handle<String>::cast(key)); return CallICBase::LoadFunction(state, object, Handle<String>::cast(key));
} }
@ -706,9 +716,10 @@ Object* KeyedCallIC::LoadFunction(State state,
if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
int argc = target()->arguments_count(); int argc = target()->arguments_count();
InLoopFlag in_loop = target()->ic_in_loop(); InLoopFlag in_loop = target()->ic_in_loop();
Object* code = StubCache::ComputeCallMegamorphic( MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic(
argc, in_loop, Code::KEYED_CALL_IC); argc, in_loop, Code::KEYED_CALL_IC);
if (!code->IsFailure()) { Object* code;
if (maybe_code->ToObject(&code)) {
set_target(Code::cast(code)); set_target(Code::cast(code));
#ifdef DEBUG #ifdef DEBUG
TraceIC( TraceIC(
@ -716,11 +727,17 @@ Object* KeyedCallIC::LoadFunction(State state,
#endif #endif
} }
} }
Object* result = Runtime::GetObjectProperty(object, key); Object* result;
{ MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
if (result->IsJSFunction()) return result; if (result->IsJSFunction()) return result;
result = TryCallAsFunction(result); result = TryCallAsFunction(result);
return result->IsJSFunction() ? MaybeObject* answer = result;
result : TypeError("property_not_function", object, key); if (!result->IsJSFunction()) {
answer = TypeError("property_not_function", object, key);
}
return answer;
} }
@ -732,7 +749,9 @@ Object* KeyedCallIC::LoadFunction(State state,
#endif #endif
Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { MaybeObject* LoadIC::Load(State state,
Handle<Object> object,
Handle<String> name) {
// If the object is undefined or null it's illegal to try to get any // If the object is undefined or null it's illegal to try to get any
// of its properties; throw a TypeError in that case. // of its properties; throw a TypeError in that case.
if (object->IsUndefined() || object->IsNull()) { if (object->IsUndefined() || object->IsNull()) {
@ -874,8 +893,11 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) {
PropertyAttributes attr; PropertyAttributes attr;
if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
// Get the property. // Get the property.
Object* result = object->GetProperty(*object, &lookup, *name, &attr); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result =
object->GetProperty(*object, &lookup, *name, &attr);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
// If the property is not present, check if we need to throw an // If the property is not present, check if we need to throw an
// exception. // exception.
if (attr == ABSENT && IsContextual(object)) { if (attr == ABSENT && IsContextual(object)) {
@ -904,28 +926,29 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
// Compute the code stub for this load. // Compute the code stub for this load.
Object* code = NULL; MaybeObject* maybe_code = NULL;
Object* code;
if (state == UNINITIALIZED) { if (state == UNINITIALIZED) {
// This is the first time we execute this inline cache. // This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay // Set the target to the pre monomorphic stub to delay
// setting the monomorphic state. // setting the monomorphic state.
code = pre_monomorphic_stub(); maybe_code = pre_monomorphic_stub();
} else if (!lookup->IsProperty()) { } else if (!lookup->IsProperty()) {
// Nonexistent property. The result is undefined. // Nonexistent property. The result is undefined.
code = StubCache::ComputeLoadNonexistent(*name, *receiver); maybe_code = StubCache::ComputeLoadNonexistent(*name, *receiver);
} else { } else {
// Compute monomorphic stub. // Compute monomorphic stub.
switch (lookup->type()) { switch (lookup->type()) {
case FIELD: { case FIELD: {
code = StubCache::ComputeLoadField(*name, *receiver, maybe_code = StubCache::ComputeLoadField(*name, *receiver,
lookup->holder(), lookup->holder(),
lookup->GetFieldIndex()); lookup->GetFieldIndex());
break; break;
} }
case CONSTANT_FUNCTION: { case CONSTANT_FUNCTION: {
Object* constant = lookup->GetConstantFunction(); Object* constant = lookup->GetConstantFunction();
code = StubCache::ComputeLoadConstant(*name, *receiver, maybe_code = StubCache::ComputeLoadConstant(*name, *receiver,
lookup->holder(), constant); lookup->holder(), constant);
break; break;
} }
case NORMAL: { case NORMAL: {
@ -933,18 +956,18 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
GlobalObject* global = GlobalObject::cast(lookup->holder()); GlobalObject* global = GlobalObject::cast(lookup->holder());
JSGlobalPropertyCell* cell = JSGlobalPropertyCell* cell =
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
code = StubCache::ComputeLoadGlobal(*name, maybe_code = StubCache::ComputeLoadGlobal(*name,
*receiver, *receiver,
global, global,
cell, cell,
lookup->IsDontDelete()); lookup->IsDontDelete());
} else { } else {
// There is only one shared stub for loading normalized // There is only one shared stub for loading normalized
// properties. It does not traverse the prototype chain, so the // properties. It does not traverse the prototype chain, so the
// property must be found in the receiver for the stub to be // property must be found in the receiver for the stub to be
// applicable. // applicable.
if (lookup->holder() != *receiver) return; if (lookup->holder() != *receiver) return;
code = StubCache::ComputeLoadNormal(); maybe_code = StubCache::ComputeLoadNormal();
} }
break; break;
} }
@ -953,14 +976,14 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
AccessorInfo* callback = AccessorInfo* callback =
AccessorInfo::cast(lookup->GetCallbackObject()); AccessorInfo::cast(lookup->GetCallbackObject());
if (v8::ToCData<Address>(callback->getter()) == 0) return; if (v8::ToCData<Address>(callback->getter()) == 0) return;
code = StubCache::ComputeLoadCallback(*name, *receiver, maybe_code = StubCache::ComputeLoadCallback(*name, *receiver,
lookup->holder(), callback); lookup->holder(), callback);
break; break;
} }
case INTERCEPTOR: { case INTERCEPTOR: {
ASSERT(HasInterceptorGetter(lookup->holder())); ASSERT(HasInterceptorGetter(lookup->holder()));
code = StubCache::ComputeLoadInterceptor(*name, *receiver, maybe_code = StubCache::ComputeLoadInterceptor(*name, *receiver,
lookup->holder()); lookup->holder());
break; break;
} }
default: default:
@ -970,7 +993,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
// If we're unable to compute the stub (not enough memory left), we // If we're unable to compute the stub (not enough memory left), we
// simply avoid updating the caches. // simply avoid updating the caches.
if (code == NULL || code->IsFailure()) return; if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
// Patch the call site depending on the state of the cache. // Patch the call site depending on the state of the cache.
if (state == UNINITIALIZED || state == PREMONOMORPHIC || if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
@ -993,9 +1016,9 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
} }
Object* KeyedLoadIC::Load(State state, MaybeObject* KeyedLoadIC::Load(State state,
Handle<Object> object, Handle<Object> object,
Handle<Object> key) { Handle<Object> key) {
if (key->IsSymbol()) { if (key->IsSymbol()) {
Handle<String> name = Handle<String>::cast(key); Handle<String> name = Handle<String>::cast(key);
@ -1010,8 +1033,10 @@ Object* KeyedLoadIC::Load(State state,
if (object->IsString() && name->Equals(Heap::length_symbol())) { if (object->IsString() && name->Equals(Heap::length_symbol())) {
Handle<String> string = Handle<String>::cast(object); Handle<String> string = Handle<String>::cast(object);
Object* code = NULL; Object* code = NULL;
code = StubCache::ComputeKeyedLoadStringLength(*name, *string); { MaybeObject* maybe_code =
if (code->IsFailure()) return code; StubCache::ComputeKeyedLoadStringLength(*name, *string);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
set_target(Code::cast(code)); set_target(Code::cast(code));
#ifdef DEBUG #ifdef DEBUG
TraceIC("KeyedLoadIC", name, state, target()); TraceIC("KeyedLoadIC", name, state, target());
@ -1022,8 +1047,11 @@ Object* KeyedLoadIC::Load(State state,
// Use specialized code for getting the length of arrays. // Use specialized code for getting the length of arrays.
if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
Handle<JSArray> array = Handle<JSArray>::cast(object); Handle<JSArray> array = Handle<JSArray>::cast(object);
Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array); Object* code;
if (code->IsFailure()) return code; { MaybeObject* maybe_code =
StubCache::ComputeKeyedLoadArrayLength(*name, *array);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
set_target(Code::cast(code)); set_target(Code::cast(code));
#ifdef DEBUG #ifdef DEBUG
TraceIC("KeyedLoadIC", name, state, target()); TraceIC("KeyedLoadIC", name, state, target());
@ -1035,9 +1063,11 @@ Object* KeyedLoadIC::Load(State state,
if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
JSFunction::cast(*object)->should_have_prototype()) { JSFunction::cast(*object)->should_have_prototype()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(object); Handle<JSFunction> function = Handle<JSFunction>::cast(object);
Object* code = Object* code;
StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); { MaybeObject* maybe_code =
if (code->IsFailure()) return code; StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
set_target(Code::cast(code)); set_target(Code::cast(code));
#ifdef DEBUG #ifdef DEBUG
TraceIC("KeyedLoadIC", name, state, target()); TraceIC("KeyedLoadIC", name, state, target());
@ -1074,8 +1104,11 @@ Object* KeyedLoadIC::Load(State state,
PropertyAttributes attr; PropertyAttributes attr;
if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
// Get the property. // Get the property.
Object* result = object->GetProperty(*object, &lookup, *name, &attr); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result =
object->GetProperty(*object, &lookup, *name, &attr);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
// If the property is not present, check if we need to throw an // If the property is not present, check if we need to throw an
// exception. // exception.
if (attr == ABSENT && IsContextual(object)) { if (attr == ABSENT && IsContextual(object)) {
@ -1133,26 +1166,29 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
// Compute the code stub for this load. // Compute the code stub for this load.
Object* code = NULL; MaybeObject* maybe_code = NULL;
Object* code;
if (state == UNINITIALIZED) { if (state == UNINITIALIZED) {
// This is the first time we execute this inline cache. // This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay // Set the target to the pre monomorphic stub to delay
// setting the monomorphic state. // setting the monomorphic state.
code = pre_monomorphic_stub(); maybe_code = pre_monomorphic_stub();
} else { } else {
// Compute a monomorphic stub. // Compute a monomorphic stub.
switch (lookup->type()) { switch (lookup->type()) {
case FIELD: { case FIELD: {
code = StubCache::ComputeKeyedLoadField(*name, *receiver, maybe_code = StubCache::ComputeKeyedLoadField(*name, *receiver,
lookup->holder(), lookup->holder(),
lookup->GetFieldIndex()); lookup->GetFieldIndex());
break; break;
} }
case CONSTANT_FUNCTION: { case CONSTANT_FUNCTION: {
Object* constant = lookup->GetConstantFunction(); Object* constant = lookup->GetConstantFunction();
code = StubCache::ComputeKeyedLoadConstant(*name, *receiver, maybe_code = StubCache::ComputeKeyedLoadConstant(*name,
lookup->holder(), constant); *receiver,
lookup->holder(),
constant);
break; break;
} }
case CALLBACKS: { case CALLBACKS: {
@ -1160,20 +1196,22 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
AccessorInfo* callback = AccessorInfo* callback =
AccessorInfo::cast(lookup->GetCallbackObject()); AccessorInfo::cast(lookup->GetCallbackObject());
if (v8::ToCData<Address>(callback->getter()) == 0) return; if (v8::ToCData<Address>(callback->getter()) == 0) return;
code = StubCache::ComputeKeyedLoadCallback(*name, *receiver, maybe_code = StubCache::ComputeKeyedLoadCallback(*name,
lookup->holder(), callback); *receiver,
lookup->holder(),
callback);
break; break;
} }
case INTERCEPTOR: { case INTERCEPTOR: {
ASSERT(HasInterceptorGetter(lookup->holder())); ASSERT(HasInterceptorGetter(lookup->holder()));
code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver, maybe_code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver,
lookup->holder()); lookup->holder());
break; break;
} }
default: { default: {
// Always rewrite to the generic case so that we do not // Always rewrite to the generic case so that we do not
// repeatedly try to rewrite. // repeatedly try to rewrite.
code = generic_stub(); maybe_code = generic_stub();
break; break;
} }
} }
@ -1181,7 +1219,7 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
// If we're unable to compute the stub (not enough memory left), we // If we're unable to compute the stub (not enough memory left), we
// simply avoid updating the caches. // simply avoid updating the caches.
if (code == NULL || code->IsFailure()) return; if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
// Patch the call site depending on the state of the cache. Make // Patch the call site depending on the state of the cache. Make
// sure to always rewrite from monomorphic to megamorphic. // sure to always rewrite from monomorphic to megamorphic.
@ -1229,10 +1267,10 @@ static bool LookupForWrite(JSObject* object,
} }
Object* StoreIC::Store(State state, MaybeObject* StoreIC::Store(State state,
Handle<Object> object, Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> value) { Handle<Object> value) {
// If the object is undefined or null it's illegal to try to set any // If the object is undefined or null it's illegal to try to set any
// properties on it; throw a TypeError in that case. // properties on it; throw a TypeError in that case.
if (object->IsUndefined() || object->IsNull()) { if (object->IsUndefined() || object->IsNull()) {
@ -1345,11 +1383,12 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
// Compute the code stub for this store; used for rewriting to // Compute the code stub for this store; used for rewriting to
// monomorphic state and making sure that the code stub is in the // monomorphic state and making sure that the code stub is in the
// stub cache. // stub cache.
MaybeObject* maybe_code = NULL;
Object* code = NULL; Object* code = NULL;
switch (type) { switch (type) {
case FIELD: { case FIELD: {
code = StubCache::ComputeStoreField(*name, *receiver, maybe_code = StubCache::ComputeStoreField(*name, *receiver,
lookup->GetFieldIndex()); lookup->GetFieldIndex());
break; break;
} }
case MAP_TRANSITION: { case MAP_TRANSITION: {
@ -1358,7 +1397,8 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
ASSERT(type == MAP_TRANSITION); ASSERT(type == MAP_TRANSITION);
Handle<Map> transition(lookup->GetTransitionMap()); Handle<Map> transition(lookup->GetTransitionMap());
int index = transition->PropertyIndexFor(*name); int index = transition->PropertyIndexFor(*name);
code = StubCache::ComputeStoreField(*name, *receiver, index, *transition); maybe_code = StubCache::ComputeStoreField(*name, *receiver,
index, *transition);
break; break;
} }
case NORMAL: { case NORMAL: {
@ -1369,10 +1409,10 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
JSGlobalPropertyCell* cell = JSGlobalPropertyCell* cell =
JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
code = StubCache::ComputeStoreGlobal(*name, *global, cell); maybe_code = StubCache::ComputeStoreGlobal(*name, *global, cell);
} else { } else {
if (lookup->holder() != *receiver) return; if (lookup->holder() != *receiver) return;
code = StubCache::ComputeStoreNormal(); maybe_code = StubCache::ComputeStoreNormal();
} }
break; break;
} }
@ -1380,12 +1420,12 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
if (v8::ToCData<Address>(callback->setter()) == 0) return; if (v8::ToCData<Address>(callback->setter()) == 0) return;
code = StubCache::ComputeStoreCallback(*name, *receiver, callback); maybe_code = StubCache::ComputeStoreCallback(*name, *receiver, callback);
break; break;
} }
case INTERCEPTOR: { case INTERCEPTOR: {
ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
code = StubCache::ComputeStoreInterceptor(*name, *receiver); maybe_code = StubCache::ComputeStoreInterceptor(*name, *receiver);
break; break;
} }
default: default:
@ -1394,7 +1434,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
// If we're unable to compute the stub (not enough memory left), we // If we're unable to compute the stub (not enough memory left), we
// simply avoid updating the caches. // simply avoid updating the caches.
if (code == NULL || code->IsFailure()) return; if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
// Patch the call site depending on the state of the cache. // Patch the call site depending on the state of the cache.
if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
@ -1413,10 +1453,10 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
} }
Object* KeyedStoreIC::Store(State state, MaybeObject* KeyedStoreIC::Store(State state,
Handle<Object> object, Handle<Object> object,
Handle<Object> key, Handle<Object> key,
Handle<Object> value) { Handle<Object> value) {
if (key->IsSymbol()) { if (key->IsSymbol()) {
Handle<String> name = Handle<String>::cast(key); Handle<String> name = Handle<String>::cast(key);
@ -1496,12 +1536,13 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
// Compute the code stub for this store; used for rewriting to // Compute the code stub for this store; used for rewriting to
// monomorphic state and making sure that the code stub is in the // monomorphic state and making sure that the code stub is in the
// stub cache. // stub cache.
MaybeObject* maybe_code = NULL;
Object* code = NULL; Object* code = NULL;
switch (type) { switch (type) {
case FIELD: { case FIELD: {
code = StubCache::ComputeKeyedStoreField(*name, *receiver, maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
lookup->GetFieldIndex()); lookup->GetFieldIndex());
break; break;
} }
case MAP_TRANSITION: { case MAP_TRANSITION: {
@ -1510,8 +1551,8 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
ASSERT(type == MAP_TRANSITION); ASSERT(type == MAP_TRANSITION);
Handle<Map> transition(lookup->GetTransitionMap()); Handle<Map> transition(lookup->GetTransitionMap());
int index = transition->PropertyIndexFor(*name); int index = transition->PropertyIndexFor(*name);
code = StubCache::ComputeKeyedStoreField(*name, *receiver, maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
index, *transition); index, *transition);
break; break;
} }
// fall through. // fall through.
@ -1519,14 +1560,14 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
default: { default: {
// Always rewrite to the generic case so that we do not // Always rewrite to the generic case so that we do not
// repeatedly try to rewrite. // repeatedly try to rewrite.
code = generic_stub(); maybe_code = generic_stub();
break; break;
} }
} }
// If we're unable to compute the stub (not enough memory left), we // If we're unable to compute the stub (not enough memory left), we
// simply avoid updating the caches. // simply avoid updating the caches.
if (code == NULL || code->IsFailure()) return; if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
// Patch the call site depending on the state of the cache. Make // Patch the call site depending on the state of the cache. Make
// sure to always rewrite from monomorphic to megamorphic. // sure to always rewrite from monomorphic to megamorphic.
@ -1562,13 +1603,16 @@ static JSFunction* CompileFunction(JSFunction* function,
// Used from ic-<arch>.cc. // Used from ic-<arch>.cc.
Object* CallIC_Miss(Arguments args) { MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
CallIC ic; CallIC ic;
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Object* result = Object* result;
ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); { MaybeObject* maybe_result =
ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
// The first time the inline cache is updated may be the first time the // The first time the inline cache is updated may be the first time the
// function it references gets called. If the function was lazily compiled // function it references gets called. If the function was lazily compiled
@ -1585,13 +1629,16 @@ Object* CallIC_Miss(Arguments args) {
// Used from ic-<arch>.cc. // Used from ic-<arch>.cc.
Object* KeyedCallIC_Miss(Arguments args) { MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
KeyedCallIC ic; KeyedCallIC ic;
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
Object* result = Object* result;
{ MaybeObject* maybe_result =
ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
return result; return result;
@ -1601,7 +1648,7 @@ Object* KeyedCallIC_Miss(Arguments args) {
// Used from ic-<arch>.cc. // Used from ic-<arch>.cc.
Object* LoadIC_Miss(Arguments args) { MUST_USE_RESULT MaybeObject* LoadIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
LoadIC ic; LoadIC ic;
@ -1611,7 +1658,7 @@ Object* LoadIC_Miss(Arguments args) {
// Used from ic-<arch>.cc // Used from ic-<arch>.cc
Object* KeyedLoadIC_Miss(Arguments args) { MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
KeyedLoadIC ic; KeyedLoadIC ic;
@ -1621,7 +1668,7 @@ Object* KeyedLoadIC_Miss(Arguments args) {
// Used from ic-<arch>.cc. // Used from ic-<arch>.cc.
Object* StoreIC_Miss(Arguments args) { MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 3); ASSERT(args.length() == 3);
StoreIC ic; StoreIC ic;
@ -1631,15 +1678,20 @@ Object* StoreIC_Miss(Arguments args) {
} }
Object* StoreIC_ArrayLength(Arguments args) { MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) {
NoHandleAllocation nha; NoHandleAllocation nha;
ASSERT(args.length() == 2); ASSERT(args.length() == 2);
JSObject* receiver = JSObject::cast(args[0]); JSObject* receiver = JSObject::cast(args[0]);
Object* len = args[1]; Object* len = args[1];
Object* result = receiver->SetElementsLength(len); // The generated code should filter out non-Smis before we get here.
if (result->IsFailure()) return result; ASSERT(len->IsSmi());
Object* result;
{ MaybeObject* maybe_result = receiver->SetElementsLength(len);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
return len; return len;
} }
@ -1647,7 +1699,7 @@ Object* StoreIC_ArrayLength(Arguments args) {
// Extend storage is called in a store inline cache when // Extend storage is called in a store inline cache when
// it is necessary to extend the properties array of a // it is necessary to extend the properties array of a
// JSObject. // JSObject.
Object* SharedStoreIC_ExtendStorage(Arguments args) { MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 3); ASSERT(args.length() == 3);
@ -1664,8 +1716,10 @@ Object* SharedStoreIC_ExtendStorage(Arguments args) {
FixedArray* old_storage = object->properties(); FixedArray* old_storage = object->properties();
int new_unused = transition->unused_property_fields(); int new_unused = transition->unused_property_fields();
int new_size = old_storage->length() + new_unused + 1; int new_size = old_storage->length() + new_unused + 1;
Object* result = old_storage->CopySize(new_size); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result = old_storage->CopySize(new_size);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
FixedArray* new_storage = FixedArray::cast(result); FixedArray* new_storage = FixedArray::cast(result);
new_storage->set(old_storage->length(), value); new_storage->set(old_storage->length(), value);
@ -1679,7 +1733,7 @@ Object* SharedStoreIC_ExtendStorage(Arguments args) {
// Used from ic-<arch>.cc. // Used from ic-<arch>.cc.
Object* KeyedStoreIC_Miss(Arguments args) { MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) {
NoHandleAllocation na; NoHandleAllocation na;
ASSERT(args.length() == 3); ASSERT(args.length() == 3);
KeyedStoreIC ic; KeyedStoreIC ic;
@ -1744,7 +1798,7 @@ BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Object* left,
Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info); Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info);
Object* BinaryOp_Patch(Arguments args) { MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) {
ASSERT(args.length() == 5); ASSERT(args.length() == 5);
Handle<Object> left = args.at<Object>(0); Handle<Object> left = args.at<Object>(0);

32
deps/v8/src/ic.h

@ -191,7 +191,9 @@ class CallICBase: public IC {
explicit CallICBase(Code::Kind kind) : IC(EXTRA_CALL_FRAME), kind_(kind) {} explicit CallICBase(Code::Kind kind) : IC(EXTRA_CALL_FRAME), kind_(kind) {}
public: public:
Object* LoadFunction(State state, Handle<Object> object, Handle<String> name); MUST_USE_RESULT MaybeObject* LoadFunction(State state,
Handle<Object> object,
Handle<String> name);
protected: protected:
Code::Kind kind_; Code::Kind kind_;
@ -235,7 +237,9 @@ class KeyedCallIC: public CallICBase {
ASSERT(target()->is_keyed_call_stub()); ASSERT(target()->is_keyed_call_stub());
} }
Object* LoadFunction(State state, Handle<Object> object, Handle<Object> key); MUST_USE_RESULT MaybeObject* LoadFunction(State state,
Handle<Object> object,
Handle<Object> key);
// Code generator routines. // Code generator routines.
static void GenerateInitialize(MacroAssembler* masm, int argc) { static void GenerateInitialize(MacroAssembler* masm, int argc) {
@ -251,7 +255,9 @@ class LoadIC: public IC {
public: public:
LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); } LoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_load_stub()); }
Object* Load(State state, Handle<Object> object, Handle<String> name); MUST_USE_RESULT MaybeObject* Load(State state,
Handle<Object> object,
Handle<String> name);
// Code generator routines. // Code generator routines.
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
@ -311,7 +317,9 @@ class KeyedLoadIC: public IC {
public: public:
KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); } KeyedLoadIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_keyed_load_stub()); }
Object* Load(State state, Handle<Object> object, Handle<Object> key); MUST_USE_RESULT MaybeObject* Load(State state,
Handle<Object> object,
Handle<Object> key);
// Code generator routines. // Code generator routines.
static void GenerateMiss(MacroAssembler* masm); static void GenerateMiss(MacroAssembler* masm);
@ -384,10 +392,10 @@ class StoreIC: public IC {
public: public:
StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); } StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); }
Object* Store(State state, MUST_USE_RESULT MaybeObject* Store(State state,
Handle<Object> object, Handle<Object> object,
Handle<String> name, Handle<String> name,
Handle<Object> value); Handle<Object> value);
// Code generators for stub routines. Only called once at startup. // Code generators for stub routines. Only called once at startup.
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
@ -433,10 +441,10 @@ class KeyedStoreIC: public IC {
public: public:
KeyedStoreIC() : IC(NO_EXTRA_FRAME) { } KeyedStoreIC() : IC(NO_EXTRA_FRAME) { }
Object* Store(State state, MUST_USE_RESULT MaybeObject* Store(State state,
Handle<Object> object, Handle<Object> object,
Handle<Object> name, Handle<Object> name,
Handle<Object> value); Handle<Object> value);
// Code generators for stub routines. Only called once at startup. // Code generators for stub routines. Only called once at startup.
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }

43
deps/v8/src/liveedit.cc

@ -463,7 +463,7 @@ class JSArrayBasedStruct {
SetElement(array_, field_position, Handle<Smi>(Smi::FromInt(value))); SetElement(array_, field_position, Handle<Smi>(Smi::FromInt(value)));
} }
Object* GetField(int field_position) { Object* GetField(int field_position) {
return array_->GetElement(field_position); return array_->GetElementNoExceptionThrown(field_position);
} }
int GetSmiValueField(int field_position) { int GetSmiValueField(int field_position) {
Object* res = GetField(field_position); Object* res = GetField(field_position);
@ -550,7 +550,7 @@ class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
public: public:
static bool IsInstance(Handle<JSArray> array) { static bool IsInstance(Handle<JSArray> array) {
return array->length() == Smi::FromInt(kSize_) && return array->length() == Smi::FromInt(kSize_) &&
array->GetElement(kSharedInfoOffset_)->IsJSValue(); array->GetElementNoExceptionThrown(kSharedInfoOffset_)->IsJSValue();
} }
explicit SharedInfoWrapper(Handle<JSArray> array) explicit SharedInfoWrapper(Handle<JSArray> array)
@ -605,16 +605,18 @@ class FunctionInfoListener {
void FunctionDone() { void FunctionDone() {
HandleScope scope; HandleScope scope;
FunctionInfoWrapper info = Object* element =
FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_)); result_->GetElementNoExceptionThrown(current_parent_index_);
FunctionInfoWrapper info = FunctionInfoWrapper::cast(element);
current_parent_index_ = info.GetParentIndex(); current_parent_index_ = info.GetParentIndex();
} }
// Saves only function code, because for a script function we // Saves only function code, because for a script function we
// may never create a SharedFunctionInfo object. // may never create a SharedFunctionInfo object.
void FunctionCode(Handle<Code> function_code) { void FunctionCode(Handle<Code> function_code) {
FunctionInfoWrapper info = Object* element =
FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_)); result_->GetElementNoExceptionThrown(current_parent_index_);
FunctionInfoWrapper info = FunctionInfoWrapper::cast(element);
info.SetFunctionCode(function_code, Handle<Object>(Heap::null_value())); info.SetFunctionCode(function_code, Handle<Object>(Heap::null_value()));
} }
@ -624,8 +626,9 @@ class FunctionInfoListener {
if (!shared->IsSharedFunctionInfo()) { if (!shared->IsSharedFunctionInfo()) {
return; return;
} }
FunctionInfoWrapper info = Object* element =
FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_)); result_->GetElementNoExceptionThrown(current_parent_index_);
FunctionInfoWrapper info = FunctionInfoWrapper::cast(element);
info.SetFunctionCode(Handle<Code>(shared->code()), info.SetFunctionCode(Handle<Code>(shared->code()),
Handle<Object>(shared->scope_info())); Handle<Object>(shared->scope_info()));
info.SetSharedFunctionInfo(shared); info.SetSharedFunctionInfo(shared);
@ -721,7 +724,7 @@ void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) {
int len = Smi::cast(array->length())->value(); int len = Smi::cast(array->length())->value();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Handle<SharedFunctionInfo> info( Handle<SharedFunctionInfo> info(
SharedFunctionInfo::cast(array->GetElement(i))); SharedFunctionInfo::cast(array->GetElementNoExceptionThrown(i)));
SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(); SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create();
Handle<String> name_handle(String::cast(info->name())); Handle<String> name_handle(String::cast(info->name()));
info_wrapper.SetProperties(name_handle, info->start_position(), info_wrapper.SetProperties(name_handle, info->start_position(),
@ -825,8 +828,9 @@ static bool IsJSFunctionCode(Code* code) {
} }
Object* LiveEdit::ReplaceFunctionCode(Handle<JSArray> new_compile_info_array, MaybeObject* LiveEdit::ReplaceFunctionCode(
Handle<JSArray> shared_info_array) { Handle<JSArray> new_compile_info_array,
Handle<JSArray> shared_info_array) {
HandleScope scope; HandleScope scope;
if (!SharedInfoWrapper::IsInstance(shared_info_array)) { if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
@ -889,17 +893,17 @@ static int TranslatePosition(int original_position,
int array_len = Smi::cast(position_change_array->length())->value(); int array_len = Smi::cast(position_change_array->length())->value();
// TODO(635): binary search may be used here // TODO(635): binary search may be used here
for (int i = 0; i < array_len; i += 3) { for (int i = 0; i < array_len; i += 3) {
int chunk_start = Object* element = position_change_array->GetElementNoExceptionThrown(i);
Smi::cast(position_change_array->GetElement(i))->value(); int chunk_start = Smi::cast(element)->value();
if (original_position < chunk_start) { if (original_position < chunk_start) {
break; break;
} }
int chunk_end = element = position_change_array->GetElementNoExceptionThrown(i + 1);
Smi::cast(position_change_array->GetElement(i + 1))->value(); int chunk_end = Smi::cast(element)->value();
// Position mustn't be inside a chunk. // Position mustn't be inside a chunk.
ASSERT(original_position >= chunk_end); ASSERT(original_position >= chunk_end);
int chunk_changed_end = element = position_change_array->GetElementNoExceptionThrown(i + 2);
Smi::cast(position_change_array->GetElement(i + 2))->value(); int chunk_changed_end = Smi::cast(element)->value();
position_diff = chunk_changed_end - chunk_end; position_diff = chunk_changed_end - chunk_end;
} }
@ -1024,7 +1028,7 @@ static Handle<Code> PatchPositionsInCode(Handle<Code> code,
} }
Object* LiveEdit::PatchFunctionPositions( MaybeObject* LiveEdit::PatchFunctionPositions(
Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) { Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array) {
if (!SharedInfoWrapper::IsInstance(shared_info_array)) { if (!SharedInfoWrapper::IsInstance(shared_info_array)) {
@ -1138,7 +1142,8 @@ static bool CheckActivation(Handle<JSArray> shared_info_array,
} }
int len = Smi::cast(shared_info_array->length())->value(); int len = Smi::cast(shared_info_array->length())->value();
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
JSValue* wrapper = JSValue::cast(shared_info_array->GetElement(i)); JSValue* wrapper =
JSValue::cast(shared_info_array->GetElementNoExceptionThrown(i));
Handle<SharedFunctionInfo> shared( Handle<SharedFunctionInfo> shared(
SharedFunctionInfo::cast(wrapper->value())); SharedFunctionInfo::cast(wrapper->value()));

7
deps/v8/src/liveedit.h

@ -83,14 +83,15 @@ class LiveEdit : AllStatic {
static void WrapSharedFunctionInfos(Handle<JSArray> array); static void WrapSharedFunctionInfos(Handle<JSArray> array);
static Object* ReplaceFunctionCode(Handle<JSArray> new_compile_info_array, MUST_USE_RESULT static MaybeObject* ReplaceFunctionCode(
Handle<JSArray> shared_info_array); Handle<JSArray> new_compile_info_array,
Handle<JSArray> shared_info_array);
// Updates script field in FunctionSharedInfo. // Updates script field in FunctionSharedInfo.
static void SetFunctionScript(Handle<JSValue> function_wrapper, static void SetFunctionScript(Handle<JSValue> function_wrapper,
Handle<Object> script_handle); Handle<Object> script_handle);
static Object* PatchFunctionPositions( MUST_USE_RESULT static MaybeObject* PatchFunctionPositions(
Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array); Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array);
// For a script updates its source field. If old_script_name is provided // For a script updates its source field. If old_script_name is provided

13
deps/v8/src/log.cc

@ -559,7 +559,12 @@ void Logger::LogRuntime(Vector<const char> format, JSArray* args) {
if (c == '%' && i <= format.length() - 2) { if (c == '%' && i <= format.length() - 2) {
i++; i++;
ASSERT('0' <= format[i] && format[i] <= '9'); ASSERT('0' <= format[i] && format[i] <= '9');
Object* obj = args->GetElement(format[i] - '0'); MaybeObject* maybe = args->GetElement(format[i] - '0');
Object* obj;
if (!maybe->ToObject(&obj)) {
msg.Append("<exception>");
continue;
}
i++; i++;
switch (format[i]) { switch (format[i]) {
case 's': case 's':
@ -1378,8 +1383,10 @@ void Logger::LogCodeInfo() {
void Logger::LowLevelCodeCreateEvent(Code* code, LogMessageBuilder* msg) { void Logger::LowLevelCodeCreateEvent(Code* code, LogMessageBuilder* msg) {
if (!FLAG_ll_prof || Log::output_code_handle_ == NULL) return; if (!FLAG_ll_prof || Log::output_code_handle_ == NULL) return;
int pos = static_cast<int>(ftell(Log::output_code_handle_)); int pos = static_cast<int>(ftell(Log::output_code_handle_));
fwrite(code->instruction_start(), 1, code->instruction_size(), size_t rv = fwrite(code->instruction_start(), 1, code->instruction_size(),
Log::output_code_handle_); Log::output_code_handle_);
ASSERT(static_cast<size_t>(code->instruction_size()) == rv);
USE(rv);
msg->Append(",%d", pos); msg->Append(",%d", pos);
} }

48
deps/v8/src/mark-compact.cc

@ -1264,8 +1264,9 @@ void EncodeFreeRegion(Address free_start, int free_size) {
// Try to promote all objects in new space. Heap numbers and sequential // Try to promote all objects in new space. Heap numbers and sequential
// strings are promoted to the code space, large objects to large object space, // strings are promoted to the code space, large objects to large object space,
// and all others to the old space. // and all others to the old space.
inline Object* MCAllocateFromNewSpace(HeapObject* object, int object_size) { inline MaybeObject* MCAllocateFromNewSpace(HeapObject* object,
Object* forwarded; int object_size) {
MaybeObject* forwarded;
if (object_size > Heap::MaxObjectSizeInPagedSpace()) { if (object_size > Heap::MaxObjectSizeInPagedSpace()) {
forwarded = Failure::Exception(); forwarded = Failure::Exception();
} else { } else {
@ -1274,36 +1275,45 @@ inline Object* MCAllocateFromNewSpace(HeapObject* object, int object_size) {
target_space == Heap::old_data_space()); target_space == Heap::old_data_space());
forwarded = target_space->MCAllocateRaw(object_size); forwarded = target_space->MCAllocateRaw(object_size);
} }
if (forwarded->IsFailure()) { Object* result;
forwarded = Heap::new_space()->MCAllocateRaw(object_size); if (!forwarded->ToObject(&result)) {
result = Heap::new_space()->MCAllocateRaw(object_size)->ToObjectUnchecked();
} }
return forwarded; return result;
} }
// Allocation functions for the paged spaces call the space's MCAllocateRaw. // Allocation functions for the paged spaces call the space's MCAllocateRaw.
inline Object* MCAllocateFromOldPointerSpace(HeapObject* ignore, MUST_USE_RESULT inline MaybeObject* MCAllocateFromOldPointerSpace(
int object_size) { HeapObject* ignore,
int object_size) {
return Heap::old_pointer_space()->MCAllocateRaw(object_size); return Heap::old_pointer_space()->MCAllocateRaw(object_size);
} }
inline Object* MCAllocateFromOldDataSpace(HeapObject* ignore, int object_size) { MUST_USE_RESULT inline MaybeObject* MCAllocateFromOldDataSpace(
HeapObject* ignore,
int object_size) {
return Heap::old_data_space()->MCAllocateRaw(object_size); return Heap::old_data_space()->MCAllocateRaw(object_size);
} }
inline Object* MCAllocateFromCodeSpace(HeapObject* ignore, int object_size) { MUST_USE_RESULT inline MaybeObject* MCAllocateFromCodeSpace(
HeapObject* ignore,
int object_size) {
return Heap::code_space()->MCAllocateRaw(object_size); return Heap::code_space()->MCAllocateRaw(object_size);
} }
inline Object* MCAllocateFromMapSpace(HeapObject* ignore, int object_size) { MUST_USE_RESULT inline MaybeObject* MCAllocateFromMapSpace(
HeapObject* ignore,
int object_size) {
return Heap::map_space()->MCAllocateRaw(object_size); return Heap::map_space()->MCAllocateRaw(object_size);
} }
inline Object* MCAllocateFromCellSpace(HeapObject* ignore, int object_size) { MUST_USE_RESULT inline MaybeObject* MCAllocateFromCellSpace(
HeapObject* ignore, int object_size) {
return Heap::cell_space()->MCAllocateRaw(object_size); return Heap::cell_space()->MCAllocateRaw(object_size);
} }
@ -1380,9 +1390,8 @@ inline void EncodeForwardingAddressesInRange(Address start,
MarkCompactCollector::tracer()->decrement_marked_count(); MarkCompactCollector::tracer()->decrement_marked_count();
object_size = object->Size(); object_size = object->Size();
Object* forwarded = Alloc(object, object_size);
// Allocation cannot fail, because we are compacting the space. // Allocation cannot fail, because we are compacting the space.
ASSERT(!forwarded->IsFailure()); Object* forwarded = Alloc(object, object_size)->ToObjectUnchecked();
Encode(object, object_size, forwarded, offset); Encode(object, object_size, forwarded, offset);
#ifdef DEBUG #ifdef DEBUG
@ -1551,8 +1560,9 @@ static bool TryPromoteObject(HeapObject* object, int object_size) {
Object* result; Object* result;
if (object_size > Heap::MaxObjectSizeInPagedSpace()) { if (object_size > Heap::MaxObjectSizeInPagedSpace()) {
result = Heap::lo_space()->AllocateRawFixedArray(object_size); MaybeObject* maybe_result =
if (!result->IsFailure()) { Heap::lo_space()->AllocateRawFixedArray(object_size);
if (maybe_result->ToObject(&result)) {
HeapObject* target = HeapObject::cast(result); HeapObject* target = HeapObject::cast(result);
MigrateObject(target->address(), object->address(), object_size, true); MigrateObject(target->address(), object->address(), object_size, true);
MarkCompactCollector::tracer()-> MarkCompactCollector::tracer()->
@ -1564,8 +1574,8 @@ static bool TryPromoteObject(HeapObject* object, int object_size) {
ASSERT(target_space == Heap::old_pointer_space() || ASSERT(target_space == Heap::old_pointer_space() ||
target_space == Heap::old_data_space()); target_space == Heap::old_data_space());
result = target_space->AllocateRaw(object_size); MaybeObject* maybe_result = target_space->AllocateRaw(object_size);
if (!result->IsFailure()) { if (maybe_result->ToObject(&result)) {
HeapObject* target = HeapObject::cast(result); HeapObject* target = HeapObject::cast(result);
MigrateObject(target->address(), MigrateObject(target->address(),
object->address(), object->address(),
@ -1613,10 +1623,8 @@ static void SweepNewSpace(NewSpace* space) {
} }
// Promotion failed. Just migrate object to another semispace. // Promotion failed. Just migrate object to another semispace.
Object* target = space->AllocateRaw(size);
// Allocation cannot fail at this point: semispaces are of equal size. // Allocation cannot fail at this point: semispaces are of equal size.
ASSERT(!target->IsFailure()); Object* target = space->AllocateRaw(size)->ToObjectUnchecked();
MigrateObject(HeapObject::cast(target)->address(), MigrateObject(HeapObject::cast(target)->address(),
current, current,

3
deps/v8/src/mark-compact.h

@ -53,7 +53,8 @@ class MarkCompactCollector: public AllStatic {
// Object* that will be the object after forwarding. There is a separate // Object* that will be the object after forwarding. There is a separate
// allocation function for each (compactable) space based on the location // allocation function for each (compactable) space based on the location
// of the object before compaction. // of the object before compaction.
typedef Object* (*AllocationFunction)(HeapObject* object, int object_size); typedef MaybeObject* (*AllocationFunction)(HeapObject* object,
int object_size);
// Type of functions to encode the forwarding address for an object. // Type of functions to encode the forwarding address for an object.
// Given the object, its size, and the new (non-failure) object it will be // Given the object, its size, and the new (non-failure) object it will be

4
deps/v8/src/messages.cc

@ -152,8 +152,8 @@ void MessageHandler::ReportMessage(MessageLocation* loc,
Handle<String> MessageHandler::GetMessage(Handle<Object> data) { Handle<String> MessageHandler::GetMessage(Handle<Object> data) {
Handle<String> fmt_str = Factory::LookupAsciiSymbol("FormatMessage"); Handle<String> fmt_str = Factory::LookupAsciiSymbol("FormatMessage");
Handle<JSFunction> fun = Handle<JSFunction> fun =
Handle<JSFunction>( Handle<JSFunction>(JSFunction::cast(
JSFunction::cast(Top::builtins()->GetProperty(*fmt_str))); Top::builtins()->GetPropertyNoExceptionThrown(*fmt_str)));
Object** argv[1] = { data.location() }; Object** argv[1] = { data.location() };
bool caught_exception; bool caught_exception;

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

@ -40,31 +40,37 @@ namespace internal {
static const char* TypeToString(InstanceType type); static const char* TypeToString(InstanceType type);
void Object::Print() { void MaybeObject::Print() {
if (IsSmi()) { Object* this_as_object;
Smi::cast(this)->SmiPrint(); if (ToObject(&this_as_object)) {
} else if (IsFailure()) { if (this_as_object->IsSmi()) {
Failure::cast(this)->FailurePrint(); Smi::cast(this_as_object)->SmiPrint();
} else {
HeapObject::cast(this_as_object)->HeapObjectPrint();
}
} else { } else {
HeapObject::cast(this)->HeapObjectPrint(); Failure::cast(this)->FailurePrint();
} }
Flush(); Flush();
} }
void Object::PrintLn() { void MaybeObject::PrintLn() {
Print(); Print();
PrintF("\n"); PrintF("\n");
} }
void Object::Verify() { void MaybeObject::Verify() {
if (IsSmi()) { Object* this_as_object;
Smi::cast(this)->SmiVerify(); if (ToObject(&this_as_object)) {
} else if (IsFailure()) { if (this_as_object->IsSmi()) {
Failure::cast(this)->FailureVerify(); Smi::cast(this_as_object)->SmiVerify();
} else {
HeapObject::cast(this_as_object)->HeapObjectVerify();
}
} else { } else {
HeapObject::cast(this)->HeapObjectVerify(); Failure::cast(this)->FailureVerify();
} }
} }

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

@ -396,28 +396,39 @@ bool Object::IsExternalFloatArray() {
} }
bool Object::IsFailure() { bool MaybeObject::IsFailure() {
return HAS_FAILURE_TAG(this); return HAS_FAILURE_TAG(this);
} }
bool Object::IsRetryAfterGC() { bool MaybeObject::IsRetryAfterGC() {
return HAS_FAILURE_TAG(this) return HAS_FAILURE_TAG(this)
&& Failure::cast(this)->type() == Failure::RETRY_AFTER_GC; && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC;
} }
bool Object::IsOutOfMemoryFailure() { bool MaybeObject::IsOutOfMemory() {
return HAS_FAILURE_TAG(this) return HAS_FAILURE_TAG(this)
&& Failure::cast(this)->IsOutOfMemoryException(); && Failure::cast(this)->IsOutOfMemoryException();
} }
bool Object::IsException() { bool MaybeObject::IsException() {
return this == Failure::Exception(); return this == Failure::Exception();
} }
bool MaybeObject::IsTheHole() {
return this == Heap::the_hole_value();
}
Failure* Failure::cast(MaybeObject* obj) {
ASSERT(HAS_FAILURE_TAG(obj));
return reinterpret_cast<Failure*>(obj);
}
bool Object::IsJSObject() { bool Object::IsJSObject() {
return IsHeapObject() return IsHeapObject()
&& HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE; && HeapObject::cast(this)->map()->instance_type() >= FIRST_JS_OBJECT_TYPE;
@ -677,11 +688,6 @@ bool Object::IsUndefined() {
} }
bool Object::IsTheHole() {
return this == Heap::the_hole_value();
}
bool Object::IsNull() { bool Object::IsNull() {
return this == Heap::null_value(); return this == Heap::null_value();
} }
@ -706,7 +712,7 @@ double Object::Number() {
Object* Object::ToSmi() { MaybeObject* Object::ToSmi() {
if (IsSmi()) return this; if (IsSmi()) return this;
if (IsHeapNumber()) { if (IsHeapNumber()) {
double value = HeapNumber::cast(this)->value(); double value = HeapNumber::cast(this)->value();
@ -724,18 +730,27 @@ bool Object::HasSpecificClassOf(String* name) {
} }
Object* Object::GetElement(uint32_t index) { MaybeObject* Object::GetElement(uint32_t index) {
return GetElementWithReceiver(this, index); return GetElementWithReceiver(this, index);
} }
Object* Object::GetProperty(String* key) { Object* Object::GetElementNoExceptionThrown(uint32_t index) {
MaybeObject* maybe = GetElementWithReceiver(this, index);
ASSERT(!maybe->IsFailure());
Object* result = NULL; // Initialization to please compiler.
maybe->ToObject(&result);
return result;
}
MaybeObject* Object::GetProperty(String* key) {
PropertyAttributes attributes; PropertyAttributes attributes;
return GetPropertyWithReceiver(this, key, &attributes); return GetPropertyWithReceiver(this, key, &attributes);
} }
Object* Object::GetProperty(String* key, PropertyAttributes* attributes) { MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) {
return GetPropertyWithReceiver(this, key, attributes); return GetPropertyWithReceiver(this, key, attributes);
} }
@ -1189,9 +1204,11 @@ void JSObject::initialize_elements() {
} }
Object* JSObject::ResetElements() { MaybeObject* JSObject::ResetElements() {
Object* obj = map()->GetFastElementsMap(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = map()->GetFastElementsMap();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
set_map(Map::cast(obj)); set_map(Map::cast(obj));
initialize_elements(); initialize_elements();
return this; return this;
@ -1681,7 +1698,6 @@ CAST_ACCESSOR(ExternalAsciiString)
CAST_ACCESSOR(ExternalTwoByteString) CAST_ACCESSOR(ExternalTwoByteString)
CAST_ACCESSOR(JSObject) CAST_ACCESSOR(JSObject)
CAST_ACCESSOR(Smi) CAST_ACCESSOR(Smi)
CAST_ACCESSOR(Failure)
CAST_ACCESSOR(HeapObject) CAST_ACCESSOR(HeapObject)
CAST_ACCESSOR(HeapNumber) CAST_ACCESSOR(HeapNumber)
CAST_ACCESSOR(Oddball) CAST_ACCESSOR(Oddball)
@ -1754,7 +1770,7 @@ bool String::Equals(String* other) {
} }
Object* String::TryFlatten(PretenureFlag pretenure) { MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
if (!StringShape(this).IsCons()) return this; if (!StringShape(this).IsCons()) return this;
ConsString* cons = ConsString::cast(this); ConsString* cons = ConsString::cast(this);
if (cons->second()->length() == 0) return cons->first(); if (cons->second()->length() == 0) return cons->first();
@ -1763,8 +1779,12 @@ Object* String::TryFlatten(PretenureFlag pretenure) {
String* String::TryFlattenGetString(PretenureFlag pretenure) { String* String::TryFlattenGetString(PretenureFlag pretenure) {
Object* flat = TryFlatten(pretenure); MaybeObject* flat = TryFlatten(pretenure);
return flat->IsFailure() ? this : String::cast(flat); Object* successfully_flattened;
if (flat->ToObject(&successfully_flattened)) {
return String::cast(successfully_flattened);
}
return this;
} }
@ -2475,10 +2495,12 @@ void Map::set_prototype(Object* value, WriteBarrierMode mode) {
} }
Object* Map::GetFastElementsMap() { MaybeObject* Map::GetFastElementsMap() {
if (has_fast_elements()) return this; if (has_fast_elements()) return this;
Object* obj = CopyDropTransitions(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = CopyDropTransitions();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
Map* new_map = Map::cast(obj); Map* new_map = Map::cast(obj);
new_map->set_has_fast_elements(true); new_map->set_has_fast_elements(true);
Counters::map_slow_to_fast_elements.Increment(); Counters::map_slow_to_fast_elements.Increment();
@ -2486,10 +2508,12 @@ Object* Map::GetFastElementsMap() {
} }
Object* Map::GetSlowElementsMap() { MaybeObject* Map::GetSlowElementsMap() {
if (!has_fast_elements()) return this; if (!has_fast_elements()) return this;
Object* obj = CopyDropTransitions(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = CopyDropTransitions();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
Map* new_map = Map::cast(obj); Map* new_map = Map::cast(obj);
new_map->set_has_fast_elements(false); new_map->set_has_fast_elements(false);
Counters::map_fast_to_slow_elements.Increment(); Counters::map_fast_to_slow_elements.Increment();
@ -3189,13 +3213,17 @@ bool JSObject::AllowsSetElementsLength() {
} }
Object* JSObject::EnsureWritableFastElements() { MaybeObject* JSObject::EnsureWritableFastElements() {
ASSERT(HasFastElements()); ASSERT(HasFastElements());
FixedArray* elems = FixedArray::cast(elements()); FixedArray* elems = FixedArray::cast(elements());
if (elems->map() != Heap::fixed_cow_array_map()) return elems; if (elems->map() != Heap::fixed_cow_array_map()) return elems;
Object* writable_elems = Heap::CopyFixedArrayWithMap(elems, Object* writable_elems;
Heap::fixed_array_map()); { MaybeObject* maybe_writable_elems =
if (writable_elems->IsFailure()) return writable_elems; Heap::CopyFixedArrayWithMap(elems, Heap::fixed_array_map());
if (!maybe_writable_elems->ToObject(&writable_elems)) {
return maybe_writable_elems;
}
}
set_elements(FixedArray::cast(writable_elems)); set_elements(FixedArray::cast(writable_elems));
Counters::cow_arrays_converted.Increment(); Counters::cow_arrays_converted.Increment();
return writable_elems; return writable_elems;
@ -3340,13 +3368,18 @@ bool JSObject::HasHiddenPropertiesObject() {
Object* JSObject::GetHiddenPropertiesObject() { Object* JSObject::GetHiddenPropertiesObject() {
ASSERT(!IsJSGlobalProxy()); ASSERT(!IsJSGlobalProxy());
PropertyAttributes attributes; PropertyAttributes attributes;
return GetLocalPropertyPostInterceptor(this, // You can't install a getter on a property indexed by the hidden symbol,
Heap::hidden_symbol(), // so we can be sure that GetLocalPropertyPostInterceptor returns a real
&attributes); // object.
Object* result =
GetLocalPropertyPostInterceptor(this,
Heap::hidden_symbol(),
&attributes)->ToObjectUnchecked();
return result;
} }
Object* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) { MaybeObject* JSObject::SetHiddenPropertiesObject(Object* hidden_obj) {
ASSERT(!IsJSGlobalProxy()); ASSERT(!IsJSGlobalProxy());
return SetPropertyPostInterceptor(Heap::hidden_symbol(), return SetPropertyPostInterceptor(Heap::hidden_symbol(),
hidden_obj, hidden_obj,
@ -3453,7 +3486,7 @@ void JSArray::SetContent(FixedArray* storage) {
} }
Object* FixedArray::Copy() { MaybeObject* FixedArray::Copy() {
if (length() == 0) return this; if (length() == 0) return this;
return Heap::CopyFixedArray(this); return Heap::CopyFixedArray(this);
} }

1307
deps/v8/src/objects.cc

File diff suppressed because it is too large

515
deps/v8/src/objects.h

@ -41,9 +41,10 @@
// Most object types in the V8 JavaScript are described in this file. // Most object types in the V8 JavaScript are described in this file.
// //
// Inheritance hierarchy: // Inheritance hierarchy:
// - MaybeObject (an object or a failure)
// - Failure (immediate for marking failed operation)
// - Object // - Object
// - Smi (immediate small integer) // - Smi (immediate small integer)
// - Failure (immediate for marking failed operation)
// - HeapObject (superclass for everything allocated in the heap) // - HeapObject (superclass for everything allocated in the heap)
// - JSObject // - JSObject
// - JSArray // - JSArray
@ -584,6 +585,35 @@ struct ValueInfo : public Malloced {
// A template-ized version of the IsXXX functions. // A template-ized version of the IsXXX functions.
template <class C> static inline bool Is(Object* obj); template <class C> static inline bool Is(Object* obj);
class MaybeObject BASE_EMBEDDED {
public:
inline bool IsFailure();
inline bool IsRetryAfterGC();
inline bool IsOutOfMemory();
inline bool IsException();
INLINE(bool IsTheHole());
inline bool ToObject(Object** obj) {
if (IsFailure()) return false;
*obj = reinterpret_cast<Object*>(this);
return true;
}
inline Object* ToObjectUnchecked() {
ASSERT(!IsFailure());
return reinterpret_cast<Object*>(this);
}
inline Object* ToObjectChecked() {
CHECK(!IsFailure());
return reinterpret_cast<Object*>(this);
}
#ifdef DEBUG
// Prints this object with details.
void Print();
void PrintLn();
// Verifies the object.
void Verify();
#endif
};
// Object is the abstract superclass for all classes in the // Object is the abstract superclass for all classes in the
// object hierarchy. // object hierarchy.
@ -591,7 +621,7 @@ template <class C> static inline bool Is(Object* obj);
// allocation of the C++ vtable. // allocation of the C++ vtable.
// Since Smi and Failure are subclasses of Object no // Since Smi and Failure are subclasses of Object no
// data members can be present in Object. // data members can be present in Object.
class Object BASE_EMBEDDED { class Object : public MaybeObject {
public: public:
// Type testing. // Type testing.
inline bool IsSmi(); inline bool IsSmi();
@ -619,10 +649,6 @@ class Object BASE_EMBEDDED {
inline bool IsExternalIntArray(); inline bool IsExternalIntArray();
inline bool IsExternalUnsignedIntArray(); inline bool IsExternalUnsignedIntArray();
inline bool IsExternalFloatArray(); inline bool IsExternalFloatArray();
inline bool IsFailure();
inline bool IsRetryAfterGC();
inline bool IsOutOfMemoryFailure();
inline bool IsException();
inline bool IsJSObject(); inline bool IsJSObject();
inline bool IsJSContextExtensionObject(); inline bool IsJSContextExtensionObject();
inline bool IsMap(); inline bool IsMap();
@ -669,7 +695,6 @@ class Object BASE_EMBEDDED {
// Oddball testing. // Oddball testing.
INLINE(bool IsUndefined()); INLINE(bool IsUndefined());
INLINE(bool IsTheHole());
INLINE(bool IsNull()); INLINE(bool IsNull());
INLINE(bool IsTrue()); INLINE(bool IsTrue());
INLINE(bool IsFalse()); INLINE(bool IsFalse());
@ -679,38 +704,43 @@ class Object BASE_EMBEDDED {
inline bool HasSpecificClassOf(String* name); inline bool HasSpecificClassOf(String* name);
Object* ToObject(); // ECMA-262 9.9. MUST_USE_RESULT MaybeObject* ToObject(); // ECMA-262 9.9.
Object* ToBoolean(); // ECMA-262 9.2. Object* ToBoolean(); // ECMA-262 9.2.
// Convert to a JSObject if needed. // Convert to a JSObject if needed.
// global_context is used when creating wrapper object. // global_context is used when creating wrapper object.
Object* ToObject(Context* global_context); MUST_USE_RESULT MaybeObject* ToObject(Context* global_context);
// Converts this to a Smi if possible. // Converts this to a Smi if possible.
// Failure is returned otherwise. // Failure is returned otherwise.
inline Object* ToSmi(); MUST_USE_RESULT inline MaybeObject* ToSmi();
void Lookup(String* name, LookupResult* result); void Lookup(String* name, LookupResult* result);
// Property access. // Property access.
inline Object* GetProperty(String* key); MUST_USE_RESULT inline MaybeObject* GetProperty(String* key);
inline Object* GetProperty(String* key, PropertyAttributes* attributes); MUST_USE_RESULT inline MaybeObject* GetProperty(
Object* GetPropertyWithReceiver(Object* receiver, String* key,
String* key, PropertyAttributes* attributes);
PropertyAttributes* attributes); MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver(
Object* GetProperty(Object* receiver, Object* receiver,
LookupResult* result, String* key,
String* key, PropertyAttributes* attributes);
PropertyAttributes* attributes); MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver,
Object* GetPropertyWithCallback(Object* receiver, LookupResult* result,
Object* structure, String* key,
String* name, PropertyAttributes* attributes);
Object* holder); MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver,
Object* GetPropertyWithDefinedGetter(Object* receiver, Object* structure,
JSFunction* getter); String* name,
Object* holder);
inline Object* GetElement(uint32_t index); MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver,
Object* GetElementWithReceiver(Object* receiver, uint32_t index); JSFunction* getter);
inline MaybeObject* GetElement(uint32_t index);
// For use when we know that no exception can be thrown.
inline Object* GetElementNoExceptionThrown(uint32_t index);
MaybeObject* GetElementWithReceiver(Object* receiver, uint32_t index);
// Return the object's prototype (might be Heap::null_value()). // Return the object's prototype (might be Heap::null_value()).
Object* GetPrototype(); Object* GetPrototype();
@ -724,12 +754,6 @@ class Object BASE_EMBEDDED {
inline bool IsStringObjectWithCharacterAt(uint32_t index); inline bool IsStringObjectWithCharacterAt(uint32_t index);
#ifdef DEBUG #ifdef DEBUG
// Prints this object with details.
void Print();
void PrintLn();
// Verifies the object.
void Verify();
// Verify a pointer is a valid object pointer. // Verify a pointer is a valid object pointer.
static void VerifyPointer(Object* p); static void VerifyPointer(Object* p);
#endif #endif
@ -815,7 +839,7 @@ class Smi: public Object {
const int kFailureTypeTagSize = 2; const int kFailureTypeTagSize = 2;
const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1; const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1;
class Failure: public Object { class Failure: public MaybeObject {
public: public:
// RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code. // RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code.
enum Type { enum Type {
@ -840,7 +864,7 @@ class Failure: public Object {
static inline Failure* InternalError(); static inline Failure* InternalError();
static inline Failure* OutOfMemoryException(); static inline Failure* OutOfMemoryException();
// Casting. // Casting.
static inline Failure* cast(Object* object); static inline Failure* cast(MaybeObject* object);
// Dispatched behavior. // Dispatched behavior.
void FailurePrint(); void FailurePrint();
@ -1249,7 +1273,7 @@ class JSObject: public HeapObject {
// PixelArray or an ExternalArray. // PixelArray or an ExternalArray.
DECL_ACCESSORS(elements, HeapObject) DECL_ACCESSORS(elements, HeapObject)
inline void initialize_elements(); inline void initialize_elements();
inline Object* ResetElements(); MUST_USE_RESULT inline MaybeObject* ResetElements();
inline ElementsKind GetElementsKind(); inline ElementsKind GetElementsKind();
inline bool HasFastElements(); inline bool HasFastElements();
inline bool HasDictionaryElements(); inline bool HasDictionaryElements();
@ -1265,41 +1289,45 @@ class JSObject: public HeapObject {
inline bool AllowsSetElementsLength(); inline bool AllowsSetElementsLength();
inline NumberDictionary* element_dictionary(); // Gets slow elements. inline NumberDictionary* element_dictionary(); // Gets slow elements.
// Requires: this->HasFastElements(). // Requires: this->HasFastElements().
inline Object* EnsureWritableFastElements(); MUST_USE_RESULT inline MaybeObject* EnsureWritableFastElements();
// Collects elements starting at index 0. // Collects elements starting at index 0.
// Undefined values are placed after non-undefined values. // Undefined values are placed after non-undefined values.
// Returns the number of non-undefined values. // Returns the number of non-undefined values.
Object* PrepareElementsForSort(uint32_t limit); MUST_USE_RESULT MaybeObject* PrepareElementsForSort(uint32_t limit);
// As PrepareElementsForSort, but only on objects where elements is // As PrepareElementsForSort, but only on objects where elements is
// a dictionary, and it will stay a dictionary. // a dictionary, and it will stay a dictionary.
MUST_USE_RESULT Object* PrepareSlowElementsForSort(uint32_t limit); MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit);
Object* SetProperty(String* key, MUST_USE_RESULT MaybeObject* SetProperty(String* key,
Object* value, Object* value,
PropertyAttributes attributes); PropertyAttributes attributes);
Object* SetProperty(LookupResult* result, MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result,
String* key, String* key,
Object* value, Object* value,
PropertyAttributes attributes); PropertyAttributes attributes);
Object* SetPropertyWithFailedAccessCheck(LookupResult* result, MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck(
String* name, LookupResult* result,
Object* value); String* name,
Object* SetPropertyWithCallback(Object* structure, Object* value);
String* name, MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(Object* structure,
Object* value, String* name,
JSObject* holder); Object* value,
Object* SetPropertyWithDefinedSetter(JSFunction* setter, JSObject* holder);
Object* value); MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSFunction* setter,
Object* SetPropertyWithInterceptor(String* name, Object* value);
Object* value, MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor(
PropertyAttributes attributes); String* name,
Object* SetPropertyPostInterceptor(String* name, Object* value,
Object* value, PropertyAttributes attributes);
PropertyAttributes attributes); MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor(
Object* IgnoreAttributesAndSetLocalProperty(String* key, String* name,
Object* value, Object* value,
PropertyAttributes attributes); PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* IgnoreAttributesAndSetLocalProperty(
String* key,
Object* value,
PropertyAttributes attributes);
// Retrieve a value in a normalized object given a lookup result. // Retrieve a value in a normalized object given a lookup result.
// Handles the special representation of JS global objects. // Handles the special representation of JS global objects.
@ -1311,13 +1339,13 @@ class JSObject: public HeapObject {
// Sets the property value in a normalized object given (key, value, details). // Sets the property value in a normalized object given (key, value, details).
// Handles the special representation of JS global objects. // Handles the special representation of JS global objects.
MUST_USE_RESULT Object* SetNormalizedProperty(String* name, MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name,
Object* value, Object* value,
PropertyDetails details); PropertyDetails details);
// Deletes the named property in a normalized object. // Deletes the named property in a normalized object.
MUST_USE_RESULT Object* DeleteNormalizedProperty(String* name, MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name,
DeleteMode mode); DeleteMode mode);
// Returns the class name ([[Class]] property in the specification). // Returns the class name ([[Class]] property in the specification).
String* class_name(); String* class_name();
@ -1335,28 +1363,31 @@ class JSObject: public HeapObject {
String* name); String* name);
PropertyAttributes GetLocalPropertyAttribute(String* name); PropertyAttributes GetLocalPropertyAttribute(String* name);
MUST_USE_RESULT Object* DefineAccessor(String* name, MUST_USE_RESULT MaybeObject* DefineAccessor(String* name,
bool is_getter, bool is_getter,
JSFunction* fun, JSFunction* fun,
PropertyAttributes attributes); PropertyAttributes attributes);
Object* LookupAccessor(String* name, bool is_getter); Object* LookupAccessor(String* name, bool is_getter);
MUST_USE_RESULT Object* DefineAccessor(AccessorInfo* info); MUST_USE_RESULT MaybeObject* DefineAccessor(AccessorInfo* info);
// Used from Object::GetProperty(). // Used from Object::GetProperty().
Object* GetPropertyWithFailedAccessCheck(Object* receiver, MaybeObject* GetPropertyWithFailedAccessCheck(
LookupResult* result, Object* receiver,
String* name, LookupResult* result,
PropertyAttributes* attributes); String* name,
Object* GetPropertyWithInterceptor(JSObject* receiver, PropertyAttributes* attributes);
String* name, MaybeObject* GetPropertyWithInterceptor(
PropertyAttributes* attributes); JSObject* receiver,
Object* GetPropertyPostInterceptor(JSObject* receiver, String* name,
String* name, PropertyAttributes* attributes);
PropertyAttributes* attributes); MaybeObject* GetPropertyPostInterceptor(
Object* GetLocalPropertyPostInterceptor(JSObject* receiver, JSObject* receiver,
String* name, String* name,
PropertyAttributes* attributes); PropertyAttributes* attributes);
MaybeObject* GetLocalPropertyPostInterceptor(JSObject* receiver,
String* name,
PropertyAttributes* attributes);
// Returns true if this is an instance of an api function and has // Returns true if this is an instance of an api function and has
// been modified since it was created. May give false positives. // been modified since it was created. May give false positives.
@ -1390,10 +1421,11 @@ class JSObject: public HeapObject {
// These accessors do not touch interceptors or accessors. // These accessors do not touch interceptors or accessors.
inline bool HasHiddenPropertiesObject(); inline bool HasHiddenPropertiesObject();
inline Object* GetHiddenPropertiesObject(); inline Object* GetHiddenPropertiesObject();
inline Object* SetHiddenPropertiesObject(Object* hidden_obj); MUST_USE_RESULT inline MaybeObject* SetHiddenPropertiesObject(
Object* hidden_obj);
MUST_USE_RESULT Object* DeleteProperty(String* name, DeleteMode mode); MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode);
MUST_USE_RESULT Object* DeleteElement(uint32_t index, DeleteMode mode); MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode);
// Tests for the fast common case for property enumeration. // Tests for the fast common case for property enumeration.
bool IsSimpleEnum(); bool IsSimpleEnum();
@ -1411,7 +1443,8 @@ class JSObject: public HeapObject {
inline Object* GetPrototype(); inline Object* GetPrototype();
// Set the object's prototype (only JSObject and null are allowed). // Set the object's prototype (only JSObject and null are allowed).
Object* SetPrototype(Object* value, bool skip_hidden_prototypes); MUST_USE_RESULT MaybeObject* SetPrototype(Object* value,
bool skip_hidden_prototypes);
// Tells whether the index'th element is present. // Tells whether the index'th element is present.
inline bool HasElement(uint32_t index); inline bool HasElement(uint32_t index);
@ -1440,20 +1473,20 @@ class JSObject: public HeapObject {
bool HasElementWithInterceptor(JSObject* receiver, uint32_t index); bool HasElementWithInterceptor(JSObject* receiver, uint32_t index);
bool HasElementPostInterceptor(JSObject* receiver, uint32_t index); bool HasElementPostInterceptor(JSObject* receiver, uint32_t index);
MUST_USE_RESULT Object* SetFastElement(uint32_t index, Object* value); MUST_USE_RESULT MaybeObject* SetFastElement(uint32_t index, Object* value);
// Set the index'th array element. // Set the index'th array element.
// A Failure object is returned if GC is needed. // A Failure object is returned if GC is needed.
MUST_USE_RESULT Object* SetElement(uint32_t index, Object* value); MUST_USE_RESULT MaybeObject* SetElement(uint32_t index, Object* value);
// Returns the index'th element. // Returns the index'th element.
// The undefined object if index is out of bounds. // The undefined object if index is out of bounds.
Object* GetElementWithReceiver(JSObject* receiver, uint32_t index); MaybeObject* GetElementWithReceiver(JSObject* receiver, uint32_t index);
Object* GetElementWithInterceptor(JSObject* receiver, uint32_t index); MaybeObject* GetElementWithInterceptor(JSObject* receiver, uint32_t index);
MUST_USE_RESULT Object* SetFastElementsCapacityAndLength(int capacity, MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(int capacity,
int length); int length);
MUST_USE_RESULT Object* SetSlowElements(Object* length); MUST_USE_RESULT MaybeObject* SetSlowElements(Object* length);
// Lookup interceptors are used for handling properties controlled by host // Lookup interceptors are used for handling properties controlled by host
// objects. // objects.
@ -1466,7 +1499,7 @@ class JSObject: public HeapObject {
bool HasRealNamedCallbackProperty(String* key); bool HasRealNamedCallbackProperty(String* key);
// Initializes the array to a certain length // Initializes the array to a certain length
MUST_USE_RESULT Object* SetElementsLength(Object* length); MUST_USE_RESULT MaybeObject* SetElementsLength(Object* length);
// Get the header size for a JSObject. Used to compute the index of // Get the header size for a JSObject. Used to compute the index of
// internal fields as well as the number of internal fields. // internal fields as well as the number of internal fields.
@ -1515,9 +1548,9 @@ class JSObject: public HeapObject {
// Add a property to a fast-case object using a map transition to // Add a property to a fast-case object using a map transition to
// new_map. // new_map.
Object* AddFastPropertyUsingMap(Map* new_map, MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map,
String* name, String* name,
Object* value); Object* value);
// Add a constant function property to a fast-case object. // Add a constant function property to a fast-case object.
// This leaves a CONSTANT_TRANSITION in the old map, and // This leaves a CONSTANT_TRANSITION in the old map, and
@ -1525,20 +1558,22 @@ class JSObject: public HeapObject {
// normal property is added instead, with a map transition. // normal property is added instead, with a map transition.
// This avoids the creation of many maps with the same constant // This avoids the creation of many maps with the same constant
// function, all orphaned. // function, all orphaned.
Object* AddConstantFunctionProperty(String* name, MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty(
JSFunction* function, String* name,
PropertyAttributes attributes); JSFunction* function,
PropertyAttributes attributes);
Object* ReplaceSlowProperty(String* name, MUST_USE_RESULT MaybeObject* ReplaceSlowProperty(
Object* value, String* name,
PropertyAttributes attributes); Object* value,
PropertyAttributes attributes);
// Converts a descriptor of any other type to a real field, // Converts a descriptor of any other type to a real field,
// backed by the properties array. Descriptors of visible // backed by the properties array. Descriptors of visible
// types, such as CONSTANT_FUNCTION, keep their enumeration order. // types, such as CONSTANT_FUNCTION, keep their enumeration order.
// Converts the descriptor on the original object's map to a // Converts the descriptor on the original object's map to a
// map transition, and the the new field is on the object's new map. // map transition, and the the new field is on the object's new map.
Object* ConvertDescriptorToFieldAndMapTransition( MUST_USE_RESULT MaybeObject* ConvertDescriptorToFieldAndMapTransition(
String* name, String* name,
Object* new_value, Object* new_value,
PropertyAttributes attributes); PropertyAttributes attributes);
@ -1546,38 +1581,41 @@ class JSObject: public HeapObject {
// Converts a descriptor of any other type to a real field, // Converts a descriptor of any other type to a real field,
// backed by the properties array. Descriptors of visible // backed by the properties array. Descriptors of visible
// types, such as CONSTANT_FUNCTION, keep their enumeration order. // types, such as CONSTANT_FUNCTION, keep their enumeration order.
Object* ConvertDescriptorToField(String* name, MUST_USE_RESULT MaybeObject* ConvertDescriptorToField(
Object* new_value, String* name,
PropertyAttributes attributes); Object* new_value,
PropertyAttributes attributes);
// Add a property to a fast-case object. // Add a property to a fast-case object.
Object* AddFastProperty(String* name, MUST_USE_RESULT MaybeObject* AddFastProperty(String* name,
Object* value, Object* value,
PropertyAttributes attributes); PropertyAttributes attributes);
// Add a property to a slow-case object. // Add a property to a slow-case object.
Object* AddSlowProperty(String* name, MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name,
Object* value, Object* value,
PropertyAttributes attributes); PropertyAttributes attributes);
// Add a property to an object. // Add a property to an object.
Object* AddProperty(String* name, MUST_USE_RESULT MaybeObject* AddProperty(String* name,
Object* value, Object* value,
PropertyAttributes attributes); PropertyAttributes attributes);
// Convert the object to use the canonical dictionary // Convert the object to use the canonical dictionary
// representation. If the object is expected to have additional properties // representation. If the object is expected to have additional properties
// added this number can be indicated to have the backing store allocated to // added this number can be indicated to have the backing store allocated to
// an initial capacity for holding these properties. // an initial capacity for holding these properties.
Object* NormalizeProperties(PropertyNormalizationMode mode, MUST_USE_RESULT MaybeObject* NormalizeProperties(
int expected_additional_properties); PropertyNormalizationMode mode,
Object* NormalizeElements(); int expected_additional_properties);
MUST_USE_RESULT MaybeObject* NormalizeElements();
Object* UpdateMapCodeCache(String* name, Code* code); MUST_USE_RESULT MaybeObject* UpdateMapCodeCache(String* name, Code* code);
// Transform slow named properties to fast variants. // Transform slow named properties to fast variants.
// Returns failure if allocation failed. // Returns failure if allocation failed.
Object* TransformToFastProperties(int unused_property_fields); MUST_USE_RESULT MaybeObject* TransformToFastProperties(
int unused_property_fields);
// Access fast-case object properties at index. // Access fast-case object properties at index.
inline Object* FastPropertyAt(int index); inline Object* FastPropertyAt(int index);
@ -1603,7 +1641,7 @@ class JSObject: public HeapObject {
static inline JSObject* cast(Object* obj); static inline JSObject* cast(Object* obj);
// Disalow further properties to be added to the object. // Disalow further properties to be added to the object.
MUST_USE_RESULT Object* PreventExtensions(); MUST_USE_RESULT MaybeObject* PreventExtensions();
// Dispatched behavior. // Dispatched behavior.
@ -1668,28 +1706,28 @@ class JSObject: public HeapObject {
}; };
private: private:
Object* GetElementWithCallback(Object* receiver, MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver,
Object* structure, Object* structure,
uint32_t index, uint32_t index,
Object* holder); Object* holder);
Object* SetElementWithCallback(Object* structure, MaybeObject* SetElementWithCallback(Object* structure,
uint32_t index, uint32_t index,
Object* value, Object* value,
JSObject* holder); JSObject* holder);
MUST_USE_RESULT Object* SetElementWithInterceptor(uint32_t index, MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(uint32_t index,
Object* value); Object* value);
MUST_USE_RESULT Object* SetElementWithoutInterceptor(uint32_t index, MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(uint32_t index,
Object* value); Object* value);
Object* GetElementPostInterceptor(JSObject* receiver, uint32_t index); MaybeObject* GetElementPostInterceptor(JSObject* receiver, uint32_t index);
MUST_USE_RESULT Object* DeletePropertyPostInterceptor(String* name, MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name,
DeleteMode mode); DeleteMode mode);
MUST_USE_RESULT Object* DeletePropertyWithInterceptor(String* name); MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name);
MUST_USE_RESULT Object* DeleteElementPostInterceptor(uint32_t index, MUST_USE_RESULT MaybeObject* DeleteElementPostInterceptor(uint32_t index,
DeleteMode mode); DeleteMode mode);
MUST_USE_RESULT Object* DeleteElementWithInterceptor(uint32_t index); MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver, PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
String* name, String* name,
@ -1711,14 +1749,17 @@ class JSObject: public HeapObject {
bool HasDenseElements(); bool HasDenseElements();
bool CanSetCallback(String* name); bool CanSetCallback(String* name);
MUST_USE_RESULT Object* SetElementCallback(uint32_t index, MUST_USE_RESULT MaybeObject* SetElementCallback(
Object* structure, uint32_t index,
PropertyAttributes attributes); Object* structure,
MUST_USE_RESULT Object* SetPropertyCallback(String* name, PropertyAttributes attributes);
Object* structure, MUST_USE_RESULT MaybeObject* SetPropertyCallback(
PropertyAttributes attributes); String* name,
MUST_USE_RESULT Object* DefineGetterSetter(String* name, Object* structure,
PropertyAttributes attributes); PropertyAttributes attributes);
MUST_USE_RESULT MaybeObject* DefineGetterSetter(
String* name,
PropertyAttributes attributes);
void LookupInDescriptor(String* name, LookupResult* result); void LookupInDescriptor(String* name, LookupResult* result);
@ -1757,14 +1798,14 @@ class FixedArray: public HeapObject {
inline Object** data_start(); inline Object** data_start();
// Copy operations. // Copy operations.
inline Object* Copy(); MUST_USE_RESULT inline MaybeObject* Copy();
MUST_USE_RESULT Object* CopySize(int new_length); MUST_USE_RESULT MaybeObject* CopySize(int new_length);
// Add the elements of a JSArray to this FixedArray. // Add the elements of a JSArray to this FixedArray.
MUST_USE_RESULT Object* AddKeysFromJSArray(JSArray* array); MUST_USE_RESULT MaybeObject* AddKeysFromJSArray(JSArray* array);
// Compute the union of this and other. // Compute the union of this and other.
MUST_USE_RESULT Object* UnionOfKeys(FixedArray* other); MUST_USE_RESULT MaybeObject* UnionOfKeys(FixedArray* other);
// Copy a sub array from the receiver to dest. // Copy a sub array from the receiver to dest.
void CopyTo(int pos, FixedArray* dest, int dest_pos, int len); void CopyTo(int pos, FixedArray* dest, int dest_pos, int len);
@ -1903,12 +1944,12 @@ class DescriptorArray: public FixedArray {
// or null), its enumeration index is kept as is. // or null), its enumeration index is kept as is.
// If adding a real property, map transitions must be removed. If adding // If adding a real property, map transitions must be removed. If adding
// a transition, they must not be removed. All null descriptors are removed. // a transition, they must not be removed. All null descriptors are removed.
MUST_USE_RESULT Object* CopyInsert(Descriptor* descriptor, MUST_USE_RESULT MaybeObject* CopyInsert(Descriptor* descriptor,
TransitionFlag transition_flag); TransitionFlag transition_flag);
// Remove all transitions. Return a copy of the array with all transitions // Remove all transitions. Return a copy of the array with all transitions
// removed, or a Failure object if the new array could not be allocated. // removed, or a Failure object if the new array could not be allocated.
MUST_USE_RESULT Object* RemoveTransitions(); MUST_USE_RESULT MaybeObject* RemoveTransitions();
// Sort the instance descriptors by the hash codes of their keys. // Sort the instance descriptors by the hash codes of their keys.
// Does not check for duplicates. // Does not check for duplicates.
@ -1941,7 +1982,7 @@ class DescriptorArray: public FixedArray {
// Allocates a DescriptorArray, but returns the singleton // Allocates a DescriptorArray, but returns the singleton
// empty descriptor array object if number_of_descriptors is 0. // empty descriptor array object if number_of_descriptors is 0.
MUST_USE_RESULT static Object* Allocate(int number_of_descriptors); MUST_USE_RESULT static MaybeObject* Allocate(int number_of_descriptors);
// Casting. // Casting.
static inline DescriptorArray* cast(Object* obj); static inline DescriptorArray* cast(Object* obj);
@ -2081,7 +2122,7 @@ class HashTable: public FixedArray {
} }
// Returns a new HashTable object. Might return Failure. // Returns a new HashTable object. Might return Failure.
MUST_USE_RESULT static Object* Allocate( MUST_USE_RESULT static MaybeObject* Allocate(
int at_least_space_for, int at_least_space_for,
PretenureFlag pretenure = NOT_TENURED); PretenureFlag pretenure = NOT_TENURED);
@ -2177,7 +2218,7 @@ class HashTable: public FixedArray {
} }
// Ensure enough space for n additional elements. // Ensure enough space for n additional elements.
MUST_USE_RESULT Object* EnsureCapacity(int n, Key key); MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
}; };
@ -2193,7 +2234,7 @@ class HashTableKey {
virtual uint32_t HashForObject(Object* key) = 0; virtual uint32_t HashForObject(Object* key) = 0;
// Returns the key object for storing into the hash table. // Returns the key object for storing into the hash table.
// If allocations fails a failure object is returned. // If allocations fails a failure object is returned.
MUST_USE_RESULT virtual Object* AsObject() = 0; MUST_USE_RESULT virtual MaybeObject* AsObject() = 0;
// Required. // Required.
virtual ~HashTableKey() {} virtual ~HashTableKey() {}
}; };
@ -2209,7 +2250,7 @@ class SymbolTableShape {
static uint32_t HashForObject(HashTableKey* key, Object* object) { static uint32_t HashForObject(HashTableKey* key, Object* object) {
return key->HashForObject(object); return key->HashForObject(object);
} }
MUST_USE_RESULT static Object* AsObject(HashTableKey* key) { MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
return key->AsObject(); return key->AsObject();
} }
@ -2227,8 +2268,8 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
// added. The return value is the symbol table which might have // added. The return value is the symbol table which might have
// been enlarged. If the return value is not a failure, the symbol // been enlarged. If the return value is not a failure, the symbol
// pointer *s is set to the symbol found. // pointer *s is set to the symbol found.
Object* LookupSymbol(Vector<const char> str, Object** s); MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s);
Object* LookupString(String* key, Object** s); MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s);
// Looks up a symbol that is equal to the given string and returns // Looks up a symbol that is equal to the given string and returns
// true if it is found, assigning the symbol to the given output // true if it is found, assigning the symbol to the given output
@ -2240,7 +2281,7 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
static inline SymbolTable* cast(Object* obj); static inline SymbolTable* cast(Object* obj);
private: private:
Object* LookupKey(HashTableKey* key, Object** s); MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s);
DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable); DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable);
}; };
@ -2259,7 +2300,7 @@ class MapCacheShape {
return key->HashForObject(object); return key->HashForObject(object);
} }
MUST_USE_RESULT static Object* AsObject(HashTableKey* key) { MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
return key->AsObject(); return key->AsObject();
} }
@ -2276,7 +2317,7 @@ class MapCache: public HashTable<MapCacheShape, HashTableKey*> {
public: public:
// Find cached value for a string key, otherwise return null. // Find cached value for a string key, otherwise return null.
Object* Lookup(FixedArray* key); Object* Lookup(FixedArray* key);
Object* Put(FixedArray* key, Map* value); MUST_USE_RESULT MaybeObject* Put(FixedArray* key, Map* value);
static inline MapCache* cast(Object* obj); static inline MapCache* cast(Object* obj);
private: private:
@ -2347,10 +2388,10 @@ class Dictionary: public HashTable<Shape, Key> {
} }
// Returns a new array for dictionary usage. Might return Failure. // Returns a new array for dictionary usage. Might return Failure.
MUST_USE_RESULT static Object* Allocate(int at_least_space_for); MUST_USE_RESULT static MaybeObject* Allocate(int at_least_space_for);
// Ensure enough space for n additional elements. // Ensure enough space for n additional elements.
Object* EnsureCapacity(int n, Key key); MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key);
#ifdef DEBUG #ifdef DEBUG
void Print(); void Print();
@ -2364,20 +2405,22 @@ class Dictionary: public HashTable<Shape, Key> {
Object* value, Object* value,
PropertyDetails details); PropertyDetails details);
Object* Add(Key key, Object* value, PropertyDetails details); MUST_USE_RESULT MaybeObject* Add(Key key,
Object* value,
PropertyDetails details);
protected: protected:
// Generic at put operation. // Generic at put operation.
Object* AtPut(Key key, Object* value); MUST_USE_RESULT MaybeObject* AtPut(Key key, Object* value);
// Add entry to dictionary. // Add entry to dictionary.
Object* AddEntry(Key key, MUST_USE_RESULT MaybeObject* AddEntry(Key key,
Object* value, Object* value,
PropertyDetails details, PropertyDetails details,
uint32_t hash); uint32_t hash);
// Generate new enumeration indices to avoid enumeration index overflow. // Generate new enumeration indices to avoid enumeration index overflow.
Object* GenerateNewEnumerationIndices(); MUST_USE_RESULT MaybeObject* GenerateNewEnumerationIndices();
static const int kMaxNumberKeyIndex = static const int kMaxNumberKeyIndex =
HashTable<Shape, Key>::kPrefixStartIndex; HashTable<Shape, Key>::kPrefixStartIndex;
static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1; static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
@ -2389,7 +2432,7 @@ class StringDictionaryShape {
static inline bool IsMatch(String* key, Object* other); static inline bool IsMatch(String* key, Object* other);
static inline uint32_t Hash(String* key); static inline uint32_t Hash(String* key);
static inline uint32_t HashForObject(String* key, Object* object); static inline uint32_t HashForObject(String* key, Object* object);
MUST_USE_RESULT static inline Object* AsObject(String* key); MUST_USE_RESULT static inline MaybeObject* AsObject(String* key);
static const int kPrefixSize = 2; static const int kPrefixSize = 2;
static const int kEntrySize = 3; static const int kEntrySize = 3;
static const bool kIsEnumerable = true; static const bool kIsEnumerable = true;
@ -2407,8 +2450,9 @@ class StringDictionary: public Dictionary<StringDictionaryShape, String*> {
void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array); void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array);
// For transforming properties of a JSObject. // For transforming properties of a JSObject.
Object* TransformPropertiesToFastFor(JSObject* obj, MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor(
int unused_property_fields); JSObject* obj,
int unused_property_fields);
// Find entry for key otherwise return kNotFound. Optimzed version of // Find entry for key otherwise return kNotFound. Optimzed version of
// HashTable::FindEntry. // HashTable::FindEntry.
@ -2421,7 +2465,7 @@ class NumberDictionaryShape {
static inline bool IsMatch(uint32_t key, Object* other); static inline bool IsMatch(uint32_t key, Object* other);
static inline uint32_t Hash(uint32_t key); static inline uint32_t Hash(uint32_t key);
static inline uint32_t HashForObject(uint32_t key, Object* object); static inline uint32_t HashForObject(uint32_t key, Object* object);
MUST_USE_RESULT static inline Object* AsObject(uint32_t key); MUST_USE_RESULT static inline MaybeObject* AsObject(uint32_t key);
static const int kPrefixSize = 2; static const int kPrefixSize = 2;
static const int kEntrySize = 3; static const int kEntrySize = 3;
static const bool kIsEnumerable = false; static const bool kIsEnumerable = false;
@ -2436,13 +2480,15 @@ class NumberDictionary: public Dictionary<NumberDictionaryShape, uint32_t> {
} }
// Type specific at put (default NONE attributes is used when adding). // Type specific at put (default NONE attributes is used when adding).
Object* AtNumberPut(uint32_t key, Object* value); MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value);
Object* AddNumberEntry(uint32_t key, MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key,
Object* value, Object* value,
PropertyDetails details); PropertyDetails details);
// Set an existing entry or add a new one if needed. // Set an existing entry or add a new one if needed.
Object* Set(uint32_t key, Object* value, PropertyDetails details); MUST_USE_RESULT MaybeObject* Set(uint32_t key,
Object* value,
PropertyDetails details);
void UpdateMaxNumberKey(uint32_t key); void UpdateMaxNumberKey(uint32_t key);
@ -2509,7 +2555,8 @@ class NormalizedMapCache: public FixedArray {
public: public:
static const int kEntries = 64; static const int kEntries = 64;
Object* Get(JSObject* object, PropertyNormalizationMode mode); MUST_USE_RESULT MaybeObject* Get(JSObject* object,
PropertyNormalizationMode mode);
void Clear(); void Clear();
@ -2686,7 +2733,7 @@ class ExternalByteArray: public ExternalArray {
// This accessor applies the correct conversion from Smi, HeapNumber // This accessor applies the correct conversion from Smi, HeapNumber
// and undefined. // and undefined.
Object* SetValue(uint32_t index, Object* value); MaybeObject* SetValue(uint32_t index, Object* value);
// Casting. // Casting.
static inline ExternalByteArray* cast(Object* obj); static inline ExternalByteArray* cast(Object* obj);
@ -2709,7 +2756,7 @@ class ExternalUnsignedByteArray: public ExternalArray {
// This accessor applies the correct conversion from Smi, HeapNumber // This accessor applies the correct conversion from Smi, HeapNumber
// and undefined. // and undefined.
Object* SetValue(uint32_t index, Object* value); MaybeObject* SetValue(uint32_t index, Object* value);
// Casting. // Casting.
static inline ExternalUnsignedByteArray* cast(Object* obj); static inline ExternalUnsignedByteArray* cast(Object* obj);
@ -2732,7 +2779,7 @@ class ExternalShortArray: public ExternalArray {
// This accessor applies the correct conversion from Smi, HeapNumber // This accessor applies the correct conversion from Smi, HeapNumber
// and undefined. // and undefined.
Object* SetValue(uint32_t index, Object* value); MaybeObject* SetValue(uint32_t index, Object* value);
// Casting. // Casting.
static inline ExternalShortArray* cast(Object* obj); static inline ExternalShortArray* cast(Object* obj);
@ -2755,7 +2802,7 @@ class ExternalUnsignedShortArray: public ExternalArray {
// This accessor applies the correct conversion from Smi, HeapNumber // This accessor applies the correct conversion from Smi, HeapNumber
// and undefined. // and undefined.
Object* SetValue(uint32_t index, Object* value); MaybeObject* SetValue(uint32_t index, Object* value);
// Casting. // Casting.
static inline ExternalUnsignedShortArray* cast(Object* obj); static inline ExternalUnsignedShortArray* cast(Object* obj);
@ -2778,7 +2825,7 @@ class ExternalIntArray: public ExternalArray {
// This accessor applies the correct conversion from Smi, HeapNumber // This accessor applies the correct conversion from Smi, HeapNumber
// and undefined. // and undefined.
Object* SetValue(uint32_t index, Object* value); MaybeObject* SetValue(uint32_t index, Object* value);
// Casting. // Casting.
static inline ExternalIntArray* cast(Object* obj); static inline ExternalIntArray* cast(Object* obj);
@ -2801,7 +2848,7 @@ class ExternalUnsignedIntArray: public ExternalArray {
// This accessor applies the correct conversion from Smi, HeapNumber // This accessor applies the correct conversion from Smi, HeapNumber
// and undefined. // and undefined.
Object* SetValue(uint32_t index, Object* value); MaybeObject* SetValue(uint32_t index, Object* value);
// Casting. // Casting.
static inline ExternalUnsignedIntArray* cast(Object* obj); static inline ExternalUnsignedIntArray* cast(Object* obj);
@ -2824,7 +2871,7 @@ class ExternalFloatArray: public ExternalArray {
// This accessor applies the correct conversion from Smi, HeapNumber // This accessor applies the correct conversion from Smi, HeapNumber
// and undefined. // and undefined.
Object* SetValue(uint32_t index, Object* value); MaybeObject* SetValue(uint32_t index, Object* value);
// Casting. // Casting.
static inline ExternalFloatArray* cast(Object* obj); static inline ExternalFloatArray* cast(Object* obj);
@ -3192,24 +3239,24 @@ class Map: public HeapObject {
// [stub cache]: contains stubs compiled for this map. // [stub cache]: contains stubs compiled for this map.
DECL_ACCESSORS(code_cache, Object) DECL_ACCESSORS(code_cache, Object)
MUST_USE_RESULT Object* CopyDropDescriptors(); MUST_USE_RESULT MaybeObject* CopyDropDescriptors();
MUST_USE_RESULT Object* CopyNormalized(PropertyNormalizationMode mode, MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode,
NormalizedMapSharingMode sharing); NormalizedMapSharingMode sharing);
// Returns a copy of the map, with all transitions dropped from the // Returns a copy of the map, with all transitions dropped from the
// instance descriptors. // instance descriptors.
MUST_USE_RESULT Object* CopyDropTransitions(); MUST_USE_RESULT MaybeObject* CopyDropTransitions();
// Returns this map if it has the fast elements bit set, otherwise // Returns this map if it has the fast elements bit set, otherwise
// returns a copy of the map, with all transitions dropped from the // returns a copy of the map, with all transitions dropped from the
// descriptors and the fast elements bit set. // descriptors and the fast elements bit set.
inline Object* GetFastElementsMap(); MUST_USE_RESULT inline MaybeObject* GetFastElementsMap();
// Returns this map if it has the fast elements bit cleared, // Returns this map if it has the fast elements bit cleared,
// otherwise returns a copy of the map, with all transitions dropped // otherwise returns a copy of the map, with all transitions dropped
// from the descriptors and the fast elements bit cleared. // from the descriptors and the fast elements bit cleared.
inline Object* GetSlowElementsMap(); MUST_USE_RESULT inline MaybeObject* GetSlowElementsMap();
// Returns the property index for name (only valid for FAST MODE). // Returns the property index for name (only valid for FAST MODE).
int PropertyIndexFor(String* name); int PropertyIndexFor(String* name);
@ -3232,7 +3279,7 @@ class Map: public HeapObject {
inline void ClearCodeCache(); inline void ClearCodeCache();
// Update code cache. // Update code cache.
MUST_USE_RESULT Object* UpdateCodeCache(String* name, Code* code); MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
// Returns the found code or undefined if absent. // Returns the found code or undefined if absent.
Object* FindInCodeCache(String* name, Code::Flags flags); Object* FindInCodeCache(String* name, Code::Flags flags);
@ -3881,7 +3928,7 @@ class JSFunction: public JSObject {
inline Object* prototype(); inline Object* prototype();
inline Object* instance_prototype(); inline Object* instance_prototype();
Object* SetInstancePrototype(Object* value); Object* SetInstancePrototype(Object* value);
MUST_USE_RESULT Object* SetPrototype(Object* value); MUST_USE_RESULT MaybeObject* SetPrototype(Object* value);
// After prototype is removed, it will not be created when accessed, and // After prototype is removed, it will not be created when accessed, and
// [[Construct]] from this function will not be allowed. // [[Construct]] from this function will not be allowed.
@ -3991,8 +4038,17 @@ class GlobalObject: public JSObject {
// Retrieve the property cell used to store a property. // Retrieve the property cell used to store a property.
Object* GetPropertyCell(LookupResult* result); Object* GetPropertyCell(LookupResult* result);
// This is like GetProperty, but is used when you know the lookup won't fail
// by throwing an exception. This is for the debug and builtins global
// objects, where it is known which properties can be expected to be present
// on the object.
Object* GetPropertyNoExceptionThrown(String* key) {
Object* answer = GetProperty(key)->ToObjectUnchecked();
return answer;
}
// Ensure that the global object has a cell for the given property name. // Ensure that the global object has a cell for the given property name.
Object* EnsurePropertyCell(String* name); MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name);
// Casting. // Casting.
static inline GlobalObject* cast(Object* obj); static inline GlobalObject* cast(Object* obj);
@ -4222,7 +4278,7 @@ class CompilationCacheShape {
return key->HashForObject(object); return key->HashForObject(object);
} }
MUST_USE_RESULT static Object* AsObject(HashTableKey* key) { MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
return key->AsObject(); return key->AsObject();
} }
@ -4238,9 +4294,9 @@ class CompilationCacheTable: public HashTable<CompilationCacheShape,
Object* Lookup(String* src); Object* Lookup(String* src);
Object* LookupEval(String* src, Context* context); Object* LookupEval(String* src, Context* context);
Object* LookupRegExp(String* source, JSRegExp::Flags flags); Object* LookupRegExp(String* source, JSRegExp::Flags flags);
Object* Put(String* src, Object* value); MaybeObject* Put(String* src, Object* value);
Object* PutEval(String* src, Context* context, Object* value); MaybeObject* PutEval(String* src, Context* context, Object* value);
Object* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value); MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value);
static inline CompilationCacheTable* cast(Object* obj); static inline CompilationCacheTable* cast(Object* obj);
@ -4255,7 +4311,7 @@ class CodeCache: public Struct {
DECL_ACCESSORS(normal_type_cache, Object) DECL_ACCESSORS(normal_type_cache, Object)
// Add the code object to the cache. // Add the code object to the cache.
MUST_USE_RESULT Object* Update(String* name, Code* code); MUST_USE_RESULT MaybeObject* Update(String* name, Code* code);
// Lookup code object in the cache. Returns code object if found and undefined // Lookup code object in the cache. Returns code object if found and undefined
// if not. // if not.
@ -4283,8 +4339,8 @@ class CodeCache: public Struct {
static const int kSize = kNormalTypeCacheOffset + kPointerSize; static const int kSize = kNormalTypeCacheOffset + kPointerSize;
private: private:
MUST_USE_RESULT Object* UpdateDefaultCache(String* name, Code* code); MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code);
MUST_USE_RESULT Object* UpdateNormalTypeCache(String* name, Code* code); MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code);
Object* LookupDefaultCache(String* name, Code::Flags flags); Object* LookupDefaultCache(String* name, Code::Flags flags);
Object* LookupNormalTypeCache(String* name, Code::Flags flags); Object* LookupNormalTypeCache(String* name, Code::Flags flags);
@ -4312,7 +4368,7 @@ class CodeCacheHashTableShape {
return key->HashForObject(object); return key->HashForObject(object);
} }
MUST_USE_RESULT static Object* AsObject(HashTableKey* key) { MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) {
return key->AsObject(); return key->AsObject();
} }
@ -4325,7 +4381,7 @@ class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape,
HashTableKey*> { HashTableKey*> {
public: public:
Object* Lookup(String* name, Code::Flags flags); Object* Lookup(String* name, Code::Flags flags);
MUST_USE_RESULT Object* Put(String* name, Code* code); MUST_USE_RESULT MaybeObject* Put(String* name, Code* code);
int GetIndex(String* name, Code::Flags flags); int GetIndex(String* name, Code::Flags flags);
void RemoveByIndex(int index); void RemoveByIndex(int index);
@ -4492,7 +4548,7 @@ class String: public HeapObject {
// //
// Use FlattenString from Handles.cc to flatten even in case an // Use FlattenString from Handles.cc to flatten even in case an
// allocation failure happens. // allocation failure happens.
inline Object* TryFlatten(PretenureFlag pretenure = NOT_TENURED); inline MaybeObject* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
// Convenience function. Has exactly the same behavior as // Convenience function. Has exactly the same behavior as
// TryFlatten(), except in the case of failure returns the original // TryFlatten(), except in the case of failure returns the original
@ -4507,7 +4563,9 @@ class String: public HeapObject {
bool MarkAsUndetectable(); bool MarkAsUndetectable();
// Return a substring. // Return a substring.
Object* SubString(int from, int to, PretenureFlag pretenure = NOT_TENURED); MUST_USE_RESULT MaybeObject* SubString(int from,
int to,
PretenureFlag pretenure = NOT_TENURED);
// String equality operations. // String equality operations.
inline bool Equals(String* other); inline bool Equals(String* other);
@ -4709,7 +4767,7 @@ class String: public HeapObject {
// Try to flatten the top level ConsString that is hiding behind this // Try to flatten the top level ConsString that is hiding behind this
// string. This is a no-op unless the string is a ConsString. Flatten // string. This is a no-op unless the string is a ConsString. Flatten
// mutates the ConsString and might return a failure. // mutates the ConsString and might return a failure.
Object* SlowTryFlatten(PretenureFlag pretenure); MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
static inline bool IsHashFieldComputed(uint32_t field); static inline bool IsHashFieldComputed(uint32_t field);
@ -5101,7 +5159,8 @@ class Oddball: public HeapObject {
#endif #endif
// Initialize the fields. // Initialize the fields.
Object* Initialize(const char* to_string, Object* to_number); MUST_USE_RESULT MaybeObject* Initialize(const char* to_string,
Object* to_number);
// Layout description. // Layout description.
static const int kToStringOffset = HeapObject::kHeaderSize; static const int kToStringOffset = HeapObject::kHeaderSize;
@ -5193,13 +5252,13 @@ class JSArray: public JSObject {
// is set to a smi. This matches the set function on FixedArray. // is set to a smi. This matches the set function on FixedArray.
inline void set_length(Smi* length); inline void set_length(Smi* length);
MUST_USE_RESULT Object* JSArrayUpdateLengthFromIndex(uint32_t index, MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index,
Object* value); Object* value);
// Initialize the array with the given capacity. The function may // Initialize the array with the given capacity. The function may
// fail due to out-of-memory situations, but only if the requested // fail due to out-of-memory situations, but only if the requested
// capacity is non-zero. // capacity is non-zero.
MUST_USE_RESULT Object* Initialize(int capacity); MUST_USE_RESULT MaybeObject* Initialize(int capacity);
// Set the content of the array to the content of storage. // Set the content of the array to the content of storage.
inline void SetContent(FixedArray* storage); inline void SetContent(FixedArray* storage);

4
deps/v8/src/parser.cc

@ -4266,11 +4266,9 @@ Expression* Parser::NewThrowError(Handle<String> constructor,
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
Handle<Object> element = arguments[i]; Handle<Object> element = arguments[i];
if (!element.is_null()) { if (!element.is_null()) {
Object* ok = array->SetFastElement(i, *element);
USE(ok); // Don't get an unused variable warning.
// We know this doesn't cause a GC here because we allocated the JSArray // We know this doesn't cause a GC here because we allocated the JSArray
// large enough. // large enough.
ASSERT(!ok->IsFailure()); array->SetFastElement(i, *element)->ToObjectUnchecked();
} }
} }
ZoneList<Expression*>* args = new ZoneList<Expression*>(2); ZoneList<Expression*>* args = new ZoneList<Expression*>(2);

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

@ -617,7 +617,10 @@ class Sampler::PlatformData : public Malloced {
Sampler::Sampler(int interval, bool profiling) Sampler::Sampler(int interval, bool profiling)
: interval_(interval), profiling_(profiling), active_(false) { : interval_(interval),
profiling_(profiling),
synchronous_(profiling),
active_(false) {
data_ = new PlatformData(); data_ = new PlatformData();
} }

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

@ -33,6 +33,7 @@
#include <signal.h> #include <signal.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdlib.h> #include <stdlib.h>
@ -714,7 +715,6 @@ Semaphore* OS::CreateSemaphore(int count) {
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
static Sampler* active_sampler_ = NULL; static Sampler* active_sampler_ = NULL;
static pthread_t vm_thread_ = 0;
#if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__)) #if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__))
@ -743,36 +743,11 @@ enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11};
#endif #endif
// A function that determines if a signal handler is called in the context
// of a VM thread.
//
// The problem is that SIGPROF signal can be delivered to an arbitrary thread
// (see http://code.google.com/p/google-perftools/issues/detail?id=106#c2)
// So, if the signal is being handled in the context of a non-VM thread,
// it means that the VM thread is running, and trying to sample its stack can
// cause a crash.
static inline bool IsVmThread() {
// In the case of a single VM thread, this check is enough.
if (pthread_equal(pthread_self(), vm_thread_)) return true;
// If there are multiple threads that use VM, they must have a thread id
// stored in TLS. To verify that the thread is really executing VM,
// we check Top's data. Having that ThreadManager::RestoreThread first
// restores ThreadLocalTop from TLS, and only then erases the TLS value,
// reading Top::thread_id() should not be affected by races.
if (ThreadManager::HasId() && !ThreadManager::IsArchived() &&
ThreadManager::CurrentId() == Top::thread_id()) {
return true;
}
return false;
}
static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
#ifndef V8_HOST_ARCH_MIPS #ifndef V8_HOST_ARCH_MIPS
USE(info); USE(info);
if (signal != SIGPROF) return; if (signal != SIGPROF) return;
if (active_sampler_ == NULL) return; if (active_sampler_ == NULL) return;
if (!IsVmThread()) return;
TickSample sample_obj; TickSample sample_obj;
TickSample* sample = CpuProfiler::TickSampleEvent(); TickSample* sample = CpuProfiler::TickSampleEvent();
@ -819,22 +794,51 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
class Sampler::PlatformData : public Malloced { class Sampler::PlatformData : public Malloced {
public: public:
PlatformData() { explicit PlatformData(Sampler* sampler)
signal_handler_installed_ = false; : sampler_(sampler),
signal_handler_installed_(false),
vm_tgid_(getpid()),
// Glibc doesn't provide a wrapper for gettid(2).
vm_tid_(syscall(SYS_gettid)),
signal_sender_launched_(false) {
} }
void SignalSender() {
while (sampler_->IsActive()) {
// Glibc doesn't provide a wrapper for tgkill(2).
syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF);
// Convert ms to us and subtract 100 us to compensate delays
// occuring during signal delivery.
int result = usleep(sampler_->interval_ * 1000 - 100);
ASSERT(result == 0 || errno == EINTR);
USE(result);
}
}
Sampler* sampler_;
bool signal_handler_installed_; bool signal_handler_installed_;
struct sigaction old_signal_handler_; struct sigaction old_signal_handler_;
struct itimerval old_timer_value_; int vm_tgid_;
int vm_tid_;
bool signal_sender_launched_;
pthread_t signal_sender_thread_;
}; };
static void* SenderEntry(void* arg) {
Sampler::PlatformData* data =
reinterpret_cast<Sampler::PlatformData*>(arg);
data->SignalSender();
return 0;
}
Sampler::Sampler(int interval, bool profiling) Sampler::Sampler(int interval, bool profiling)
: interval_(interval), : interval_(interval),
profiling_(profiling), profiling_(profiling),
synchronous_(profiling), synchronous_(profiling),
active_(false) { active_(false) {
data_ = new PlatformData(); data_ = new PlatformData(this);
} }
@ -848,8 +852,6 @@ void Sampler::Start() {
// platforms. // platforms.
if (active_sampler_ != NULL) return; if (active_sampler_ != NULL) return;
vm_thread_ = pthread_self();
// Request profiling signals. // Request profiling signals.
struct sigaction sa; struct sigaction sa;
sa.sa_sigaction = ProfilerSignalHandler; sa.sa_sigaction = ProfilerSignalHandler;
@ -858,31 +860,38 @@ void Sampler::Start() {
if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return; if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return;
data_->signal_handler_installed_ = true; data_->signal_handler_installed_ = true;
// Set the itimer to generate a tick for each interval. // Start a thread that sends SIGPROF signal to VM thread.
itimerval itimer; // Sending the signal ourselves instead of relying on itimer provides
itimer.it_interval.tv_sec = interval_ / 1000; // much better accuracy.
itimer.it_interval.tv_usec = (interval_ % 1000) * 1000; active_ = true;
itimer.it_value.tv_sec = itimer.it_interval.tv_sec; if (pthread_create(
itimer.it_value.tv_usec = itimer.it_interval.tv_usec; &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_); data_->signal_sender_launched_ = true;
}
// Set this sampler as the active sampler. // Set this sampler as the active sampler.
active_sampler_ = this; active_sampler_ = this;
active_ = true;
} }
void Sampler::Stop() { void Sampler::Stop() {
active_ = false;
// Wait for signal sender termination (it will exit after setting
// active_ to false).
if (data_->signal_sender_launched_) {
pthread_join(data_->signal_sender_thread_, NULL);
data_->signal_sender_launched_ = false;
}
// Restore old signal handler // Restore old signal handler
if (data_->signal_handler_installed_) { if (data_->signal_handler_installed_) {
setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL);
sigaction(SIGPROF, &data_->old_signal_handler_, 0); sigaction(SIGPROF, &data_->old_signal_handler_, 0);
data_->signal_handler_installed_ = false; data_->signal_handler_installed_ = false;
} }
// This sampler is no longer the active sampler. // This sampler is no longer the active sampler.
active_sampler_ = NULL; active_sampler_ = NULL;
active_ = false;
} }

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

@ -206,7 +206,11 @@ OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
void* initial) { void* initial) {
FILE* file = fopen(name, "w+"); FILE* file = fopen(name, "w+");
if (file == NULL) return NULL; if (file == NULL) return NULL;
fwrite(initial, size, 1, file); int result = fwrite(initial, size, 1, file);
if (result < 1) {
fclose(file);
return NULL;
}
void* memory = void* memory =
mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
return new PosixMemoryMappedFile(file, memory, size); return new PosixMemoryMappedFile(file, memory, size);

4
deps/v8/src/profile-generator.cc

@ -1319,11 +1319,9 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
retainers_count); retainers_count);
} else if (object->IsSharedFunctionInfo()) { } else if (object->IsSharedFunctionInfo()) {
SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
String* name = String::cast(shared->name())->length() > 0 ?
String::cast(shared->name()) : shared->inferred_name();
return AddEntry(object, return AddEntry(object,
HeapEntry::kCode, HeapEntry::kCode,
collection_->GetFunctionName(name), collection_->GetName(String::cast(shared->name())),
children_count, children_count,
retainers_count); retainers_count);
} else if (object->IsScript()) { } else if (object->IsScript()) {

8
deps/v8/src/property.h

@ -45,10 +45,12 @@ class Descriptor BASE_EMBEDDED {
return Smi::cast(value)->value(); return Smi::cast(value)->value();
} }
Object* KeyToSymbol() { MUST_USE_RESULT MaybeObject* KeyToSymbol() {
if (!StringShape(key_).IsSymbol()) { if (!StringShape(key_).IsSymbol()) {
Object* result = Heap::LookupSymbol(key_); Object* result;
if (result->IsFailure()) return result; { MaybeObject* maybe_result = Heap::LookupSymbol(key_);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
key_ = String::cast(result); key_ = String::cast(result);
} }
return key_; return key_;

1393
deps/v8/src/runtime.cc

File diff suppressed because it is too large

45
deps/v8/src/runtime.h

@ -297,8 +297,6 @@ namespace internal {
F(Log, 2, 1) \ F(Log, 2, 1) \
/* ES5 */ \ /* ES5 */ \
F(LocalKeys, 1, 1) \ F(LocalKeys, 1, 1) \
/* Handle scopes */ \
F(DeleteHandleScopeExtensions, 0, 1) \
/* Cache suport */ \ /* Cache suport */ \
F(GetFromCache, 2, 1) \ F(GetFromCache, 2, 1) \
\ \
@ -488,7 +486,8 @@ class Runtime : public AllStatic {
// Returns failure if an allocation fails. In this case, it must be // Returns failure if an allocation fails. In this case, it must be
// retried with a new, empty StringDictionary, not with the same one. // retried with a new, empty StringDictionary, not with the same one.
// Alternatively, heap initialization can be completely restarted. // Alternatively, heap initialization can be completely restarted.
static Object* InitializeIntrinsicFunctionNames(Object* dictionary); MUST_USE_RESULT static MaybeObject* InitializeIntrinsicFunctionNames(
Object* dictionary);
// Get the intrinsic function with the given name, which must be a symbol. // Get the intrinsic function with the given name, which must be a symbol.
static Function* FunctionForSymbol(Handle<String> name); static Function* FunctionForSymbol(Handle<String> name);
@ -506,23 +505,29 @@ class Runtime : public AllStatic {
// Support getting the characters in a string using [] notation as // Support getting the characters in a string using [] notation as
// in Firefox/SpiderMonkey, Safari and Opera. // in Firefox/SpiderMonkey, Safari and Opera.
static Object* GetElementOrCharAt(Handle<Object> object, uint32_t index); MUST_USE_RESULT static MaybeObject* GetElementOrCharAt(Handle<Object> object,
static Object* GetElement(Handle<Object> object, uint32_t index); uint32_t index);
MUST_USE_RESULT static MaybeObject* GetElement(Handle<Object> object,
static Object* SetObjectProperty(Handle<Object> object, uint32_t index);
Handle<Object> key,
Handle<Object> value, MUST_USE_RESULT static MaybeObject* SetObjectProperty(
PropertyAttributes attr); Handle<Object> object,
Handle<Object> key,
static Object* ForceSetObjectProperty(Handle<JSObject> object, Handle<Object> value,
Handle<Object> key, PropertyAttributes attr);
Handle<Object> value,
PropertyAttributes attr); MUST_USE_RESULT static MaybeObject* ForceSetObjectProperty(
Handle<JSObject> object,
static Object* ForceDeleteObjectProperty(Handle<JSObject> object, Handle<Object> key,
Handle<Object> key); Handle<Object> value,
PropertyAttributes attr);
static Object* GetObjectProperty(Handle<Object> object, Handle<Object> key);
MUST_USE_RESULT static MaybeObject* ForceDeleteObjectProperty(
Handle<JSObject> object,
Handle<Object> key);
MUST_USE_RESULT static MaybeObject* GetObjectProperty(Handle<Object> object,
Handle<Object> key);
// This function is used in FunctionNameUsing* tests. // This function is used in FunctionNameUsing* tests.
static Object* FindSharedFunctionInfoInScript(Handle<Script> script, static Object* FindSharedFunctionInfoInScript(Handle<Script> script,

35
deps/v8/src/serialize.cc

@ -337,6 +337,11 @@ void ExternalReferenceTable::PopulateTable() {
3, 3,
"V8::Random"); "V8::Random");
Add(ExternalReference::delete_handle_scope_extensions().address(),
RUNTIME_ENTRY,
3,
"HandleScope::DeleteExtensions");
// Miscellaneous // Miscellaneous
Add(ExternalReference::the_hole_value_location().address(), Add(ExternalReference::the_hole_value_location().address(),
UNCLASSIFIED, UNCLASSIFIED,
@ -457,6 +462,18 @@ void ExternalReferenceTable::PopulateTable() {
UNCLASSIFIED, UNCLASSIFIED,
29, 29,
"TranscendentalCache::caches()"); "TranscendentalCache::caches()");
Add(ExternalReference::handle_scope_next_address().address(),
UNCLASSIFIED,
30,
"HandleScope::next");
Add(ExternalReference::handle_scope_limit_address().address(),
UNCLASSIFIED,
31,
"HandleScope::limit");
Add(ExternalReference::handle_scope_level_address().address(),
UNCLASSIFIED,
32,
"HandleScope::level");
} }
@ -538,14 +555,16 @@ Address Deserializer::Allocate(int space_index, Space* space, int size) {
if (!SpaceIsLarge(space_index)) { if (!SpaceIsLarge(space_index)) {
ASSERT(!SpaceIsPaged(space_index) || ASSERT(!SpaceIsPaged(space_index) ||
size <= Page::kPageSize - Page::kObjectStartOffset); size <= Page::kPageSize - Page::kObjectStartOffset);
Object* new_allocation; MaybeObject* maybe_new_allocation;
if (space_index == NEW_SPACE) { if (space_index == NEW_SPACE) {
new_allocation = reinterpret_cast<NewSpace*>(space)->AllocateRaw(size); maybe_new_allocation =
reinterpret_cast<NewSpace*>(space)->AllocateRaw(size);
} else { } else {
new_allocation = reinterpret_cast<PagedSpace*>(space)->AllocateRaw(size); maybe_new_allocation =
reinterpret_cast<PagedSpace*>(space)->AllocateRaw(size);
} }
Object* new_allocation = maybe_new_allocation->ToObjectUnchecked();
HeapObject* new_object = HeapObject::cast(new_allocation); HeapObject* new_object = HeapObject::cast(new_allocation);
ASSERT(!new_object->IsFailure());
address = new_object->address(); address = new_object->address();
high_water_[space_index] = address + size; high_water_[space_index] = address + size;
} else { } else {
@ -554,14 +573,14 @@ Address Deserializer::Allocate(int space_index, Space* space, int size) {
LargeObjectSpace* lo_space = reinterpret_cast<LargeObjectSpace*>(space); LargeObjectSpace* lo_space = reinterpret_cast<LargeObjectSpace*>(space);
Object* new_allocation; Object* new_allocation;
if (space_index == kLargeData) { if (space_index == kLargeData) {
new_allocation = lo_space->AllocateRaw(size); new_allocation = lo_space->AllocateRaw(size)->ToObjectUnchecked();
} else if (space_index == kLargeFixedArray) { } else if (space_index == kLargeFixedArray) {
new_allocation = lo_space->AllocateRawFixedArray(size); new_allocation =
lo_space->AllocateRawFixedArray(size)->ToObjectUnchecked();
} else { } else {
ASSERT_EQ(kLargeCode, space_index); ASSERT_EQ(kLargeCode, space_index);
new_allocation = lo_space->AllocateRawCode(size); new_allocation = lo_space->AllocateRawCode(size)->ToObjectUnchecked();
} }
ASSERT(!new_allocation->IsFailure());
HeapObject* new_object = HeapObject::cast(new_allocation); HeapObject* new_object = HeapObject::cast(new_allocation);
// Record all large objects in the same space. // Record all large objects in the same space.
address = new_object->address(); address = new_object->address();

8
deps/v8/src/spaces-inl.h

@ -430,7 +430,7 @@ HeapObject* PagedSpace::AllocateLinearly(AllocationInfo* alloc_info,
// Raw allocation. // Raw allocation.
Object* PagedSpace::AllocateRaw(int size_in_bytes) { MaybeObject* PagedSpace::AllocateRaw(int size_in_bytes) {
ASSERT(HasBeenSetup()); ASSERT(HasBeenSetup());
ASSERT_OBJECT_SIZE(size_in_bytes); ASSERT_OBJECT_SIZE(size_in_bytes);
HeapObject* object = AllocateLinearly(&allocation_info_, size_in_bytes); HeapObject* object = AllocateLinearly(&allocation_info_, size_in_bytes);
@ -444,7 +444,7 @@ Object* PagedSpace::AllocateRaw(int size_in_bytes) {
// Reallocating (and promoting) objects during a compacting collection. // Reallocating (and promoting) objects during a compacting collection.
Object* PagedSpace::MCAllocateRaw(int size_in_bytes) { MaybeObject* PagedSpace::MCAllocateRaw(int size_in_bytes) {
ASSERT(HasBeenSetup()); ASSERT(HasBeenSetup());
ASSERT_OBJECT_SIZE(size_in_bytes); ASSERT_OBJECT_SIZE(size_in_bytes);
HeapObject* object = AllocateLinearly(&mc_forwarding_info_, size_in_bytes); HeapObject* object = AllocateLinearly(&mc_forwarding_info_, size_in_bytes);
@ -471,8 +471,8 @@ HeapObject* LargeObjectChunk::GetObject() {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// LargeObjectSpace // LargeObjectSpace
Object* NewSpace::AllocateRawInternal(int size_in_bytes, MaybeObject* NewSpace::AllocateRawInternal(int size_in_bytes,
AllocationInfo* alloc_info) { AllocationInfo* alloc_info) {
Address new_top = alloc_info->top + size_in_bytes; Address new_top = alloc_info->top + size_in_bytes;
if (new_top > alloc_info->limit) return Failure::RetryAfterGC(); if (new_top > alloc_info->limit) return Failure::RetryAfterGC();

30
deps/v8/src/spaces.cc

@ -873,7 +873,7 @@ void PagedSpace::MarkAllPagesClean() {
} }
Object* PagedSpace::FindObject(Address addr) { MaybeObject* PagedSpace::FindObject(Address addr) {
// Note: this function can only be called before or after mark-compact GC // Note: this function can only be called before or after mark-compact GC
// because it accesses map pointers. // because it accesses map pointers.
ASSERT(!MarkCompactCollector::in_use()); ASSERT(!MarkCompactCollector::in_use());
@ -1804,7 +1804,7 @@ int OldSpaceFreeList::Free(Address start, int size_in_bytes) {
} }
Object* OldSpaceFreeList::Allocate(int size_in_bytes, int* wasted_bytes) { MaybeObject* OldSpaceFreeList::Allocate(int size_in_bytes, int* wasted_bytes) {
ASSERT(0 < size_in_bytes); ASSERT(0 < size_in_bytes);
ASSERT(size_in_bytes <= kMaxBlockSize); ASSERT(size_in_bytes <= kMaxBlockSize);
ASSERT(IsAligned(size_in_bytes, kPointerSize)); ASSERT(IsAligned(size_in_bytes, kPointerSize));
@ -1924,7 +1924,7 @@ void FixedSizeFreeList::Free(Address start) {
} }
Object* FixedSizeFreeList::Allocate() { MaybeObject* FixedSizeFreeList::Allocate() {
if (head_ == NULL) { if (head_ == NULL) {
return Failure::RetryAfterGC(owner_); return Failure::RetryAfterGC(owner_);
} }
@ -2187,9 +2187,10 @@ HeapObject* OldSpace::SlowAllocateRaw(int size_in_bytes) {
// is currently forbidden. // is currently forbidden.
if (!Heap::linear_allocation()) { if (!Heap::linear_allocation()) {
int wasted_bytes; int wasted_bytes;
Object* result = free_list_.Allocate(size_in_bytes, &wasted_bytes); Object* result;
MaybeObject* maybe = free_list_.Allocate(size_in_bytes, &wasted_bytes);
accounting_stats_.WasteBytes(wasted_bytes); accounting_stats_.WasteBytes(wasted_bytes);
if (!result->IsFailure()) { if (maybe->ToObject(&result)) {
accounting_stats_.AllocateBytes(size_in_bytes); accounting_stats_.AllocateBytes(size_in_bytes);
HeapObject* obj = HeapObject::cast(result); HeapObject* obj = HeapObject::cast(result);
@ -2495,8 +2496,9 @@ HeapObject* FixedSpace::SlowAllocateRaw(int size_in_bytes) {
// that is currently forbidden. The fixed space free list implicitly assumes // that is currently forbidden. The fixed space free list implicitly assumes
// that all free blocks are of the fixed size. // that all free blocks are of the fixed size.
if (!Heap::linear_allocation()) { if (!Heap::linear_allocation()) {
Object* result = free_list_.Allocate(); Object* result;
if (!result->IsFailure()) { MaybeObject* maybe = free_list_.Allocate();
if (maybe->ToObject(&result)) {
accounting_stats_.AllocateBytes(size_in_bytes); accounting_stats_.AllocateBytes(size_in_bytes);
HeapObject* obj = HeapObject::cast(result); HeapObject* obj = HeapObject::cast(result);
Page* p = Page::FromAddress(obj->address()); Page* p = Page::FromAddress(obj->address());
@ -2745,9 +2747,9 @@ void LargeObjectSpace::Unprotect() {
#endif #endif
Object* LargeObjectSpace::AllocateRawInternal(int requested_size, MaybeObject* LargeObjectSpace::AllocateRawInternal(int requested_size,
int object_size, int object_size,
Executability executable) { Executability executable) {
ASSERT(0 < object_size && object_size <= requested_size); ASSERT(0 < object_size && object_size <= requested_size);
// Check if we want to force a GC before growing the old space further. // Check if we want to force a GC before growing the old space further.
@ -2783,7 +2785,7 @@ Object* LargeObjectSpace::AllocateRawInternal(int requested_size,
} }
Object* LargeObjectSpace::AllocateRawCode(int size_in_bytes) { MaybeObject* LargeObjectSpace::AllocateRawCode(int size_in_bytes) {
ASSERT(0 < size_in_bytes); ASSERT(0 < size_in_bytes);
return AllocateRawInternal(size_in_bytes, return AllocateRawInternal(size_in_bytes,
size_in_bytes, size_in_bytes,
@ -2791,7 +2793,7 @@ Object* LargeObjectSpace::AllocateRawCode(int size_in_bytes) {
} }
Object* LargeObjectSpace::AllocateRawFixedArray(int size_in_bytes) { MaybeObject* LargeObjectSpace::AllocateRawFixedArray(int size_in_bytes) {
ASSERT(0 < size_in_bytes); ASSERT(0 < size_in_bytes);
return AllocateRawInternal(size_in_bytes, return AllocateRawInternal(size_in_bytes,
size_in_bytes, size_in_bytes,
@ -2799,7 +2801,7 @@ Object* LargeObjectSpace::AllocateRawFixedArray(int size_in_bytes) {
} }
Object* LargeObjectSpace::AllocateRaw(int size_in_bytes) { MaybeObject* LargeObjectSpace::AllocateRaw(int size_in_bytes) {
ASSERT(0 < size_in_bytes); ASSERT(0 < size_in_bytes);
return AllocateRawInternal(size_in_bytes, return AllocateRawInternal(size_in_bytes,
size_in_bytes, size_in_bytes,
@ -2808,7 +2810,7 @@ Object* LargeObjectSpace::AllocateRaw(int size_in_bytes) {
// GC support // GC support
Object* LargeObjectSpace::FindObject(Address a) { MaybeObject* LargeObjectSpace::FindObject(Address a) {
for (LargeObjectChunk* chunk = first_chunk_; for (LargeObjectChunk* chunk = first_chunk_;
chunk != NULL; chunk != NULL;
chunk = chunk->next()) { chunk = chunk->next()) {

50
deps/v8/src/spaces.h

@ -425,7 +425,8 @@ class CodeRange : public AllStatic {
// Allocates a chunk of memory from the large-object portion of // Allocates a chunk of memory from the large-object portion of
// the code range. On platforms with no separate code range, should // the code range. On platforms with no separate code range, should
// not be called. // not be called.
static void* AllocateRawMemory(const size_t requested, size_t* allocated); MUST_USE_RESULT static void* AllocateRawMemory(const size_t requested,
size_t* allocated);
static void FreeRawMemory(void* buf, size_t length); static void FreeRawMemory(void* buf, size_t length);
private: private:
@ -563,9 +564,9 @@ class MemoryAllocator : public AllStatic {
// If the flag is EXECUTABLE and a code range exists, the requested // If the flag is EXECUTABLE and a code range exists, the requested
// memory is allocated from the code range. If a code range exists // memory is allocated from the code range. If a code range exists
// and the freed memory is in it, the code range manages the freed memory. // and the freed memory is in it, the code range manages the freed memory.
static void* AllocateRawMemory(const size_t requested, MUST_USE_RESULT static void* AllocateRawMemory(const size_t requested,
size_t* allocated, size_t* allocated,
Executability executable); Executability executable);
static void FreeRawMemory(void* buf, static void FreeRawMemory(void* buf,
size_t length, size_t length,
Executability executable); Executability executable);
@ -1010,7 +1011,7 @@ class PagedSpace : public Space {
// in this space, or Failure::Exception() if it is not. The implementation // in this space, or Failure::Exception() if it is not. The implementation
// iterates over objects in the page containing the address, the cost is // iterates over objects in the page containing the address, the cost is
// linear in the number of objects in the page. It may be slow. // linear in the number of objects in the page. It may be slow.
Object* FindObject(Address addr); MUST_USE_RESULT MaybeObject* FindObject(Address addr);
// Checks whether page is currently in use by this space. // Checks whether page is currently in use by this space.
bool IsUsed(Page* page); bool IsUsed(Page* page);
@ -1059,11 +1060,11 @@ class PagedSpace : public Space {
// Allocate the requested number of bytes in the space if possible, return a // Allocate the requested number of bytes in the space if possible, return a
// failure object if not. // failure object if not.
inline Object* AllocateRaw(int size_in_bytes); MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes);
// Allocate the requested number of bytes for relocation during mark-compact // Allocate the requested number of bytes for relocation during mark-compact
// collection. // collection.
inline Object* MCAllocateRaw(int size_in_bytes); MUST_USE_RESULT inline MaybeObject* MCAllocateRaw(int size_in_bytes);
virtual bool ReserveSpace(int bytes); virtual bool ReserveSpace(int bytes);
@ -1206,10 +1207,10 @@ class PagedSpace : public Space {
int size_in_bytes) = 0; int size_in_bytes) = 0;
// Slow path of AllocateRaw. This function is space-dependent. // Slow path of AllocateRaw. This function is space-dependent.
virtual HeapObject* SlowAllocateRaw(int size_in_bytes) = 0; MUST_USE_RESULT virtual HeapObject* SlowAllocateRaw(int size_in_bytes) = 0;
// Slow path of MCAllocateRaw. // Slow path of MCAllocateRaw.
HeapObject* SlowMCAllocateRaw(int size_in_bytes); MUST_USE_RESULT HeapObject* SlowMCAllocateRaw(int size_in_bytes);
#ifdef DEBUG #ifdef DEBUG
// Returns the number of total pages in this space. // Returns the number of total pages in this space.
@ -1527,13 +1528,13 @@ class NewSpace : public Space {
Address* allocation_top_address() { return &allocation_info_.top; } Address* allocation_top_address() { return &allocation_info_.top; }
Address* allocation_limit_address() { return &allocation_info_.limit; } Address* allocation_limit_address() { return &allocation_info_.limit; }
Object* AllocateRaw(int size_in_bytes) { MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes) {
return AllocateRawInternal(size_in_bytes, &allocation_info_); return AllocateRawInternal(size_in_bytes, &allocation_info_);
} }
// Allocate the requested number of bytes for relocation during mark-compact // Allocate the requested number of bytes for relocation during mark-compact
// collection. // collection.
Object* MCAllocateRaw(int size_in_bytes) { MUST_USE_RESULT MaybeObject* MCAllocateRaw(int size_in_bytes) {
return AllocateRawInternal(size_in_bytes, &mc_forwarding_info_); return AllocateRawInternal(size_in_bytes, &mc_forwarding_info_);
} }
@ -1635,8 +1636,9 @@ class NewSpace : public Space {
#endif #endif
// Implementation of AllocateRaw and MCAllocateRaw. // Implementation of AllocateRaw and MCAllocateRaw.
inline Object* AllocateRawInternal(int size_in_bytes, MUST_USE_RESULT inline MaybeObject* AllocateRawInternal(
AllocationInfo* alloc_info); int size_in_bytes,
AllocationInfo* alloc_info);
friend class SemiSpaceIterator; friend class SemiSpaceIterator;
@ -1703,7 +1705,7 @@ class OldSpaceFreeList BASE_EMBEDDED {
// is unitialized. A failure is returned if no block is available. The // is unitialized. A failure is returned if no block is available. The
// number of bytes lost to fragmentation is returned in the output parameter // number of bytes lost to fragmentation is returned in the output parameter
// 'wasted_bytes'. The size should be a non-zero multiple of the word size. // 'wasted_bytes'. The size should be a non-zero multiple of the word size.
Object* Allocate(int size_in_bytes, int* wasted_bytes); MUST_USE_RESULT MaybeObject* Allocate(int size_in_bytes, int* wasted_bytes);
private: private:
// The size range of blocks, in bytes. (Smaller allocations are allowed, but // The size range of blocks, in bytes. (Smaller allocations are allowed, but
@ -1801,7 +1803,7 @@ class FixedSizeFreeList BASE_EMBEDDED {
// Allocate a fixed sized block from the free list. The block is unitialized. // Allocate a fixed sized block from the free list. The block is unitialized.
// A failure is returned if no block is available. // A failure is returned if no block is available.
Object* Allocate(); MUST_USE_RESULT MaybeObject* Allocate();
private: private:
// Available bytes on the free list. // Available bytes on the free list.
@ -1881,7 +1883,7 @@ class OldSpace : public PagedSpace {
protected: protected:
// Virtual function in the superclass. Slow path of AllocateRaw. // Virtual function in the superclass. Slow path of AllocateRaw.
HeapObject* SlowAllocateRaw(int size_in_bytes); MUST_USE_RESULT HeapObject* SlowAllocateRaw(int size_in_bytes);
// Virtual function in the superclass. Allocate linearly at the start of // Virtual function in the superclass. Allocate linearly at the start of
// the page after current_page (there is assumed to be one). // the page after current_page (there is assumed to be one).
@ -1948,7 +1950,7 @@ class FixedSpace : public PagedSpace {
protected: protected:
// Virtual function in the superclass. Slow path of AllocateRaw. // Virtual function in the superclass. Slow path of AllocateRaw.
HeapObject* SlowAllocateRaw(int size_in_bytes); MUST_USE_RESULT HeapObject* SlowAllocateRaw(int size_in_bytes);
// Virtual function in the superclass. Allocate linearly at the start of // Virtual function in the superclass. Allocate linearly at the start of
// the page after current_page (there is assumed to be one). // the page after current_page (there is assumed to be one).
@ -2166,11 +2168,11 @@ class LargeObjectSpace : public Space {
void TearDown(); void TearDown();
// Allocates a (non-FixedArray, non-Code) large object. // Allocates a (non-FixedArray, non-Code) large object.
Object* AllocateRaw(int size_in_bytes); MUST_USE_RESULT MaybeObject* AllocateRaw(int size_in_bytes);
// Allocates a large Code object. // Allocates a large Code object.
Object* AllocateRawCode(int size_in_bytes); MUST_USE_RESULT MaybeObject* AllocateRawCode(int size_in_bytes);
// Allocates a large FixedArray. // Allocates a large FixedArray.
Object* AllocateRawFixedArray(int size_in_bytes); MUST_USE_RESULT MaybeObject* AllocateRawFixedArray(int size_in_bytes);
// Available bytes for objects in this space. // Available bytes for objects in this space.
intptr_t Available() { intptr_t Available() {
@ -2188,7 +2190,7 @@ class LargeObjectSpace : public Space {
// Finds an object for a given address, returns Failure::Exception() // Finds an object for a given address, returns Failure::Exception()
// if it is not found. The function iterates through all objects in this // if it is not found. The function iterates through all objects in this
// space, may be slow. // space, may be slow.
Object* FindObject(Address a); MaybeObject* FindObject(Address a);
// Finds a large object page containing the given pc, returns NULL // Finds a large object page containing the given pc, returns NULL
// if such a page doesn't exist. // if such a page doesn't exist.
@ -2236,9 +2238,9 @@ class LargeObjectSpace : public Space {
// Shared implementation of AllocateRaw, AllocateRawCode and // Shared implementation of AllocateRaw, AllocateRawCode and
// AllocateRawFixedArray. // AllocateRawFixedArray.
Object* AllocateRawInternal(int requested_size, MUST_USE_RESULT MaybeObject* AllocateRawInternal(int requested_size,
int object_size, int object_size,
Executability executable); Executability executable);
friend class LargeObjectIterator; friend class LargeObjectIterator;

205
deps/v8/src/strtod.cc

@ -31,7 +31,8 @@
#include "v8.h" #include "v8.h"
#include "strtod.h" #include "strtod.h"
// #include "cached-powers.h" #include "cached-powers.h"
#include "double.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -40,9 +41,9 @@ namespace internal {
// Any integer with at most 15 decimal digits will hence fit into a double // Any integer with at most 15 decimal digits will hence fit into a double
// (which has a 53bit significand) without loss of precision. // (which has a 53bit significand) without loss of precision.
static const int kMaxExactDoubleIntegerDecimalDigits = 15; static const int kMaxExactDoubleIntegerDecimalDigits = 15;
// 2^64 = 18446744073709551616 // 2^64 = 18446744073709551616 > 10^19
// Any integer with at most 19 digits will hence fit into a 64bit datatype.
static const int kMaxUint64DecimalDigits = 19; static const int kMaxUint64DecimalDigits = 19;
// Max double: 1.7976931348623157 x 10^308 // Max double: 1.7976931348623157 x 10^308
// Min non-zero double: 4.9406564584124654 x 10^-324 // Min non-zero double: 4.9406564584124654 x 10^-324
// Any x >= 10^309 is interpreted as +infinity. // Any x >= 10^309 is interpreted as +infinity.
@ -52,6 +53,10 @@ static const int kMaxUint64DecimalDigits = 19;
static const int kMaxDecimalPower = 309; static const int kMaxDecimalPower = 309;
static const int kMinDecimalPower = -324; static const int kMinDecimalPower = -324;
// 2^64 = 18446744073709551616
static const uint64_t kMaxUint64 = V8_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF);
static const double exact_powers_of_ten[] = { static const double exact_powers_of_ten[] = {
1.0, // 10^0 1.0, // 10^0
10.0, 10.0,
@ -120,7 +125,7 @@ static double old_strtod(Vector<const char> buffer, int exponent) {
static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) { static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
for (int i = 0; i < buffer.length(); i++) { for (int i = 0; i < buffer.length(); i++) {
if (buffer[i] != '0') { if (buffer[i] != '0') {
return Vector<const char>(buffer.start() + i, buffer.length() - i); return buffer.SubVector(i, buffer.length());
} }
} }
return Vector<const char>(buffer.start(), 0); return Vector<const char>(buffer.start(), 0);
@ -130,25 +135,57 @@ static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) {
static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) { static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) {
for (int i = buffer.length() - 1; i >= 0; --i) { for (int i = buffer.length() - 1; i >= 0; --i) {
if (buffer[i] != '0') { if (buffer[i] != '0') {
return Vector<const char>(buffer.start(), i + 1); return buffer.SubVector(0, i + 1);
} }
} }
return Vector<const char>(buffer.start(), 0); return Vector<const char>(buffer.start(), 0);
} }
uint64_t ReadUint64(Vector<const char> buffer) { // Reads digits from the buffer and converts them to a uint64.
ASSERT(buffer.length() <= kMaxUint64DecimalDigits); // Reads in as many digits as fit into a uint64.
// When the string starts with "1844674407370955161" no further digit is read.
// Since 2^64 = 18446744073709551616 it would still be possible read another
// digit if it was less or equal than 6, but this would complicate the code.
static uint64_t ReadUint64(Vector<const char> buffer,
int* number_of_read_digits) {
uint64_t result = 0; uint64_t result = 0;
for (int i = 0; i < buffer.length(); ++i) { int i = 0;
int digit = buffer[i] - '0'; while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) {
int digit = buffer[i++] - '0';
ASSERT(0 <= digit && digit <= 9); ASSERT(0 <= digit && digit <= 9);
result = 10 * result + digit; result = 10 * result + digit;
} }
*number_of_read_digits = i;
return result; return result;
} }
// Reads a DiyFp from the buffer.
// The returned DiyFp is not necessarily normalized.
// If remaining_decimals is zero then the returned DiyFp is accurate.
// Otherwise it has been rounded and has error of at most 1/2 ulp.
static void ReadDiyFp(Vector<const char> buffer,
DiyFp* result,
int* remaining_decimals) {
int read_digits;
uint64_t significand = ReadUint64(buffer, &read_digits);
if (buffer.length() == read_digits) {
*result = DiyFp(significand, 0);
*remaining_decimals = 0;
} else {
// Round the significand.
if (buffer[read_digits] >= '5') {
significand++;
}
// Compute the binary exponent.
int exponent = 0;
*result = DiyFp(significand, exponent);
*remaining_decimals = buffer.length() - read_digits;
}
}
static bool DoubleStrtod(Vector<const char> trimmed, static bool DoubleStrtod(Vector<const char> trimmed,
int exponent, int exponent,
double* result) { double* result) {
@ -162,6 +199,7 @@ static bool DoubleStrtod(Vector<const char> trimmed,
return false; return false;
#endif #endif
if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) {
int read_digits;
// The trimmed input fits into a double. // The trimmed input fits into a double.
// If the 10^exponent (resp. 10^-exponent) fits into a double too then we // If the 10^exponent (resp. 10^-exponent) fits into a double too then we
// can compute the result-double simply by multiplying (resp. dividing) the // can compute the result-double simply by multiplying (resp. dividing) the
@ -170,13 +208,15 @@ static bool DoubleStrtod(Vector<const char> trimmed,
// return the best possible approximation. // return the best possible approximation.
if (exponent < 0 && -exponent < kExactPowersOfTenSize) { if (exponent < 0 && -exponent < kExactPowersOfTenSize) {
// 10^-exponent fits into a double. // 10^-exponent fits into a double.
*result = static_cast<double>(ReadUint64(trimmed)); *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
ASSERT(read_digits == trimmed.length());
*result /= exact_powers_of_ten[-exponent]; *result /= exact_powers_of_ten[-exponent];
return true; return true;
} }
if (0 <= exponent && exponent < kExactPowersOfTenSize) { if (0 <= exponent && exponent < kExactPowersOfTenSize) {
// 10^exponent fits into a double. // 10^exponent fits into a double.
*result = static_cast<double>(ReadUint64(trimmed)); *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
ASSERT(read_digits == trimmed.length());
*result *= exact_powers_of_ten[exponent]; *result *= exact_powers_of_ten[exponent];
return true; return true;
} }
@ -187,7 +227,8 @@ static bool DoubleStrtod(Vector<const char> trimmed,
// The trimmed string was short and we can multiply it with // The trimmed string was short and we can multiply it with
// 10^remaining_digits. As a result the remaining exponent now fits // 10^remaining_digits. As a result the remaining exponent now fits
// into a double too. // into a double too.
*result = static_cast<double>(ReadUint64(trimmed)); *result = static_cast<double>(ReadUint64(trimmed, &read_digits));
ASSERT(read_digits == trimmed.length());
*result *= exact_powers_of_ten[remaining_digits]; *result *= exact_powers_of_ten[remaining_digits];
*result *= exact_powers_of_ten[exponent - remaining_digits]; *result *= exact_powers_of_ten[exponent - remaining_digits];
return true; return true;
@ -197,6 +238,142 @@ static bool DoubleStrtod(Vector<const char> trimmed,
} }
// Returns 10^exponent as an exact DiyFp.
// The given exponent must be in the range [1; kDecimalExponentDistance[.
static DiyFp AdjustmentPowerOfTen(int exponent) {
ASSERT(0 < exponent);
ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance);
// Simply hardcode the remaining powers for the given decimal exponent
// distance.
ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8);
switch (exponent) {
case 1: return DiyFp(V8_2PART_UINT64_C(0xa0000000, 00000000), -60);
case 2: return DiyFp(V8_2PART_UINT64_C(0xc8000000, 00000000), -57);
case 3: return DiyFp(V8_2PART_UINT64_C(0xfa000000, 00000000), -54);
case 4: return DiyFp(V8_2PART_UINT64_C(0x9c400000, 00000000), -50);
case 5: return DiyFp(V8_2PART_UINT64_C(0xc3500000, 00000000), -47);
case 6: return DiyFp(V8_2PART_UINT64_C(0xf4240000, 00000000), -44);
case 7: return DiyFp(V8_2PART_UINT64_C(0x98968000, 00000000), -40);
default:
UNREACHABLE();
return DiyFp(0, 0);
}
}
// If the function returns true then the result is the correct double.
// Otherwise it is either the correct double or the double that is just below
// the correct double.
static bool DiyFpStrtod(Vector<const char> buffer,
int exponent,
double* result) {
DiyFp input;
int remaining_decimals;
ReadDiyFp(buffer, &input, &remaining_decimals);
// Since we may have dropped some digits the input is not accurate.
// If remaining_decimals is different than 0 than the error is at most
// .5 ulp (unit in the last place).
// We don't want to deal with fractions and therefore keep a common
// denominator.
const int kDenominatorLog = 3;
const int kDenominator = 1 << kDenominatorLog;
// Move the remaining decimals into the exponent.
exponent += remaining_decimals;
int error = (remaining_decimals == 0 ? 0 : kDenominator / 2);
int old_e = input.e();
input.Normalize();
error <<= old_e - input.e();
ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent);
if (exponent < PowersOfTenCache::kMinDecimalExponent) {
*result = 0.0;
return true;
}
DiyFp cached_power;
int cached_decimal_exponent;
PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent,
&cached_power,
&cached_decimal_exponent);
if (cached_decimal_exponent != exponent) {
int adjustment_exponent = exponent - cached_decimal_exponent;
DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent);
input.Multiply(adjustment_power);
if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) {
// The product of input with the adjustment power fits into a 64 bit
// integer.
ASSERT(DiyFp::kSignificandSize == 64);
} else {
// The adjustment power is exact. There is hence only an error of 0.5.
error += kDenominator / 2;
}
}
input.Multiply(cached_power);
// The error introduced by a multiplication of a*b equals
// error_a + error_b + error_a*error_b/2^64 + 0.5
// Substituting a with 'input' and b with 'cached_power' we have
// error_b = 0.5 (all cached powers have an error of less than 0.5 ulp),
// error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64
int error_b = kDenominator / 2;
int error_ab = (error == 0 ? 0 : 1); // We round up to 1.
int fixed_error = kDenominator / 2;
error += error_b + error_ab + fixed_error;
old_e = input.e();
input.Normalize();
error <<= old_e - input.e();
// See if the double's significand changes if we add/subtract the error.
int order_of_magnitude = DiyFp::kSignificandSize + input.e();
int effective_significand_size =
Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude);
int precision_digits_count =
DiyFp::kSignificandSize - effective_significand_size;
if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) {
// This can only happen for very small denormals. In this case the
// half-way multiplied by the denominator exceeds the range of an uint64.
// Simply shift everything to the right.
int shift_amount = (precision_digits_count + kDenominatorLog) -
DiyFp::kSignificandSize + 1;
input.set_f(input.f() >> shift_amount);
input.set_e(input.e() + shift_amount);
// We add 1 for the lost precision of error, and kDenominator for
// the lost precision of input.f().
error = (error >> shift_amount) + 1 + kDenominator;
precision_digits_count -= shift_amount;
}
// We use uint64_ts now. This only works if the DiyFp uses uint64_ts too.
ASSERT(DiyFp::kSignificandSize == 64);
ASSERT(precision_digits_count < 64);
uint64_t one64 = 1;
uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1;
uint64_t precision_bits = input.f() & precision_bits_mask;
uint64_t half_way = one64 << (precision_digits_count - 1);
precision_bits *= kDenominator;
half_way *= kDenominator;
DiyFp rounded_input(input.f() >> precision_digits_count,
input.e() + precision_digits_count);
if (precision_bits >= half_way + error) {
rounded_input.set_f(rounded_input.f() + 1);
}
// If the last_bits are too close to the half-way case than we are too
// inaccurate and round down. In this case we return false so that we can
// fall back to a more precise algorithm.
*result = Double(rounded_input).value();
if (half_way - error < precision_bits && precision_bits < half_way + error) {
// Too imprecise. The caller will have to fall back to a slower version.
// However the returned number is guaranteed to be either the correct
// double, or the next-lower double.
return false;
} else {
return true;
}
}
double Strtod(Vector<const char> buffer, int exponent) { double Strtod(Vector<const char> buffer, int exponent) {
Vector<const char> left_trimmed = TrimLeadingZeros(buffer); Vector<const char> left_trimmed = TrimLeadingZeros(buffer);
Vector<const char> trimmed = TrimTrailingZeros(left_trimmed); Vector<const char> trimmed = TrimTrailingZeros(left_trimmed);
@ -204,8 +381,10 @@ double Strtod(Vector<const char> buffer, int exponent) {
if (trimmed.length() == 0) return 0.0; if (trimmed.length() == 0) return 0.0;
if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY; if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY;
if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0; if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0;
double result; double result;
if (DoubleStrtod(trimmed, exponent, &result)) { if (DoubleStrtod(trimmed, exponent, &result) ||
DiyFpStrtod(trimmed, exponent, &result)) {
return result; return result;
} }
return old_strtod(trimmed, exponent); return old_strtod(trimmed, exponent);

827
deps/v8/src/stub-cache.cc

File diff suppressed because it is too large

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

@ -56,155 +56,169 @@ class StubCache : public AllStatic {
// Computes the right stub matching. Inserts the result in the // Computes the right stub matching. Inserts the result in the
// cache before returning. This might compile a stub if needed. // cache before returning. This might compile a stub if needed.
MUST_USE_RESULT static Object* ComputeLoadNonexistent(String* name, MUST_USE_RESULT static MaybeObject* ComputeLoadNonexistent(
JSObject* receiver); String* name,
JSObject* receiver);
MUST_USE_RESULT static Object* ComputeLoadField(String* name,
JSObject* receiver,
JSObject* holder,
int field_index);
MUST_USE_RESULT static Object* ComputeLoadCallback(String* name,
JSObject* receiver,
JSObject* holder,
AccessorInfo* callback);
MUST_USE_RESULT static Object* ComputeLoadConstant(String* name,
JSObject* receiver,
JSObject* holder,
Object* value);
MUST_USE_RESULT static Object* ComputeLoadInterceptor(String* name,
JSObject* receiver,
JSObject* holder);
MUST_USE_RESULT static Object* ComputeLoadNormal();
MUST_USE_RESULT static Object* ComputeLoadGlobal(String* name,
JSObject* receiver,
GlobalObject* holder,
JSGlobalPropertyCell* cell,
bool is_dont_delete);
// ---
MUST_USE_RESULT static Object* ComputeKeyedLoadField(String* name, MUST_USE_RESULT static MaybeObject* ComputeLoadField(String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder, JSObject* holder,
int field_index); int field_index);
MUST_USE_RESULT static Object* ComputeKeyedLoadCallback( MUST_USE_RESULT static MaybeObject* ComputeLoadCallback(
String* name, String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder, JSObject* holder,
AccessorInfo* callback); AccessorInfo* callback);
MUST_USE_RESULT static Object* ComputeKeyedLoadConstant(String* name, MUST_USE_RESULT static MaybeObject* ComputeLoadConstant(String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder, JSObject* holder,
Object* value); Object* value);
MUST_USE_RESULT static Object* ComputeKeyedLoadInterceptor(String* name, MUST_USE_RESULT static MaybeObject* ComputeLoadInterceptor(String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder); JSObject* holder);
MUST_USE_RESULT static Object* ComputeKeyedLoadArrayLength(String* name, MUST_USE_RESULT static MaybeObject* ComputeLoadNormal();
JSArray* receiver);
MUST_USE_RESULT static Object* ComputeKeyedLoadStringLength(String* name,
String* receiver);
MUST_USE_RESULT static Object* ComputeKeyedLoadFunctionPrototype( MUST_USE_RESULT static MaybeObject* ComputeLoadGlobal(
String* name, String* name,
JSFunction* receiver); JSObject* receiver,
GlobalObject* holder,
JSGlobalPropertyCell* cell,
bool is_dont_delete);
// --- // ---
MUST_USE_RESULT static Object* ComputeStoreField(String* name, MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadField(String* name,
JSObject* receiver, JSObject* receiver,
int field_index, JSObject* holder,
Map* transition = NULL); int field_index);
MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadCallback(
String* name,
JSObject* receiver,
JSObject* holder,
AccessorInfo* callback);
MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadConstant(
String* name,
JSObject* receiver,
JSObject* holder,
Object* value);
MUST_USE_RESULT static Object* ComputeStoreNormal(); MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadInterceptor(
String* name,
JSObject* receiver,
JSObject* holder);
MUST_USE_RESULT static Object* ComputeStoreGlobal(String* name, MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadArrayLength(
GlobalObject* receiver, String* name,
JSGlobalPropertyCell* cell); JSArray* receiver);
MUST_USE_RESULT static Object* ComputeStoreCallback(String* name, MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadStringLength(
JSObject* receiver, String* name,
AccessorInfo* callback); String* receiver);
MUST_USE_RESULT static Object* ComputeStoreInterceptor(String* name, MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadFunctionPrototype(
JSObject* receiver); String* name,
JSFunction* receiver);
// --- // ---
MUST_USE_RESULT static Object* ComputeKeyedStoreField(String* name, MUST_USE_RESULT static MaybeObject* ComputeStoreField(String* name,
JSObject* receiver, JSObject* receiver,
int field_index, int field_index,
Map* transition = NULL); Map* transition = NULL);
MUST_USE_RESULT static MaybeObject* ComputeStoreNormal();
MUST_USE_RESULT static MaybeObject* ComputeStoreGlobal(
String* name,
GlobalObject* receiver,
JSGlobalPropertyCell* cell);
MUST_USE_RESULT static MaybeObject* ComputeStoreCallback(
String* name,
JSObject* receiver,
AccessorInfo* callback);
MUST_USE_RESULT static MaybeObject* ComputeStoreInterceptor(
String* name,
JSObject* receiver);
// --- // ---
MUST_USE_RESULT static Object* ComputeCallField(int argc, MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreField(
InLoopFlag in_loop, String* name,
Code::Kind, JSObject* receiver,
String* name, int field_index,
Object* object, Map* transition = NULL);
JSObject* holder,
int index); // ---
MUST_USE_RESULT static Object* ComputeCallConstant(int argc, MUST_USE_RESULT static MaybeObject* ComputeCallField(int argc,
InLoopFlag in_loop, InLoopFlag in_loop,
Code::Kind, Code::Kind,
String* name, String* name,
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSFunction* function); int index);
MUST_USE_RESULT static Object* ComputeCallNormal(int argc, MUST_USE_RESULT static MaybeObject* ComputeCallConstant(int argc,
InLoopFlag in_loop, InLoopFlag in_loop,
Code::Kind, Code::Kind,
String* name, String* name,
JSObject* receiver); Object* object,
JSObject* holder,
JSFunction* function);
MUST_USE_RESULT static Object* ComputeCallInterceptor(int argc, MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
InLoopFlag in_loop,
Code::Kind, Code::Kind,
String* name, String* name,
Object* object, JSObject* receiver);
JSObject* holder);
MUST_USE_RESULT static Object* ComputeCallGlobal(int argc, MUST_USE_RESULT static MaybeObject* ComputeCallInterceptor(int argc,
InLoopFlag in_loop, Code::Kind,
Code::Kind, String* name,
String* name, Object* object,
JSObject* receiver, JSObject* holder);
GlobalObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function);
// --- MUST_USE_RESULT static MaybeObject* ComputeCallGlobal(
int argc,
InLoopFlag in_loop,
Code::Kind,
String* name,
JSObject* receiver,
GlobalObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function);
MUST_USE_RESULT static Object* ComputeCallInitialize(int argc, // ---
InLoopFlag in_loop,
Code::Kind kind);
MUST_USE_RESULT static Object* ComputeCallPreMonomorphic(int argc, MUST_USE_RESULT static MaybeObject* ComputeCallInitialize(int argc,
InLoopFlag in_loop, InLoopFlag in_loop,
Code::Kind kind); Code::Kind kind);
MUST_USE_RESULT static Object* ComputeCallNormal(int argc, MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic(
InLoopFlag in_loop, int argc,
Code::Kind kind); InLoopFlag in_loop,
Code::Kind kind);
MUST_USE_RESULT static Object* ComputeCallMegamorphic(int argc, MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
InLoopFlag in_loop, InLoopFlag in_loop,
Code::Kind kind); Code::Kind kind);
MUST_USE_RESULT static Object* ComputeCallMiss(int argc, Code::Kind kind); MUST_USE_RESULT static MaybeObject* ComputeCallMegamorphic(int argc,
InLoopFlag in_loop,
Code::Kind kind);
MUST_USE_RESULT static MaybeObject* ComputeCallMiss(int argc,
Code::Kind kind);
// Finds the Code object stored in the Heap::non_monomorphic_cache(). // Finds the Code object stored in the Heap::non_monomorphic_cache().
MUST_USE_RESULT static Code* FindCallInitialize(int argc, MUST_USE_RESULT static Code* FindCallInitialize(int argc,
@ -212,11 +226,12 @@ class StubCache : public AllStatic {
Code::Kind kind); Code::Kind kind);
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
MUST_USE_RESULT static Object* ComputeCallDebugBreak(int argc, MUST_USE_RESULT static MaybeObject* ComputeCallDebugBreak(int argc,
Code::Kind kind); Code::Kind kind);
MUST_USE_RESULT static Object* ComputeCallDebugPrepareStepIn(int argc, MUST_USE_RESULT static MaybeObject* ComputeCallDebugPrepareStepIn(
Code::Kind kind); int argc,
Code::Kind kind);
#endif #endif
// Update cache for entry hash(name, map). // Update cache for entry hash(name, map).
@ -329,17 +344,17 @@ class SCTableReference {
// Support functions for IC stubs for callbacks. // Support functions for IC stubs for callbacks.
Object* LoadCallbackProperty(Arguments args); MaybeObject* LoadCallbackProperty(Arguments args);
Object* StoreCallbackProperty(Arguments args); MaybeObject* StoreCallbackProperty(Arguments args);
// Support functions for IC stubs for interceptors. // Support functions for IC stubs for interceptors.
Object* LoadPropertyWithInterceptorOnly(Arguments args); MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args);
Object* LoadPropertyWithInterceptorForLoad(Arguments args); MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args);
Object* LoadPropertyWithInterceptorForCall(Arguments args); MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args);
Object* StoreInterceptorProperty(Arguments args); MaybeObject* StoreInterceptorProperty(Arguments args);
Object* CallInterceptorProperty(Arguments args); MaybeObject* CallInterceptorProperty(Arguments args);
Object* KeyedLoadPropertyWithInterceptor(Arguments args); MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args);
// The stub compiler compiles stubs for the stub cache. // The stub compiler compiles stubs for the stub cache.
@ -354,14 +369,14 @@ class StubCompiler BASE_EMBEDDED {
StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { } StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
Object* CompileCallInitialize(Code::Flags flags); MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags);
Object* CompileCallPreMonomorphic(Code::Flags flags); MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags);
Object* CompileCallNormal(Code::Flags flags); MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags);
Object* CompileCallMegamorphic(Code::Flags flags); MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags);
Object* CompileCallMiss(Code::Flags flags); MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags);
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
Object* CompileCallDebugBreak(Code::Flags flags); MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags);
Object* CompileCallDebugPrepareStepIn(Code::Flags flags); MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags);
#endif #endif
// Static functions for generating parts of stubs. // Static functions for generating parts of stubs.
@ -451,8 +466,8 @@ class StubCompiler BASE_EMBEDDED {
Label* miss); Label* miss);
protected: protected:
Object* GetCodeWithFlags(Code::Flags flags, const char* name); MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name);
Object* GetCodeWithFlags(Code::Flags flags, String* name); MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name);
MacroAssembler* masm() { return &masm_; } MacroAssembler* masm() { return &masm_; }
void set_failure(Failure* failure) { failure_ = failure; } void set_failure(Failure* failure) { failure_ = failure; }
@ -513,99 +528,100 @@ class StubCompiler BASE_EMBEDDED {
class LoadStubCompiler: public StubCompiler { class LoadStubCompiler: public StubCompiler {
public: public:
Object* CompileLoadNonexistent(String* name, MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
JSObject* object, JSObject* object,
JSObject* last); JSObject* last);
Object* CompileLoadField(JSObject* object, MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
JSObject* holder, JSObject* holder,
int index, int index,
String* name); String* name);
Object* CompileLoadCallback(String* name, MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
JSObject* object, JSObject* object,
JSObject* holder, JSObject* holder,
AccessorInfo* callback); AccessorInfo* callback);
Object* CompileLoadConstant(JSObject* object, MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
JSObject* holder, JSObject* holder,
Object* value, Object* value,
String* name); String* name);
Object* CompileLoadInterceptor(JSObject* object, MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
JSObject* holder, JSObject* holder,
String* name); String* name);
Object* CompileLoadGlobal(JSObject* object, MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object,
GlobalObject* holder, GlobalObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
String* name, String* name,
bool is_dont_delete); bool is_dont_delete);
private: private:
Object* GetCode(PropertyType type, String* name); MaybeObject* GetCode(PropertyType type, String* name);
}; };
class KeyedLoadStubCompiler: public StubCompiler { class KeyedLoadStubCompiler: public StubCompiler {
public: public:
Object* CompileLoadField(String* name, MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
JSObject* object, JSObject* object,
JSObject* holder, JSObject* holder,
int index); int index);
Object* CompileLoadCallback(String* name, MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
JSObject* object, JSObject* object,
JSObject* holder, JSObject* holder,
AccessorInfo* callback); AccessorInfo* callback);
Object* CompileLoadConstant(String* name, MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
JSObject* object, JSObject* object,
JSObject* holder, JSObject* holder,
Object* value); Object* value);
Object* CompileLoadInterceptor(JSObject* object, MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
JSObject* holder, JSObject* holder,
String* name); String* name);
Object* CompileLoadArrayLength(String* name); MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
Object* CompileLoadStringLength(String* name); MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
Object* CompileLoadFunctionPrototype(String* name); MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
private: private:
Object* GetCode(PropertyType type, String* name); MaybeObject* GetCode(PropertyType type, String* name);
}; };
class StoreStubCompiler: public StubCompiler { class StoreStubCompiler: public StubCompiler {
public: public:
Object* CompileStoreField(JSObject* object, MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object,
int index, int index,
Map* transition, Map* transition,
String* name); String* name);
Object* CompileStoreCallback(JSObject* object, MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object,
AccessorInfo* callbacks, AccessorInfo* callbacks,
String* name); String* name);
Object* CompileStoreInterceptor(JSObject* object, String* name); MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object,
Object* CompileStoreGlobal(GlobalObject* object, String* name);
JSGlobalPropertyCell* holder, MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object,
String* name); JSGlobalPropertyCell* holder,
String* name);
private: private:
Object* GetCode(PropertyType type, String* name); MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
}; };
class KeyedStoreStubCompiler: public StubCompiler { class KeyedStoreStubCompiler: public StubCompiler {
public: public:
Object* CompileStoreField(JSObject* object, MaybeObject* CompileStoreField(JSObject* object,
int index, int index,
Map* transition, Map* transition,
String* name); String* name);
private: private:
Object* GetCode(PropertyType type, String* name); MaybeObject* GetCode(PropertyType type, String* name);
}; };
@ -645,39 +661,39 @@ class CallStubCompiler: public StubCompiler {
Code::Kind kind, Code::Kind kind,
InlineCacheHolderFlag cache_holder); InlineCacheHolderFlag cache_holder);
Object* CompileCallField(JSObject* object, MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
JSObject* holder, JSObject* holder,
int index, int index,
String* name); String* name);
Object* CompileCallConstant(Object* object, MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
JSObject* holder, JSObject* holder,
JSFunction* function, JSFunction* function,
String* name, String* name,
CheckType check); CheckType check);
Object* CompileCallInterceptor(JSObject* object, MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
JSObject* holder, JSObject* holder,
String* name); String* name);
Object* CompileCallGlobal(JSObject* object, MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object,
GlobalObject* holder, GlobalObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name); String* name);
// Compiles a custom call constant/global IC using the generator // Compiles a custom call constant/global IC using the generator
// with given id. For constant calls cell is NULL. // with given id. For constant calls cell is NULL.
Object* CompileCustomCall(int generator_id, MUST_USE_RESULT MaybeObject* CompileCustomCall(int generator_id,
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name); String* name);
#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \ #define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \
Object* Compile##name##Call(Object* object, \ MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \
JSObject* holder, \ JSObject* holder, \
JSGlobalPropertyCell* cell, \ JSGlobalPropertyCell* cell, \
JSFunction* function, \ JSFunction* function, \
String* fname); String* fname);
CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR) CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR)
#undef DECLARE_CALL_GENERATOR #undef DECLARE_CALL_GENERATOR
@ -689,11 +705,11 @@ class CallStubCompiler: public StubCompiler {
const ParameterCount& arguments() { return arguments_; } const ParameterCount& arguments() { return arguments_; }
Object* GetCode(PropertyType type, String* name); MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name);
// Convenience function. Calls GetCode above passing // Convenience function. Calls GetCode above passing
// CONSTANT_FUNCTION type and the name of the given function. // CONSTANT_FUNCTION type and the name of the given function.
Object* GetCode(JSFunction* function); MUST_USE_RESULT MaybeObject* GetCode(JSFunction* function);
void GenerateNameCheck(String* name, Label* miss); void GenerateNameCheck(String* name, Label* miss);
@ -710,7 +726,7 @@ class CallStubCompiler: public StubCompiler {
// Generates a jump to CallIC miss stub. Returns Failure if the jump cannot // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot
// be generated. // be generated.
Object* GenerateMissBranch(); MUST_USE_RESULT MaybeObject* GenerateMissBranch();
}; };
@ -718,10 +734,10 @@ class ConstructStubCompiler: public StubCompiler {
public: public:
explicit ConstructStubCompiler() {} explicit ConstructStubCompiler() {}
Object* CompileConstructStub(SharedFunctionInfo* shared); MUST_USE_RESULT MaybeObject* CompileConstructStub(SharedFunctionInfo* shared);
private: private:
Object* GetCode(); MaybeObject* GetCode();
}; };

63
deps/v8/src/top.cc

@ -66,6 +66,13 @@ v8::TryCatch* ThreadLocalTop::TryCatchHandler() {
void ThreadLocalTop::Initialize() { void ThreadLocalTop::Initialize() {
c_entry_fp_ = 0; c_entry_fp_ = 0;
handler_ = 0; handler_ = 0;
#ifdef USE_SIMULATOR
#ifdef V8_TARGET_ARCH_ARM
simulator_ = assembler::arm::Simulator::current();
#elif V8_TARGET_ARCH_MIPS
simulator_ = assembler::mips::Simulator::current();
#endif
#endif
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
js_entry_sp_ = 0; js_entry_sp_ = 0;
#endif #endif
@ -107,11 +114,22 @@ void Top::IterateThread(ThreadVisitor* v, char* t) {
void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
v->VisitPointer(&(thread->pending_exception_)); // Visit the roots from the top for a given thread.
Object *pending;
// The pending exception can sometimes be a failure. We can't show
// that to the GC, which only understands objects.
if (thread->pending_exception_->ToObject(&pending)) {
v->VisitPointer(&pending);
thread->pending_exception_ = pending; // In case GC updated it.
}
v->VisitPointer(&(thread->pending_message_obj_)); v->VisitPointer(&(thread->pending_message_obj_));
v->VisitPointer(BitCast<Object**>(&(thread->pending_message_script_))); v->VisitPointer(BitCast<Object**>(&(thread->pending_message_script_)));
v->VisitPointer(BitCast<Object**>(&(thread->context_))); v->VisitPointer(BitCast<Object**>(&(thread->context_)));
v->VisitPointer(&(thread->scheduled_exception_)); Object* scheduled;
if (thread->scheduled_exception_->ToObject(&scheduled)) {
v->VisitPointer(&scheduled);
thread->scheduled_exception_ = scheduled;
}
for (v8::TryCatch* block = thread->TryCatchHandler(); for (v8::TryCatch* block = thread->TryCatchHandler();
block != NULL; block != NULL;
@ -688,7 +706,7 @@ Failure* Top::Throw(Object* exception, MessageLocation* location) {
} }
Failure* Top::ReThrow(Object* exception, MessageLocation* location) { Failure* Top::ReThrow(MaybeObject* exception, MessageLocation* location) {
// Set the exception being re-thrown. // Set the exception being re-thrown.
set_pending_exception(exception); set_pending_exception(exception);
return Failure::Exception(); return Failure::Exception();
@ -710,8 +728,8 @@ void Top::ScheduleThrow(Object* exception) {
} }
Object* Top::PromoteScheduledException() { Failure* Top::PromoteScheduledException() {
Object* thrown = scheduled_exception(); MaybeObject* thrown = scheduled_exception();
clear_scheduled_exception(); clear_scheduled_exception();
// Re-throw the exception to avoid getting repeated error reporting. // Re-throw the exception to avoid getting repeated error reporting.
return ReThrow(thrown); return ReThrow(thrown);
@ -794,19 +812,23 @@ bool Top::ShouldReturnException(bool* is_caught_externally,
} }
void Top::DoThrow(Object* exception, void Top::DoThrow(MaybeObject* exception,
MessageLocation* location, MessageLocation* location,
const char* message) { const char* message) {
ASSERT(!has_pending_exception()); ASSERT(!has_pending_exception());
HandleScope scope; HandleScope scope;
Handle<Object> exception_handle(exception); Object* exception_object = Smi::FromInt(0);
bool is_object = exception->ToObject(&exception_object);
Handle<Object> exception_handle(exception_object);
// Determine reporting and whether the exception is caught externally. // Determine reporting and whether the exception is caught externally.
bool is_caught_externally = false; bool is_caught_externally = false;
bool is_out_of_memory = exception == Failure::OutOfMemoryException(); bool is_out_of_memory = exception == Failure::OutOfMemoryException();
bool is_termination_exception = exception == Heap::termination_exception(); bool is_termination_exception = exception == Heap::termination_exception();
bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory; bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory;
// Only real objects can be caught by JS.
ASSERT(!catchable_by_javascript || is_object);
bool should_return_exception = bool should_return_exception =
ShouldReturnException(&is_caught_externally, catchable_by_javascript); ShouldReturnException(&is_caught_externally, catchable_by_javascript);
bool report_exception = catchable_by_javascript && should_return_exception; bool report_exception = catchable_by_javascript && should_return_exception;
@ -842,6 +864,7 @@ void Top::DoThrow(Object* exception,
stack_trace_for_uncaught_exceptions_frame_limit, stack_trace_for_uncaught_exceptions_frame_limit,
stack_trace_for_uncaught_exceptions_options); stack_trace_for_uncaught_exceptions_options);
} }
ASSERT(is_object); // Can't use the handle unless there's a real object.
message_obj = MessageHandler::MakeMessageObject("uncaught_exception", message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
location, HandleVector<Object>(&exception_handle, 1), stack_trace, location, HandleVector<Object>(&exception_handle, 1), stack_trace,
stack_trace_object); stack_trace_object);
@ -867,7 +890,13 @@ void Top::DoThrow(Object* exception,
// NOTE: Notifying the debugger or generating the message // NOTE: Notifying the debugger or generating the message
// may have caused new exceptions. For now, we just ignore // may have caused new exceptions. For now, we just ignore
// that and set the pending exception to the original one. // that and set the pending exception to the original one.
set_pending_exception(*exception_handle); if (is_object) {
set_pending_exception(*exception_handle);
} else {
// Failures are not on the heap so they neither need nor work with handles.
ASSERT(exception_handle->IsFailure());
set_pending_exception(exception);
}
} }
@ -889,7 +918,10 @@ void Top::ReportPendingMessages() {
thread_local_.TryCatchHandler()->exception_ = Heap::null_value(); thread_local_.TryCatchHandler()->exception_ = Heap::null_value();
} }
} else { } else {
Handle<Object> exception(pending_exception()); // At this point all non-object (failure) exceptions have
// been dealt with so this shouldn't fail.
Object* pending_exception_object = pending_exception()->ToObjectUnchecked();
Handle<Object> exception(pending_exception_object);
thread_local_.external_caught_exception_ = false; thread_local_.external_caught_exception_ = false;
if (external_caught) { if (external_caught) {
thread_local_.TryCatchHandler()->can_continue_ = true; thread_local_.TryCatchHandler()->can_continue_ = true;
@ -983,13 +1015,13 @@ void Top::SetCaptureStackTraceForUncaughtExceptions(
bool Top::is_out_of_memory() { bool Top::is_out_of_memory() {
if (has_pending_exception()) { if (has_pending_exception()) {
Object* e = pending_exception(); MaybeObject* e = pending_exception();
if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
return true; return true;
} }
} }
if (has_scheduled_exception()) { if (has_scheduled_exception()) {
Object* e = scheduled_exception(); MaybeObject* e = scheduled_exception();
if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
return true; return true;
} }
@ -1035,6 +1067,15 @@ char* Top::ArchiveThread(char* to) {
char* Top::RestoreThread(char* from) { char* Top::RestoreThread(char* from) {
memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(thread_local_)); memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(thread_local_));
// This might be just paranoia, but it seems to be needed in case a
// thread_local_ is restored on a separate OS thread.
#ifdef USE_SIMULATOR
#ifdef V8_TARGET_ARCH_ARM
thread_local_.simulator_ = assembler::arm::Simulator::current();
#elif V8_TARGET_ARCH_MIPS
thread_local_.simulator_ = assembler::mips::Simulator::current();
#endif
#endif
return from + sizeof(thread_local_); return from + sizeof(thread_local_);
} }

26
deps/v8/src/top.h

@ -29,6 +29,7 @@
#define V8_TOP_H_ #define V8_TOP_H_
#include "frames-inl.h" #include "frames-inl.h"
#include "simulator.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -84,7 +85,7 @@ class ThreadLocalTop BASE_EMBEDDED {
// lookups. // lookups.
Context* context_; Context* context_;
int thread_id_; int thread_id_;
Object* pending_exception_; MaybeObject* pending_exception_;
bool has_pending_message_; bool has_pending_message_;
const char* pending_message_; const char* pending_message_;
Object* pending_message_obj_; Object* pending_message_obj_;
@ -94,7 +95,7 @@ class ThreadLocalTop BASE_EMBEDDED {
// Use a separate value for scheduled exceptions to preserve the // Use a separate value for scheduled exceptions to preserve the
// invariants that hold about pending_exception. We may want to // invariants that hold about pending_exception. We may want to
// unify them later. // unify them later.
Object* scheduled_exception_; MaybeObject* scheduled_exception_;
bool external_caught_exception_; bool external_caught_exception_;
SaveContext* save_context_; SaveContext* save_context_;
v8::TryCatch* catcher_; v8::TryCatch* catcher_;
@ -103,6 +104,10 @@ class ThreadLocalTop BASE_EMBEDDED {
Address c_entry_fp_; // the frame pointer of the top c entry frame Address c_entry_fp_; // the frame pointer of the top c entry frame
Address handler_; // try-blocks are chained through the stack Address handler_; // try-blocks are chained through the stack
#ifdef USE_SIMULATOR
assembler::arm::Simulator* simulator_;
#endif // USE_SIMULATOR
#ifdef ENABLE_LOGGING_AND_PROFILING #ifdef ENABLE_LOGGING_AND_PROFILING
Address js_entry_sp_; // the stack pointer of the bottom js entry frame Address js_entry_sp_; // the stack pointer of the bottom js entry frame
#endif #endif
@ -165,21 +170,21 @@ class Top {
static void set_thread_id(int id) { thread_local_.thread_id_ = id; } static void set_thread_id(int id) { thread_local_.thread_id_ = id; }
// Interface to pending exception. // Interface to pending exception.
static Object* pending_exception() { static MaybeObject* pending_exception() {
ASSERT(has_pending_exception()); ASSERT(has_pending_exception());
return thread_local_.pending_exception_; return thread_local_.pending_exception_;
} }
static bool external_caught_exception() { static bool external_caught_exception() {
return thread_local_.external_caught_exception_; return thread_local_.external_caught_exception_;
} }
static void set_pending_exception(Object* exception) { static void set_pending_exception(MaybeObject* exception) {
thread_local_.pending_exception_ = exception; thread_local_.pending_exception_ = exception;
} }
static void clear_pending_exception() { static void clear_pending_exception() {
thread_local_.pending_exception_ = Heap::the_hole_value(); thread_local_.pending_exception_ = Heap::the_hole_value();
} }
static Object** pending_exception_address() { static MaybeObject** pending_exception_address() {
return &thread_local_.pending_exception_; return &thread_local_.pending_exception_;
} }
static bool has_pending_exception() { static bool has_pending_exception() {
@ -208,11 +213,11 @@ class Top {
return &thread_local_.external_caught_exception_; return &thread_local_.external_caught_exception_;
} }
static Object** scheduled_exception_address() { static MaybeObject** scheduled_exception_address() {
return &thread_local_.scheduled_exception_; return &thread_local_.scheduled_exception_;
} }
static Object* scheduled_exception() { static MaybeObject* scheduled_exception() {
ASSERT(has_scheduled_exception()); ASSERT(has_scheduled_exception());
return thread_local_.scheduled_exception_; return thread_local_.scheduled_exception_;
} }
@ -302,14 +307,15 @@ class Top {
// Re-throw an exception. This involves no error reporting since // Re-throw an exception. This involves no error reporting since
// error reporting was handled when the exception was thrown // error reporting was handled when the exception was thrown
// originally. // originally.
static Failure* ReThrow(Object* exception, MessageLocation* location = NULL); static Failure* ReThrow(MaybeObject* exception,
MessageLocation* location = NULL);
static void ScheduleThrow(Object* exception); static void ScheduleThrow(Object* exception);
static void ReportPendingMessages(); static void ReportPendingMessages();
static Failure* ThrowIllegalOperation(); static Failure* ThrowIllegalOperation();
// Promote a scheduled exception to pending. Asserts has_scheduled_exception. // Promote a scheduled exception to pending. Asserts has_scheduled_exception.
static Object* PromoteScheduledException(); static Failure* PromoteScheduledException();
static void DoThrow(Object* exception, static void DoThrow(MaybeObject* exception,
MessageLocation* location, MessageLocation* location,
const char* message); const char* message);
static bool ShouldReturnException(bool* is_caught_externally, static bool ShouldReturnException(bool* is_caught_externally,

6
deps/v8/src/v8.cc

@ -68,8 +68,12 @@ bool V8::Initialize(Deserializer* des) {
OS::Setup(); OS::Setup();
// Initialize other runtime facilities // Initialize other runtime facilities
#if (defined(USE_SIMULATOR) || !V8_HOST_ARCH_ARM) && V8_TARGET_ARCH_ARM #if defined(USE_SIMULATOR)
#if defined(V8_TARGET_ARCH_ARM)
::assembler::arm::Simulator::Initialize(); ::assembler::arm::Simulator::Initialize();
#elif defined(V8_TARGET_ARCH_MIPS)
::assembler::mips::Simulator::Initialize();
#endif
#endif #endif
{ // NOLINT { // NOLINT

2
deps/v8/src/version.cc

@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script. // cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 2 #define MAJOR_VERSION 2
#define MINOR_VERSION 5 #define MINOR_VERSION 5
#define BUILD_NUMBER 1 #define BUILD_NUMBER 2
#define PATCH_LEVEL 0 #define PATCH_LEVEL 0
#define CANDIDATE_VERSION false #define CANDIDATE_VERSION false

8
deps/v8/src/x64/assembler-x64.cc

@ -118,9 +118,11 @@ void CpuFeatures::Probe() {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, MaybeObject* maybe_code = Heap::CreateCode(desc,
Code::ComputeFlags(Code::STUB), Code::ComputeFlags(Code::STUB),
Handle<Object>()); Handle<Object>());
Object* code;
if (!maybe_code->ToObject(&code)) return;
if (!code->IsCode()) return; if (!code->IsCode()) return;
PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG, PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), "CpuFeatures::Probe")); Code::cast(code), "CpuFeatures::Probe"));

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

@ -2484,11 +2484,7 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
void ApiGetterEntryStub::Generate(MacroAssembler* masm) { void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
Label empty_result; __ PrepareCallApiFunction(kStackSpace);
Label prologue;
Label promote_scheduled_exception;
__ EnterApiExitFrame(kStackSpace, 0);
ASSERT_EQ(kArgc, 4);
#ifdef _WIN64 #ifdef _WIN64
// All the parameters should be set up by a caller. // All the parameters should be set up by a caller.
#else #else
@ -2497,35 +2493,7 @@ void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
// Second parameter register rdi should be set with pointer to AccessorInfo // Second parameter register rdi should be set with pointer to AccessorInfo
// by a caller. // by a caller.
#endif #endif
// Call the api function! __ CallApiFunctionAndReturn(fun());
__ movq(rax,
reinterpret_cast<int64_t>(fun()->address()),
RelocInfo::RUNTIME_ENTRY);
__ call(rax);
// Check if the function scheduled an exception.
ExternalReference scheduled_exception_address =
ExternalReference::scheduled_exception_address();
__ movq(rsi, scheduled_exception_address);
__ Cmp(Operand(rsi, 0), Factory::the_hole_value());
__ j(not_equal, &promote_scheduled_exception);
#ifdef _WIN64
// rax keeps a pointer to v8::Handle, unpack it.
__ movq(rax, Operand(rax, 0));
#endif
// Check if the result handle holds 0.
__ testq(rax, rax);
__ j(zero, &empty_result);
// It was non-zero. Dereference to get the result value.
__ movq(rax, Operand(rax, 0));
__ bind(&prologue);
__ LeaveExitFrame();
__ ret(0);
__ bind(&promote_scheduled_exception);
__ TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
__ bind(&empty_result);
// It was zero; the result is undefined.
__ Move(rax, Factory::undefined_value());
__ jmp(&prologue);
} }

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

@ -315,11 +315,12 @@ void MacroAssembler::CallStub(CodeStub* stub) {
} }
Object* MacroAssembler::TryCallStub(CodeStub* stub) { MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) {
ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
Object* result = stub->TryGetCode(); MaybeObject* result = stub->TryGetCode();
if (!result->IsFailure()) { if (!result->IsFailure()) {
call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); call(Handle<Code>(Code::cast(result->ToObjectUnchecked())),
RelocInfo::CODE_TARGET);
} }
return result; return result;
} }
@ -331,11 +332,12 @@ void MacroAssembler::TailCallStub(CodeStub* stub) {
} }
Object* MacroAssembler::TryTailCallStub(CodeStub* stub) { MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub) {
ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
Object* result = stub->TryGetCode(); MaybeObject* result = stub->TryGetCode();
if (!result->IsFailure()) { if (!result->IsFailure()) {
jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); jmp(Handle<Code>(Code::cast(result->ToObjectUnchecked())),
RelocInfo::CODE_TARGET);
} }
return result; return result;
} }
@ -379,8 +381,8 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
} }
Object* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id,
int num_arguments) { int num_arguments) {
return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); return TryCallRuntime(Runtime::FunctionForId(id), num_arguments);
} }
@ -405,8 +407,8 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
} }
Object* MacroAssembler::TryCallRuntime(Runtime::Function* f, MaybeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f,
int num_arguments) { int num_arguments) {
if (f->nargs >= 0 && f->nargs != num_arguments) { if (f->nargs >= 0 && f->nargs != num_arguments) {
IllegalOperation(num_arguments); IllegalOperation(num_arguments);
// Since we did not call the stub, there was no allocation failure. // Since we did not call the stub, there was no allocation failure.
@ -469,76 +471,89 @@ static int Offset(ExternalReference ref0, ExternalReference ref1) {
} }
void MacroAssembler::PushHandleScope(Register scratch) { void MacroAssembler::PrepareCallApiFunction(int stack_space) {
ExternalReference extensions_address = EnterApiExitFrame(stack_space, 0);
ExternalReference::handle_scope_extensions_address();
const int kExtensionsOffset = 0;
const int kNextOffset = Offset(
ExternalReference::handle_scope_next_address(),
extensions_address);
const int kLimitOffset = Offset(
ExternalReference::handle_scope_limit_address(),
extensions_address);
// Push the number of extensions, smi-tagged so the gc will ignore it.
movq(kScratchRegister, extensions_address);
movq(scratch, Operand(kScratchRegister, kExtensionsOffset));
movq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
Integer32ToSmi(scratch, scratch);
push(scratch);
// Push next and limit pointers which will be wordsize aligned and
// hence automatically smi tagged.
push(Operand(kScratchRegister, kNextOffset));
push(Operand(kScratchRegister, kLimitOffset));
} }
Object* MacroAssembler::PopHandleScopeHelper(Register saved, void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function) {
Register scratch, Label empty_result;
bool gc_allowed) { Label prologue;
ExternalReference extensions_address = Label promote_scheduled_exception;
ExternalReference::handle_scope_extensions_address(); Label delete_allocated_handles;
const int kExtensionsOffset = 0; Label leave_exit_frame;
const int kNextOffset = Offset(
ExternalReference::handle_scope_next_address(),
extensions_address);
const int kLimitOffset = Offset(
ExternalReference::handle_scope_limit_address(),
extensions_address);
Object* result = NULL;
Label write_back; Label write_back;
movq(kScratchRegister, extensions_address);
cmpq(Operand(kScratchRegister, kExtensionsOffset), Immediate(0));
j(equal, &write_back);
push(saved);
if (gc_allowed) {
CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
} else {
result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
if (result->IsFailure()) return result;
}
pop(saved);
movq(kScratchRegister, extensions_address);
bind(&write_back);
pop(Operand(kScratchRegister, kLimitOffset));
pop(Operand(kScratchRegister, kNextOffset));
pop(scratch);
SmiToInteger32(scratch, scratch);
movq(Operand(kScratchRegister, kExtensionsOffset), scratch);
return result; ExternalReference next_address =
} ExternalReference::handle_scope_next_address();
const int kNextOffset = 0;
const int kLimitOffset = Offset(
ExternalReference::handle_scope_limit_address(),
next_address);
const int kLevelOffset = Offset(
ExternalReference::handle_scope_level_address(),
next_address);
ExternalReference scheduled_exception_address =
ExternalReference::scheduled_exception_address();
// Allocate HandleScope in callee-save registers.
Register prev_next_address_reg = r14;
Register prev_limit_reg = rbx;
Register base_reg = kSmiConstantRegister;
movq(base_reg, next_address);
movq(prev_next_address_reg, Operand(base_reg, kNextOffset));
movq(prev_limit_reg, Operand(base_reg, kLimitOffset));
addl(Operand(base_reg, kLevelOffset), Immediate(1));
// Call the api function!
movq(rax,
reinterpret_cast<int64_t>(function->address()),
RelocInfo::RUNTIME_ENTRY);
call(rax);
#ifdef _WIN64
// rax keeps a pointer to v8::Handle, unpack it.
movq(rax, Operand(rax, 0));
#endif
// Check if the result handle holds 0.
testq(rax, rax);
j(zero, &empty_result);
// It was non-zero. Dereference to get the result value.
movq(rax, Operand(rax, 0));
bind(&prologue);
// No more valid handles (the result handle was the last one). Restore
// previous handle scope.
subl(Operand(base_reg, kLevelOffset), Immediate(1));
movq(Operand(base_reg, kNextOffset), prev_next_address_reg);
cmpq(prev_limit_reg, Operand(base_reg, kLimitOffset));
j(not_equal, &delete_allocated_handles);
bind(&leave_exit_frame);
InitializeSmiConstantRegister();
// Check if the function scheduled an exception.
movq(rsi, scheduled_exception_address);
Cmp(Operand(rsi, 0), Factory::the_hole_value());
j(not_equal, &promote_scheduled_exception);
LeaveExitFrame();
ret(0);
void MacroAssembler::PopHandleScope(Register saved, Register scratch) { bind(&promote_scheduled_exception);
PopHandleScopeHelper(saved, scratch, true); TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
}
bind(&empty_result);
// It was zero; the result is undefined.
Move(rax, Factory::undefined_value());
jmp(&prologue);
Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { // HandleScope limit has changed. Delete allocated extensions.
return PopHandleScopeHelper(saved, scratch, false); bind(&delete_allocated_handles);
movq(Operand(base_reg, kLimitOffset), prev_limit_reg);
movq(prev_limit_reg, rax);
movq(rax, ExternalReference::delete_handle_scope_extensions());
call(rax);
movq(rax, prev_limit_reg);
jmp(&leave_exit_frame);
} }
@ -1891,6 +1906,20 @@ void MacroAssembler::AllocateInNewSpace(int object_size,
Register scratch, Register scratch,
Label* gc_required, Label* gc_required,
AllocationFlags flags) { AllocationFlags flags) {
if (!FLAG_inline_new) {
if (FLAG_debug_code) {
// Trash the registers to simulate an allocation failure.
movl(result, Immediate(0x7091));
if (result_end.is_valid()) {
movl(result_end, Immediate(0x7191));
}
if (scratch.is_valid()) {
movl(scratch, Immediate(0x7291));
}
}
jmp(gc_required);
return;
}
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
@ -1935,6 +1964,19 @@ void MacroAssembler::AllocateInNewSpace(int header_size,
Register scratch, Register scratch,
Label* gc_required, Label* gc_required,
AllocationFlags flags) { AllocationFlags flags) {
if (!FLAG_inline_new) {
if (FLAG_debug_code) {
// Trash the registers to simulate an allocation failure.
movl(result, Immediate(0x7091));
movl(result_end, Immediate(0x7191));
if (scratch.is_valid()) {
movl(scratch, Immediate(0x7291));
}
// Register element_count is not modified by the function.
}
jmp(gc_required);
return;
}
ASSERT(!result.is(result_end)); ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
@ -1964,6 +2006,21 @@ void MacroAssembler::AllocateInNewSpace(Register object_size,
Register scratch, Register scratch,
Label* gc_required, Label* gc_required,
AllocationFlags flags) { AllocationFlags flags) {
if (!FLAG_inline_new) {
if (FLAG_debug_code) {
// Trash the registers to simulate an allocation failure.
movl(result, Immediate(0x7091));
movl(result_end, Immediate(0x7191));
if (scratch.is_valid()) {
movl(scratch, Immediate(0x7291));
}
// object_size is left unchanged by this function.
}
jmp(gc_required);
return;
}
ASSERT(!result.is(result_end));
// Load address of new object into result. // Load address of new object into result.
LoadAllocationTopHelper(result, result_end, scratch, flags); LoadAllocationTopHelper(result, result_end, scratch, flags);

29
deps/v8/src/x64/macro-assembler-x64.h

@ -773,7 +773,7 @@ class MacroAssembler: public Assembler {
// Call a code stub and return the code object called. Try to generate // Call a code stub and return the code object called. Try to generate
// the code if necessary. Do not perform a GC but instead return a retry // the code if necessary. Do not perform a GC but instead return a retry
// after GC failure. // after GC failure.
Object* TryCallStub(CodeStub* stub); MUST_USE_RESULT MaybeObject* TryCallStub(CodeStub* stub);
// Tail call a code stub (jump). // Tail call a code stub (jump).
void TailCallStub(CodeStub* stub); void TailCallStub(CodeStub* stub);
@ -781,7 +781,7 @@ class MacroAssembler: public Assembler {
// Tail call a code stub (jump) and return the code object called. Try to // Tail call a code stub (jump) and return the code object called. Try to
// generate the code if necessary. Do not perform a GC but instead return // generate the code if necessary. Do not perform a GC but instead return
// a retry after GC failure. // a retry after GC failure.
Object* TryTailCallStub(CodeStub* stub); MUST_USE_RESULT MaybeObject* TryTailCallStub(CodeStub* stub);
// Return from a code stub after popping its arguments. // Return from a code stub after popping its arguments.
void StubReturn(int argc); void StubReturn(int argc);
@ -792,13 +792,15 @@ class MacroAssembler: public Assembler {
// Call a runtime function, returning the CodeStub object called. // Call a runtime function, returning the CodeStub object called.
// Try to generate the stub code if necessary. Do not perform a GC // Try to generate the stub code if necessary. Do not perform a GC
// but instead return a retry after GC failure. // but instead return a retry after GC failure.
Object* TryCallRuntime(Runtime::Function* f, int num_arguments); MUST_USE_RESULT MaybeObject* TryCallRuntime(Runtime::Function* f,
int num_arguments);
// Convenience function: Same as above, but takes the fid instead. // Convenience function: Same as above, but takes the fid instead.
void CallRuntime(Runtime::FunctionId id, int num_arguments); void CallRuntime(Runtime::FunctionId id, int num_arguments);
// Convenience function: Same as above, but takes the fid instead. // Convenience function: Same as above, but takes the fid instead.
Object* TryCallRuntime(Runtime::FunctionId id, int num_arguments); MUST_USE_RESULT MaybeObject* TryCallRuntime(Runtime::FunctionId id,
int num_arguments);
// Convenience function: call an external reference. // Convenience function: call an external reference.
void CallExternalReference(const ExternalReference& ext, void CallExternalReference(const ExternalReference& ext,
@ -816,19 +818,18 @@ class MacroAssembler: public Assembler {
int num_arguments, int num_arguments,
int result_size); int result_size);
void PushHandleScope(Register scratch);
// Pops a handle scope using the specified scratch register and
// ensuring that saved register is left unchanged.
void PopHandleScope(Register saved, Register scratch);
// As PopHandleScope, but does not perform a GC. Instead, returns a
// retry after GC failure object if GC is necessary.
Object* TryPopHandleScope(Register saved, Register scratch);
// Jump to a runtime routine. // Jump to a runtime routine.
void JumpToExternalReference(const ExternalReference& ext, int result_size); void JumpToExternalReference(const ExternalReference& ext, int result_size);
// Prepares stack to put arguments (aligns and so on).
// Uses calle-saved esi to restore stack state after call.
void PrepareCallApiFunction(int stack_space);
// Tail call an API function (jump). Allocates HandleScope, extracts
// returned value from handle and propogates exceptions.
// Clobbers ebx, edi and caller-save registers.
void CallApiFunctionAndReturn(ApiFunction* function);
// Before calling a C-function from generated code, align arguments on stack. // Before calling a C-function from generated code, align arguments on stack.
// After aligning the frame, arguments must be stored in esp[0], esp[4], // After aligning the frame, arguments must be stored in esp[0], esp[4],
// etc., not pushed. The argument count assumes all arguments are word sized. // etc., not pushed. The argument count assumes all arguments are word sized.

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

@ -1169,7 +1169,7 @@ int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address,
ASSERT(*return_address <= ASSERT(*return_address <=
re_code->instruction_start() + re_code->instruction_size()); re_code->instruction_start() + re_code->instruction_size());
Object* result = Execution::HandleStackGuardInterrupt(); MaybeObject* result = Execution::HandleStackGuardInterrupt();
if (*code_handle != re_code) { // Return address no longer valid if (*code_handle != re_code) { // Return address no longer valid
intptr_t delta = *code_handle - re_code; intptr_t delta = *code_handle - re_code;

23
deps/v8/src/x64/simulator-x64.h

@ -30,11 +30,22 @@
#include "allocation.h" #include "allocation.h"
// Since there is no simulator for the ia32 architecture the only thing we can namespace v8 {
namespace internal {
// Since there is no simulator for the x64 architecture the only thing we can
// do is to call the entry directly. // do is to call the entry directly.
// TODO(X64): Don't pass p0, since it isn't used? // TODO(X64): Don't pass p0, since it isn't used?
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \ #define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
entry(p0, p1, p2, p3, p4); (entry(p0, p1, p2, p3, p4))
// Call the generated regexp code directly. The entry function pointer should
// expect seven int/pointer sized arguments and return an int.
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
(entry(p0, p1, p2, p3, p4, p5, p6))
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
(reinterpret_cast<TryCatch*>(try_catch_address))
// The stack limit beyond which we will throw stack overflow errors in // The stack limit beyond which we will throw stack overflow errors in
// generated code. Because generated code on x64 uses the C stack, we // generated code. Because generated code on x64 uses the C stack, we
@ -52,12 +63,6 @@ class SimulatorStack : public v8::internal::AllStatic {
static inline void UnregisterCTryCatch() { } static inline void UnregisterCTryCatch() { }
}; };
// Call the generated regexp code directly. The entry function pointer should } } // namespace v8::internal
// expect eight int/pointer sized arguments and return an int.
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
entry(p0, p1, p2, p3, p4, p5, p6)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
#endif // V8_X64_SIMULATOR_X64_H_ #endif // V8_X64_SIMULATOR_X64_H_

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

@ -796,13 +796,16 @@ class CallInterceptorCompiler BASE_EMBEDDED {
// Generate code to check that a global property cell is empty. Create // Generate code to check that a global property cell is empty. Create
// the property cell at compilation time if no cell exists for the // the property cell at compilation time if no cell exists for the
// property. // property.
static Object* GenerateCheckPropertyCell(MacroAssembler* masm, MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
GlobalObject* global, MacroAssembler* masm,
String* name, GlobalObject* global,
Register scratch, String* name,
Label* miss) { Register scratch,
Object* probe = global->EnsurePropertyCell(name); Label* miss) {
if (probe->IsFailure()) return probe; Object* probe;
{ MaybeObject* maybe_probe = global->EnsurePropertyCell(name);
if (!maybe_probe->ToObject(&probe)) return maybe_probe;
}
JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
ASSERT(cell->value()->IsTheHole()); ASSERT(cell->value()->IsTheHole());
__ Move(scratch, Handle<Object>(cell)); __ Move(scratch, Handle<Object>(cell));
@ -879,19 +882,23 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
} }
Object* CallStubCompiler::GenerateMissBranch() { MaybeObject* CallStubCompiler::GenerateMissBranch() {
Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj =
StubCache::ComputeCallMiss(arguments().immediate(), kind_);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
__ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
return obj; return obj;
} }
Object* CallStubCompiler::CompileCallConstant(Object* object, MaybeObject* CallStubCompiler::CompileCallConstant(
JSObject* holder, Object* object,
JSFunction* function, JSObject* holder,
String* name, JSFunction* function,
StubCompiler::CheckType check) { String* name,
StubCompiler::CheckType check) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// rcx : function name // rcx : function name
// rsp[0] : return address // rsp[0] : return address
@ -905,8 +912,10 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
SharedFunctionInfo* function_info = function->shared(); SharedFunctionInfo* function_info = function->shared();
if (function_info->HasCustomCallGenerator()) { if (function_info->HasCustomCallGenerator()) {
const int id = function_info->custom_call_generator_id(); const int id = function_info->custom_call_generator_id();
Object* result = CompileCustomCall( MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, NULL, function, name); id, object, holder, NULL, function, name);
Object* result;
if (!maybe_result->ToObject(&result)) return maybe_result;
// undefined means bail out to regular compiler. // undefined means bail out to regular compiler.
if (!result->IsUndefined()) return result; if (!result->IsUndefined()) return result;
} }
@ -1034,18 +1043,20 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss_in_smi_check); __ bind(&miss_in_smi_check);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileCallField(JSObject* object, MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
JSObject* holder, JSObject* holder,
int index, int index,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// rcx : function name // rcx : function name
// rsp[0] : return address // rsp[0] : return address
@ -1089,19 +1100,21 @@ Object* CallStubCompiler::CompileCallField(JSObject* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(FIELD, name); return GetCode(FIELD, name);
} }
Object* CallStubCompiler::CompileArrayPushCall(Object* object, MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
@ -1191,6 +1204,10 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object,
__ ret((argc + 1) * kPointerSize); __ ret((argc + 1) * kPointerSize);
__ bind(&attempt_to_grow_elements); __ bind(&attempt_to_grow_elements);
if (!FLAG_inline_new) {
__ jmp(&call_builtin);
}
ExternalReference new_space_allocation_top = ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address(); ExternalReference::new_space_allocation_top_address();
ExternalReference new_space_allocation_limit = ExternalReference new_space_allocation_limit =
@ -1247,19 +1264,21 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object,
} }
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileArrayPopCall(Object* object, MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rcx : name // -- rcx : name
// -- rsp[0] : return address // -- rsp[0] : return address
@ -1329,19 +1348,22 @@ Object* CallStubCompiler::CompileArrayPopCall(Object* object,
1); 1);
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileStringCharAtCall(Object* object, MaybeObject* CallStubCompiler::CompileStringCharAtCall(
JSObject* holder, Object* object,
JSGlobalPropertyCell* cell, JSObject* holder,
JSFunction* function, JSGlobalPropertyCell* cell,
String* name) { JSFunction* function,
String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rcx : function name // -- rcx : function name
// -- rsp[0] : return address // -- rsp[0] : return address
@ -1401,15 +1423,17 @@ Object* CallStubCompiler::CompileStringCharAtCall(Object* object,
__ ret((argc + 1) * kPointerSize); __ ret((argc + 1) * kPointerSize);
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileStringCharCodeAtCall( MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
@ -1471,15 +1495,17 @@ Object* CallStubCompiler::CompileStringCharCodeAtCall(
__ ret((argc + 1) * kPointerSize); __ ret((argc + 1) * kPointerSize);
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(function); return GetCode(function);
} }
Object* CallStubCompiler::CompileStringFromCharCodeCall( MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
Object* object, Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
@ -1540,29 +1566,31 @@ Object* CallStubCompiler::CompileStringFromCharCodeCall(
__ bind(&miss); __ bind(&miss);
// rcx: function name. // rcx: function name.
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
} }
Object* CallStubCompiler::CompileMathFloorCall(Object* object, MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// TODO(872): implement this. // TODO(872): implement this.
return Heap::undefined_value(); return Heap::undefined_value();
} }
Object* CallStubCompiler::CompileMathAbsCall(Object* object, MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
JSObject* holder, JSObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rcx : function name // -- rcx : function name
// -- rsp[0] : return address // -- rsp[0] : return address
@ -1653,17 +1681,19 @@ Object* CallStubCompiler::CompileMathAbsCall(Object* object,
__ bind(&miss); __ bind(&miss);
// rcx: function name. // rcx: function name.
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
} }
Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// rcx : function name // rcx : function name
// rsp[0] : return address // rsp[0] : return address
@ -1719,19 +1749,21 @@ Object* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Handle load cache miss. // Handle load cache miss.
__ bind(&miss); __ bind(&miss);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(INTERCEPTOR, name); return GetCode(INTERCEPTOR, name);
} }
Object* CallStubCompiler::CompileCallGlobal(JSObject* object, MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
GlobalObject* holder, GlobalObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
JSFunction* function, JSFunction* function,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// rcx : function name // rcx : function name
// rsp[0] : return address // rsp[0] : return address
@ -1745,8 +1777,10 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
SharedFunctionInfo* function_info = function->shared(); SharedFunctionInfo* function_info = function->shared();
if (function_info->HasCustomCallGenerator()) { if (function_info->HasCustomCallGenerator()) {
const int id = function_info->custom_call_generator_id(); const int id = function_info->custom_call_generator_id();
Object* result = CompileCustomCall( MaybeObject* maybe_result = CompileCustomCall(
id, object, holder, cell, function, name); id, object, holder, cell, function, name);
Object* result;
if (!maybe_result->ToObject(&result)) return maybe_result;
// undefined means bail out to regular compiler. // undefined means bail out to regular compiler.
if (!result->IsUndefined()) return result; if (!result->IsUndefined()) return result;
} }
@ -1782,18 +1816,20 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
// Handle call cache miss. // Handle call cache miss.
__ bind(&miss); __ bind(&miss);
__ IncrementCounter(&Counters::call_global_inline_miss, 1); __ IncrementCounter(&Counters::call_global_inline_miss, 1);
Object* obj = GenerateMissBranch(); Object* obj;
if (obj->IsFailure()) return obj; { MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
// Return the generated code. // Return the generated code.
return GetCode(NORMAL, name); return GetCode(NORMAL, name);
} }
Object* LoadStubCompiler::CompileLoadCallback(String* name, MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
JSObject* object, JSObject* object,
JSObject* holder, JSObject* holder,
AccessorInfo* callback) { AccessorInfo* callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver // -- rax : receiver
// -- rcx : name // -- rcx : name
@ -1817,10 +1853,10 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name,
} }
Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object,
JSObject* holder, JSObject* holder,
Object* value, Object* value,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver // -- rax : receiver
// -- rcx : name // -- rcx : name
@ -1837,9 +1873,9 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
} }
Object* LoadStubCompiler::CompileLoadNonexistent(String* name, MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
JSObject* object, JSObject* object,
JSObject* last) { JSObject* last) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver // -- rax : receiver
// -- rcx : name // -- rcx : name
@ -1858,11 +1894,11 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name,
// If the last object in the prototype chain is a global object, // If the last object in the prototype chain is a global object,
// check that the global property cell is empty. // check that the global property cell is empty.
if (last->IsGlobalObject()) { if (last->IsGlobalObject()) {
Object* cell = GenerateCheckPropertyCell(masm(), MaybeObject* cell = GenerateCheckPropertyCell(masm(),
GlobalObject::cast(last), GlobalObject::cast(last),
name, name,
rdx, rdx,
&miss); &miss);
if (cell->IsFailure()) { if (cell->IsFailure()) {
miss.Unuse(); miss.Unuse();
return cell; return cell;
@ -1882,10 +1918,10 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name,
} }
Object* LoadStubCompiler::CompileLoadField(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* holder, JSObject* holder,
int index, int index,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver // -- rax : receiver
// -- rcx : name // -- rcx : name
@ -1902,9 +1938,9 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object,
} }
Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver // -- rax : receiver
// -- rcx : name // -- rcx : name
@ -1936,11 +1972,11 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
} }
Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
GlobalObject* holder, GlobalObject* holder,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
String* name, String* name,
bool is_dont_delete) { bool is_dont_delete) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : receiver // -- rax : receiver
// -- rcx : name // -- rcx : name
@ -1984,10 +2020,11 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
} }
Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
JSObject* receiver, String* name,
JSObject* holder, JSObject* receiver,
AccessorInfo* callback) { JSObject* holder,
AccessorInfo* callback) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : key // -- rax : key
// -- rdx : receiver // -- rdx : receiver
@ -2018,7 +2055,7 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
} }
Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : key // -- rax : key
// -- rdx : receiver // -- rdx : receiver
@ -2042,10 +2079,10 @@ Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
} }
Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder, JSObject* holder,
Object* value) { Object* value) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : key // -- rax : key
// -- rdx : receiver // -- rdx : receiver
@ -2070,7 +2107,7 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
} }
Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : key // -- rax : key
// -- rdx : receiver // -- rdx : receiver
@ -2094,9 +2131,9 @@ Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
} }
Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder, JSObject* holder,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : key // -- rax : key
// -- rdx : receiver // -- rdx : receiver
@ -2131,7 +2168,7 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
} }
Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : key // -- rax : key
// -- rdx : receiver // -- rdx : receiver
@ -2155,9 +2192,9 @@ Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
} }
Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object,
AccessorInfo* callback, AccessorInfo* callback,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
@ -2205,10 +2242,10 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
} }
Object* StoreStubCompiler::CompileStoreField(JSObject* object, MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object,
int index, int index,
Map* transition, Map* transition,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
@ -2235,8 +2272,8 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object,
} }
Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
@ -2283,9 +2320,9 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
} }
Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
JSGlobalPropertyCell* cell, JSGlobalPropertyCell* cell,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : name // -- rcx : name
@ -2318,10 +2355,10 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object,
} }
Object* KeyedLoadStubCompiler::CompileLoadField(String* name, MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name,
JSObject* receiver, JSObject* receiver,
JSObject* holder, JSObject* holder,
int index) { int index) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : key // -- rax : key
// -- rdx : receiver // -- rdx : receiver
@ -2346,10 +2383,10 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
} }
Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
int index, int index,
Map* transition, Map* transition,
String* name) { String* name) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : value // -- rax : value
// -- rcx : key // -- rcx : key
@ -2543,7 +2580,6 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
Handle<AccessorInfo> callback_handle(callback); Handle<AccessorInfo> callback_handle(callback);
__ EnterInternalFrame(); __ EnterInternalFrame();
__ PushHandleScope(scratch2);
// Push the stack address where the list of arguments ends. // Push the stack address where the list of arguments ends.
__ movq(scratch2, rsp); __ movq(scratch2, rsp);
__ subq(scratch2, Immediate(2 * kPointerSize)); __ subq(scratch2, Immediate(2 * kPointerSize));
@ -2588,7 +2624,7 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
// already generated). Do not allow the assembler to perform a // already generated). Do not allow the assembler to perform a
// garbage collection but instead return the allocation failure // garbage collection but instead return the allocation failure
// object. // object.
Object* result = masm()->TryCallStub(&stub); MaybeObject* result = masm()->TryCallStub(&stub);
if (result->IsFailure()) { if (result->IsFailure()) {
*failure = Failure::cast(result); *failure = Failure::cast(result);
return false; return false;
@ -2597,17 +2633,6 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
// Discard allocated slot. // Discard allocated slot.
__ addq(rsp, Immediate(kPointerSize)); __ addq(rsp, Immediate(kPointerSize));
#endif #endif
// We need to avoid using rax since that now holds the result.
Register tmp = scratch2.is(rax) ? reg : scratch2;
// Emitting PopHandleScope may try to allocate. Do not allow the
// assembler to perform a garbage collection but instead return a
// failure object.
result = masm()->TryPopHandleScope(rax, tmp);
if (result->IsFailure()) {
*failure = Failure::cast(result);
return false;
}
__ LeaveInternalFrame(); __ LeaveInternalFrame();
__ ret(0); __ ret(0);
@ -2655,12 +2680,12 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
!current->IsJSGlobalObject() && !current->IsJSGlobalObject() &&
!current->IsJSGlobalProxy()) { !current->IsJSGlobalProxy()) {
if (!name->IsSymbol()) { if (!name->IsSymbol()) {
Object* lookup_result = Heap::LookupSymbol(name); MaybeObject* lookup_result = Heap::LookupSymbol(name);
if (lookup_result->IsFailure()) { if (lookup_result->IsFailure()) {
set_failure(Failure::cast(lookup_result)); set_failure(Failure::cast(lookup_result));
return reg; return reg;
} else { } else {
name = String::cast(lookup_result); name = String::cast(lookup_result->ToObjectUnchecked());
} }
} }
ASSERT(current->property_dictionary()->FindEntry(name) == ASSERT(current->property_dictionary()->FindEntry(name) ==
@ -2742,11 +2767,11 @@ Register StubCompiler::CheckPrototypes(JSObject* object,
current = object; current = object;
while (current != holder) { while (current != holder) {
if (current->IsGlobalObject()) { if (current->IsGlobalObject()) {
Object* cell = GenerateCheckPropertyCell(masm(), MaybeObject* cell = GenerateCheckPropertyCell(masm(),
GlobalObject::cast(current), GlobalObject::cast(current),
name, name,
scratch1, scratch1,
miss); miss);
if (cell->IsFailure()) { if (cell->IsFailure()) {
set_failure(Failure::cast(cell)); set_failure(Failure::cast(cell));
return reg; return reg;
@ -2808,7 +2833,7 @@ void StubCompiler::GenerateLoadConstant(JSObject* object,
// Specialized stub for constructing objects from functions which only have only // Specialized stub for constructing objects from functions which only have only
// simple assignments of the form this.x = ...; in their body. // simple assignments of the form this.x = ...; in their body.
Object* ConstructStubCompiler::CompileConstructStub( MaybeObject* ConstructStubCompiler::CompileConstructStub(
SharedFunctionInfo* shared) { SharedFunctionInfo* shared) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : argc // -- rax : argc

7
deps/v8/test/cctest/test-alloc.cc

@ -35,7 +35,7 @@
using namespace v8::internal; using namespace v8::internal;
static Object* AllocateAfterFailures() { static MaybeObject* AllocateAfterFailures() {
static int attempts = 0; static int attempts = 0;
if (++attempts < 3) return Failure::RetryAfterGC(); if (++attempts < 3) return Failure::RetryAfterGC();
@ -60,7 +60,8 @@ static Object* AllocateAfterFailures() {
CHECK(!Heap::AllocateFixedArray(100)->IsFailure()); CHECK(!Heap::AllocateFixedArray(100)->IsFailure());
CHECK(!Heap::AllocateHeapNumber(0.42)->IsFailure()); CHECK(!Heap::AllocateHeapNumber(0.42)->IsFailure());
CHECK(!Heap::AllocateArgumentsObject(Smi::FromInt(87), 10)->IsFailure()); CHECK(!Heap::AllocateArgumentsObject(Smi::FromInt(87), 10)->IsFailure());
Object* object = Heap::AllocateJSObject(*Top::object_function()); Object* object =
Heap::AllocateJSObject(*Top::object_function())->ToObjectChecked();
CHECK(!Heap::CopyJSObject(JSObject::cast(object))->IsFailure()); CHECK(!Heap::CopyJSObject(JSObject::cast(object))->IsFailure());
// Old data space. // Old data space.
@ -111,7 +112,7 @@ TEST(StressHandles) {
} }
static Object* TestAccessorGet(Object* object, void*) { static MaybeObject* TestAccessorGet(Object* object, void*) {
return AllocateAfterFailures(); return AllocateAfterFailures();
} }

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

@ -9278,7 +9278,9 @@ class RegExpStringModificationTest {
// Inject the input as a global variable. // Inject the input as a global variable.
i::Handle<i::String> input_name = i::Handle<i::String> input_name =
i::Factory::NewStringFromAscii(i::Vector<const char>("input", 5)); i::Factory::NewStringFromAscii(i::Vector<const char>("input", 5));
i::Top::global_context()->global()->SetProperty(*input_name, *input_, NONE); i::Top::global_context()->global()->SetProperty(*input_name,
*input_,
NONE)->ToObjectChecked();
MorphThread morph_thread(this); MorphThread morph_thread(this);
@ -9750,7 +9752,7 @@ THREADED_TEST(PixelArray) {
// Set the elements to be the pixels. // Set the elements to be the pixels.
// jsobj->set_elements(*pixels); // jsobj->set_elements(*pixels);
obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount); obj->SetIndexedPropertiesToPixelData(pixel_data, kElementCount);
CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1))->value()); CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
obj->Set(v8_str("field"), v8::Int32::New(1503)); obj->Set(v8_str("field"), v8::Int32::New(1503));
context->Global()->Set(v8_str("pixels"), obj); context->Global()->Set(v8_str("pixels"), obj);
v8::Handle<v8::Value> result = CompileRun("pixels.field"); v8::Handle<v8::Value> result = CompileRun("pixels.field");
@ -9802,27 +9804,34 @@ THREADED_TEST(PixelArray) {
i::Handle<i::Smi> value(i::Smi::FromInt(2)); i::Handle<i::Smi> value(i::Smi::FromInt(2));
i::SetElement(jsobj, 1, value); i::SetElement(jsobj, 1, value);
CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1))->value()); CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
*value.location() = i::Smi::FromInt(256); *value.location() = i::Smi::FromInt(256);
i::SetElement(jsobj, 1, value); i::SetElement(jsobj, 1, value);
CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(1))->value()); CHECK_EQ(255,
i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
*value.location() = i::Smi::FromInt(-1); *value.location() = i::Smi::FromInt(-1);
i::SetElement(jsobj, 1, value); i::SetElement(jsobj, 1, value);
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1))->value()); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {" result = CompileRun("for (var i = 0; i < 8; i++) {"
" pixels[i] = (i * 65) - 109;" " pixels[i] = (i * 65) - 109;"
"}" "}"
"pixels[1] + pixels[6];"); "pixels[1] + pixels[6];");
CHECK_EQ(255, result->Int32Value()); CHECK_EQ(255, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0))->value()); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1))->value()); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
CHECK_EQ(21, i::Smi::cast(jsobj->GetElement(2))->value()); CHECK_EQ(21,
CHECK_EQ(86, i::Smi::cast(jsobj->GetElement(3))->value()); i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
CHECK_EQ(151, i::Smi::cast(jsobj->GetElement(4))->value()); CHECK_EQ(86,
CHECK_EQ(216, i::Smi::cast(jsobj->GetElement(5))->value()); i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(6))->value()); CHECK_EQ(151,
CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(7))->value()); i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
CHECK_EQ(216,
i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
CHECK_EQ(255,
i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
CHECK_EQ(255,
i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
result = CompileRun("var sum = 0;" result = CompileRun("var sum = 0;"
"for (var i = 0; i < 8; i++) {" "for (var i = 0; i < 8; i++) {"
" sum += pixels[i];" " sum += pixels[i];"
@ -9835,49 +9844,50 @@ THREADED_TEST(PixelArray) {
"}" "}"
"pixels[1] + pixels[6];"); "pixels[1] + pixels[6];");
CHECK_EQ(8, result->Int32Value()); CHECK_EQ(8, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0))->value()); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value());
CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1))->value()); CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value());
CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2))->value()); CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value());
CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3))->value()); CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value());
CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4))->value()); CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value());
CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5))->value()); CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6))->value()); CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7))->value()); CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {" result = CompileRun("for (var i = 0; i < 8; i++) {"
" pixels[7] = undefined;" " pixels[7] = undefined;"
"}" "}"
"pixels[7];"); "pixels[7];");
CHECK_EQ(0, result->Int32Value()); CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7))->value()); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {" result = CompileRun("for (var i = 0; i < 8; i++) {"
" pixels[6] = '2.3';" " pixels[6] = '2.3';"
"}" "}"
"pixels[6];"); "pixels[6];");
CHECK_EQ(2, result->Int32Value()); CHECK_EQ(2, result->Int32Value());
CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6))->value()); CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {" result = CompileRun("for (var i = 0; i < 8; i++) {"
" pixels[5] = NaN;" " pixels[5] = NaN;"
"}" "}"
"pixels[5];"); "pixels[5];");
CHECK_EQ(0, result->Int32Value()); CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value()); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {" result = CompileRun("for (var i = 0; i < 8; i++) {"
" pixels[8] = Infinity;" " pixels[8] = Infinity;"
"}" "}"
"pixels[8];"); "pixels[8];");
CHECK_EQ(255, result->Int32Value()); CHECK_EQ(255, result->Int32Value());
CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(8))->value()); CHECK_EQ(255,
i::Smi::cast(jsobj->GetElement(8)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {" result = CompileRun("for (var i = 0; i < 8; i++) {"
" pixels[9] = -Infinity;" " pixels[9] = -Infinity;"
"}" "}"
"pixels[9];"); "pixels[9];");
CHECK_EQ(0, result->Int32Value()); CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9))->value()); CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(9)->ToObjectChecked())->value());
result = CompileRun("pixels[3] = 33;" result = CompileRun("pixels[3] = 33;"
"delete pixels[3];" "delete pixels[3];"
@ -9987,7 +9997,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
obj->SetIndexedPropertiesToExternalArrayData(array_data, obj->SetIndexedPropertiesToExternalArrayData(array_data,
array_type, array_type,
kElementCount); kElementCount);
CHECK_EQ(1, static_cast<int>(jsobj->GetElement(1)->Number())); CHECK_EQ(
1, static_cast<int>(jsobj->GetElement(1)->ToObjectChecked()->Number()));
obj->Set(v8_str("field"), v8::Int32::New(1503)); obj->Set(v8_str("field"), v8::Int32::New(1503));
context->Global()->Set(v8_str("ext_array"), obj); context->Global()->Set(v8_str("ext_array"), obj);
v8::Handle<v8::Value> result = CompileRun("ext_array.field"); v8::Handle<v8::Value> result = CompileRun("ext_array.field");
@ -10126,14 +10137,16 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
"}" "}"
"ext_array[7];"); "ext_array[7];");
CHECK_EQ(0, result->Int32Value()); CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, static_cast<int>(jsobj->GetElement(7)->Number())); CHECK_EQ(
0, static_cast<int>(jsobj->GetElement(7)->ToObjectChecked()->Number()));
result = CompileRun("for (var i = 0; i < 8; i++) {" result = CompileRun("for (var i = 0; i < 8; i++) {"
" ext_array[6] = '2.3';" " ext_array[6] = '2.3';"
"}" "}"
"ext_array[6];"); "ext_array[6];");
CHECK_EQ(2, result->Int32Value()); CHECK_EQ(2, result->Int32Value());
CHECK_EQ(2, static_cast<int>(jsobj->GetElement(6)->Number())); CHECK_EQ(
2, static_cast<int>(jsobj->GetElement(6)->ToObjectChecked()->Number()));
if (array_type != v8::kExternalFloatArray) { if (array_type != v8::kExternalFloatArray) {
// Though the specification doesn't state it, be explicit about // Though the specification doesn't state it, be explicit about
@ -10146,7 +10159,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
"}" "}"
"ext_array[5];"); "ext_array[5];");
CHECK_EQ(0, result->Int32Value()); CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value()); CHECK_EQ(0,
i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {" result = CompileRun("for (var i = 0; i < 8; i++) {"
" ext_array[i] = 5;" " ext_array[i] = 5;"
@ -10156,7 +10170,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
"}" "}"
"ext_array[5];"); "ext_array[5];");
CHECK_EQ(0, result->Int32Value()); CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value()); CHECK_EQ(0,
i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
result = CompileRun("for (var i = 0; i < 8; i++) {" result = CompileRun("for (var i = 0; i < 8; i++) {"
" ext_array[i] = 5;" " ext_array[i] = 5;"
@ -10166,7 +10181,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
"}" "}"
"ext_array[5];"); "ext_array[5];");
CHECK_EQ(0, result->Int32Value()); CHECK_EQ(0, result->Int32Value());
CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(5))->value()); CHECK_EQ(0,
i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value());
} }
result = CompileRun("ext_array[3] = 33;" result = CompileRun("ext_array[3] = 33;"

49
deps/v8/test/cctest/test-assembler-arm.cc

@ -69,9 +69,10 @@ TEST(0) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -105,9 +106,10 @@ TEST(1) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -150,9 +152,10 @@ TEST(2) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -197,9 +200,10 @@ TEST(3) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -290,9 +294,10 @@ TEST(4) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -341,9 +346,10 @@ TEST(5) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -375,9 +381,10 @@ TEST(6) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();

62
deps/v8/test/cctest/test-assembler-ia32.cc

@ -71,7 +71,8 @@ TEST(AssemblerIa320) {
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(desc,
Code::ComputeFlags(Code::STUB), Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value())); Handle<Object>(Heap::undefined_value()))->
ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -108,7 +109,8 @@ TEST(AssemblerIa321) {
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(desc,
Code::ComputeFlags(Code::STUB), Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value())); Handle<Object>(Heap::undefined_value()))->
ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -147,9 +149,11 @@ TEST(AssemblerIa322) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -180,10 +184,10 @@ TEST(AssemblerIa323) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Code* code = Code* code = Code::cast(Heap::CreateCode(
Code::cast(Heap::CreateCode(desc, desc,
Code::ComputeFlags(Code::STUB), Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))); Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
// don't print the code - our disassembler can't handle cvttss2si // don't print the code - our disassembler can't handle cvttss2si
// instead print bytes // instead print bytes
Disassembler::Dump(stdout, Disassembler::Dump(stdout,
@ -214,10 +218,10 @@ TEST(AssemblerIa324) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Code* code = Code* code = Code::cast(Heap::CreateCode(
Code::cast(Heap::CreateCode(desc, desc,
Code::ComputeFlags(Code::STUB), Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))); Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
// don't print the code - our disassembler can't handle cvttsd2si // don't print the code - our disassembler can't handle cvttsd2si
// instead print bytes // instead print bytes
Disassembler::Dump(stdout, Disassembler::Dump(stdout,
@ -243,10 +247,10 @@ TEST(AssemblerIa325) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Code* code = Code* code = Code::cast(Heap::CreateCode(
Code::cast(Heap::CreateCode(desc, desc,
Code::ComputeFlags(Code::STUB), Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))); Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
F0 f = FUNCTION_CAST<F0>(code->entry()); F0 f = FUNCTION_CAST<F0>(code->entry());
int res = f(); int res = f();
CHECK_EQ(42, res); CHECK_EQ(42, res);
@ -280,10 +284,10 @@ TEST(AssemblerIa326) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Code* code = Code* code = Code::cast(Heap::CreateCode(
Code::cast(Heap::CreateCode(desc, desc,
Code::ComputeFlags(Code::STUB), Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))); Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
#ifdef DEBUG #ifdef DEBUG
::printf("\n---\n"); ::printf("\n---\n");
// don't print the code - our disassembler can't handle SSE instructions // don't print the code - our disassembler can't handle SSE instructions
@ -320,10 +324,10 @@ TEST(AssemblerIa328) {
__ ret(0); __ ret(0);
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Code* code = Code* code = Code::cast(Heap::CreateCode(
Code::cast(Heap::CreateCode(desc, desc,
Code::ComputeFlags(Code::STUB), Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))); Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();
@ -375,10 +379,10 @@ TEST(AssemblerIa329) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Code* code = Code* code = Code::cast(Heap::CreateCode(
Code::cast(Heap::CreateCode(desc, desc,
Code::ComputeFlags(Code::STUB), Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))); Handle<Object>(Heap::undefined_value()))->ToObjectChecked());
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();

22
deps/v8/test/cctest/test-compiler.cc

@ -98,7 +98,7 @@ static void InitializeVM() {
} }
static Object* GetGlobalProperty(const char* name) { static MaybeObject* GetGlobalProperty(const char* name) {
Handle<String> symbol = Factory::LookupAsciiSymbol(name); Handle<String> symbol = Factory::LookupAsciiSymbol(name);
return Top::context()->global()->GetProperty(*symbol); return Top::context()->global()->GetProperty(*symbol);
} }
@ -140,7 +140,7 @@ static double Inc(int x) {
Handle<JSObject> global(Top::context()->global()); Handle<JSObject> global(Top::context()->global());
Execution::Call(fun, global, 0, NULL, &has_pending_exception); Execution::Call(fun, global, 0, NULL, &has_pending_exception);
CHECK(!has_pending_exception); CHECK(!has_pending_exception);
return GetGlobalProperty("result")->Number(); return GetGlobalProperty("result")->ToObjectChecked()->Number();
} }
@ -161,7 +161,7 @@ static double Add(int x, int y) {
Handle<JSObject> global(Top::context()->global()); Handle<JSObject> global(Top::context()->global());
Execution::Call(fun, global, 0, NULL, &has_pending_exception); Execution::Call(fun, global, 0, NULL, &has_pending_exception);
CHECK(!has_pending_exception); CHECK(!has_pending_exception);
return GetGlobalProperty("result")->Number(); return GetGlobalProperty("result")->ToObjectChecked()->Number();
} }
@ -181,7 +181,7 @@ static double Abs(int x) {
Handle<JSObject> global(Top::context()->global()); Handle<JSObject> global(Top::context()->global());
Execution::Call(fun, global, 0, NULL, &has_pending_exception); Execution::Call(fun, global, 0, NULL, &has_pending_exception);
CHECK(!has_pending_exception); CHECK(!has_pending_exception);
return GetGlobalProperty("result")->Number(); return GetGlobalProperty("result")->ToObjectChecked()->Number();
} }
@ -202,7 +202,7 @@ static double Sum(int n) {
Handle<JSObject> global(Top::context()->global()); Handle<JSObject> global(Top::context()->global());
Execution::Call(fun, global, 0, NULL, &has_pending_exception); Execution::Call(fun, global, 0, NULL, &has_pending_exception);
CHECK(!has_pending_exception); CHECK(!has_pending_exception);
return GetGlobalProperty("result")->Number(); return GetGlobalProperty("result")->ToObjectChecked()->Number();
} }
@ -256,7 +256,7 @@ TEST(Stuff) {
Handle<JSObject> global(Top::context()->global()); Handle<JSObject> global(Top::context()->global());
Execution::Call(fun, global, 0, NULL, &has_pending_exception); Execution::Call(fun, global, 0, NULL, &has_pending_exception);
CHECK(!has_pending_exception); CHECK(!has_pending_exception);
CHECK_EQ(511.0, GetGlobalProperty("r")->Number()); CHECK_EQ(511.0, GetGlobalProperty("r")->ToObjectChecked()->Number());
} }
@ -272,7 +272,7 @@ TEST(UncaughtThrow) {
Handle<Object> result = Handle<Object> result =
Execution::Call(fun, global, 0, NULL, &has_pending_exception); Execution::Call(fun, global, 0, NULL, &has_pending_exception);
CHECK(has_pending_exception); CHECK(has_pending_exception);
CHECK_EQ(42.0, Top::pending_exception()->Number()); CHECK_EQ(42.0, Top::pending_exception()->ToObjectChecked()->Number());
} }
@ -297,10 +297,10 @@ TEST(C2JSFrames) {
Execution::Call(fun0, global, 0, NULL, &has_pending_exception); Execution::Call(fun0, global, 0, NULL, &has_pending_exception);
CHECK(!has_pending_exception); CHECK(!has_pending_exception);
Handle<Object> fun1 = Object* foo_symbol = Factory::LookupAsciiSymbol("foo")->ToObjectChecked();
Handle<Object>( MaybeObject* fun1_object =
Top::context()->global()->GetProperty( Top::context()->global()->GetProperty(String::cast(foo_symbol));
*Factory::LookupAsciiSymbol("foo"))); Handle<Object> fun1(fun1_object->ToObjectChecked());
CHECK(fun1->IsJSFunction()); CHECK(fun1->IsJSFunction());
Object** argv[1] = { Object** argv[1] = {

7
deps/v8/test/cctest/test-disasm-ia32.cc

@ -438,9 +438,10 @@ TEST(DisasmIa320) {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
#ifdef DEBUG #ifdef DEBUG
Code::cast(code)->Print(); Code::cast(code)->Print();

159
deps/v8/test/cctest/test-heap.cc

@ -58,7 +58,7 @@ static void CheckSmi(int value, const char* string) {
static void CheckNumber(double value, const char* string) { static void CheckNumber(double value, const char* string) {
Object* obj = Heap::NumberFromDouble(value); Object* obj = Heap::NumberFromDouble(value)->ToObjectChecked();
CHECK(obj->IsNumber()); CHECK(obj->IsNumber());
bool exc; bool exc;
Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc); Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
@ -76,9 +76,10 @@ static void CheckFindCodeObject() {
CodeDesc desc; CodeDesc desc;
assm.GetCode(&desc); assm.GetCode(&desc);
Object* code = Heap::CreateCode(desc, Object* code = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(code->IsCode()); CHECK(code->IsCode());
HeapObject* obj = HeapObject::cast(code); HeapObject* obj = HeapObject::cast(code);
@ -89,9 +90,10 @@ static void CheckFindCodeObject() {
CHECK_EQ(code, found); CHECK_EQ(code, found);
} }
Object* copy = Heap::CreateCode(desc, Object* copy = Heap::CreateCode(
Code::ComputeFlags(Code::STUB), desc,
Handle<Object>(Heap::undefined_value())); Code::ComputeFlags(Code::STUB),
Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
CHECK(copy->IsCode()); CHECK(copy->IsCode());
HeapObject* obj_copy = HeapObject::cast(copy); HeapObject* obj_copy = HeapObject::cast(copy);
Object* not_right = Heap::FindCodeObject(obj_copy->address() + Object* not_right = Heap::FindCodeObject(obj_copy->address() +
@ -104,40 +106,42 @@ TEST(HeapObjects) {
InitializeVM(); InitializeVM();
v8::HandleScope sc; v8::HandleScope sc;
Object* value = Heap::NumberFromDouble(1.000123); Object* value = Heap::NumberFromDouble(1.000123)->ToObjectChecked();
CHECK(value->IsHeapNumber()); CHECK(value->IsHeapNumber());
CHECK(value->IsNumber()); CHECK(value->IsNumber());
CHECK_EQ(1.000123, value->Number()); CHECK_EQ(1.000123, value->Number());
value = Heap::NumberFromDouble(1.0); value = Heap::NumberFromDouble(1.0)->ToObjectChecked();
CHECK(value->IsSmi()); CHECK(value->IsSmi());
CHECK(value->IsNumber()); CHECK(value->IsNumber());
CHECK_EQ(1.0, value->Number()); CHECK_EQ(1.0, value->Number());
value = Heap::NumberFromInt32(1024); value = Heap::NumberFromInt32(1024)->ToObjectChecked();
CHECK(value->IsSmi()); CHECK(value->IsSmi());
CHECK(value->IsNumber()); CHECK(value->IsNumber());
CHECK_EQ(1024.0, value->Number()); CHECK_EQ(1024.0, value->Number());
value = Heap::NumberFromInt32(Smi::kMinValue); value = Heap::NumberFromInt32(Smi::kMinValue)->ToObjectChecked();
CHECK(value->IsSmi()); CHECK(value->IsSmi());
CHECK(value->IsNumber()); CHECK(value->IsNumber());
CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value()); CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value());
value = Heap::NumberFromInt32(Smi::kMaxValue); value = Heap::NumberFromInt32(Smi::kMaxValue)->ToObjectChecked();
CHECK(value->IsSmi()); CHECK(value->IsSmi());
CHECK(value->IsNumber()); CHECK(value->IsNumber());
CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value()); CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value());
#ifndef V8_TARGET_ARCH_X64 #ifndef V8_TARGET_ARCH_X64
// TODO(lrn): We need a NumberFromIntptr function in order to test this. // TODO(lrn): We need a NumberFromIntptr function in order to test this.
value = Heap::NumberFromInt32(Smi::kMinValue - 1); value = Heap::NumberFromInt32(Smi::kMinValue - 1)->ToObjectChecked();
CHECK(value->IsHeapNumber()); CHECK(value->IsHeapNumber());
CHECK(value->IsNumber()); CHECK(value->IsNumber());
CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number()); CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number());
#endif #endif
value = Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1); MaybeObject* maybe_value =
Heap::NumberFromUint32(static_cast<uint32_t>(Smi::kMaxValue) + 1);
value = maybe_value->ToObjectChecked();
CHECK(value->IsHeapNumber()); CHECK(value->IsHeapNumber());
CHECK(value->IsNumber()); CHECK(value->IsNumber());
CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1), CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1),
@ -208,11 +212,13 @@ TEST(GarbageCollection) {
Handle<Map> initial_map = Handle<Map> initial_map =
Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
function->set_initial_map(*initial_map); function->set_initial_map(*initial_map);
Top::context()->global()->SetProperty(*name, *function, NONE); Top::context()->global()->SetProperty(*name,
*function,
NONE)->ToObjectChecked();
// Allocate an object. Unrooted after leaving the scope. // Allocate an object. Unrooted after leaving the scope.
Handle<JSObject> obj = Factory::NewJSObject(function); Handle<JSObject> obj = Factory::NewJSObject(function);
obj->SetProperty(*prop_name, Smi::FromInt(23), NONE); obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
obj->SetProperty(*prop_namex, Smi::FromInt(24), NONE); obj->SetProperty(*prop_namex, Smi::FromInt(24), NONE)->ToObjectChecked();
CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex)); CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex));
@ -223,7 +229,8 @@ TEST(GarbageCollection) {
// Function should be alive. // Function should be alive.
CHECK(Top::context()->global()->HasLocalProperty(*name)); CHECK(Top::context()->global()->HasLocalProperty(*name));
// Check function is retained. // Check function is retained.
Object* func_value = Top::context()->global()->GetProperty(*name); Object* func_value =
Top::context()->global()->GetProperty(*name)->ToObjectChecked();
CHECK(func_value->IsJSFunction()); CHECK(func_value->IsJSFunction());
Handle<JSFunction> function(JSFunction::cast(func_value)); Handle<JSFunction> function(JSFunction::cast(func_value));
@ -231,18 +238,22 @@ TEST(GarbageCollection) {
HandleScope inner_scope; HandleScope inner_scope;
// Allocate another object, make it reachable from global. // Allocate another object, make it reachable from global.
Handle<JSObject> obj = Factory::NewJSObject(function); Handle<JSObject> obj = Factory::NewJSObject(function);
Top::context()->global()->SetProperty(*obj_name, *obj, NONE); Top::context()->global()->SetProperty(*obj_name,
obj->SetProperty(*prop_name, Smi::FromInt(23), NONE); *obj,
NONE)->ToObjectChecked();
obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
} }
// After gc, it should survive. // After gc, it should survive.
Heap::CollectGarbage(NEW_SPACE); Heap::CollectGarbage(NEW_SPACE);
CHECK(Top::context()->global()->HasLocalProperty(*obj_name)); CHECK(Top::context()->global()->HasLocalProperty(*obj_name));
CHECK(Top::context()->global()->GetProperty(*obj_name)->IsJSObject()); CHECK(Top::context()->global()->GetProperty(*obj_name)->ToObjectChecked()->
JSObject* obj = IsJSObject());
JSObject::cast(Top::context()->global()->GetProperty(*obj_name)); Object* obj =
CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); Top::context()->global()->GetProperty(*obj_name)->ToObjectChecked();
JSObject* js_obj = JSObject::cast(obj);
CHECK_EQ(Smi::FromInt(23), js_obj->GetProperty(*prop_name));
} }
@ -494,12 +505,14 @@ static const char* not_so_random_string_table[] = {
static void CheckSymbols(const char** strings) { static void CheckSymbols(const char** strings) {
for (const char* string = *strings; *strings != 0; string = *strings++) { for (const char* string = *strings; *strings != 0; string = *strings++) {
Object* a = Heap::LookupAsciiSymbol(string); Object* a;
MaybeObject* maybe_a = Heap::LookupAsciiSymbol(string);
// LookupAsciiSymbol may return a failure if a GC is needed. // LookupAsciiSymbol may return a failure if a GC is needed.
if (a->IsFailure()) continue; if (!maybe_a->ToObject(&a)) continue;
CHECK(a->IsSymbol()); CHECK(a->IsSymbol());
Object* b = Heap::LookupAsciiSymbol(string); Object* b;
if (b->IsFailure()) continue; MaybeObject* maybe_b = Heap::LookupAsciiSymbol(string);
if (!maybe_b->ToObject(&b)) continue;
CHECK_EQ(b, a); CHECK_EQ(b, a);
CHECK(String::cast(b)->IsEqualTo(CStrVector(string))); CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
} }
@ -527,10 +540,12 @@ TEST(FunctionAllocation) {
Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot"); Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot");
Handle<JSObject> obj = Factory::NewJSObject(function); Handle<JSObject> obj = Factory::NewJSObject(function);
obj->SetProperty(*prop_name, Smi::FromInt(23), NONE); obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
// Check that we can add properties to function objects. // Check that we can add properties to function objects.
function->SetProperty(*prop_name, Smi::FromInt(24), NONE); function->SetProperty(*prop_name,
Smi::FromInt(24),
NONE)->ToObjectChecked();
CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name)); CHECK_EQ(Smi::FromInt(24), function->GetProperty(*prop_name));
} }
@ -540,8 +555,9 @@ TEST(ObjectProperties) {
v8::HandleScope sc; v8::HandleScope sc;
String* object_symbol = String::cast(Heap::Object_symbol()); String* object_symbol = String::cast(Heap::Object_symbol());
JSFunction* object_function = Object* raw_object =
JSFunction::cast(Top::context()->global()->GetProperty(object_symbol)); Top::context()->global()->GetProperty(object_symbol)->ToObjectChecked();
JSFunction* object_function = JSFunction::cast(raw_object);
Handle<JSFunction> constructor(object_function); Handle<JSFunction> constructor(object_function);
Handle<JSObject> obj = Factory::NewJSObject(constructor); Handle<JSObject> obj = Factory::NewJSObject(constructor);
Handle<String> first = Factory::LookupAsciiSymbol("first"); Handle<String> first = Factory::LookupAsciiSymbol("first");
@ -551,7 +567,7 @@ TEST(ObjectProperties) {
CHECK(!obj->HasLocalProperty(*first)); CHECK(!obj->HasLocalProperty(*first));
// add first // add first
obj->SetProperty(*first, Smi::FromInt(1), NONE); obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
CHECK(obj->HasLocalProperty(*first)); CHECK(obj->HasLocalProperty(*first));
// delete first // delete first
@ -559,8 +575,8 @@ TEST(ObjectProperties) {
CHECK(!obj->HasLocalProperty(*first)); CHECK(!obj->HasLocalProperty(*first));
// add first and then second // add first and then second
obj->SetProperty(*first, Smi::FromInt(1), NONE); obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
obj->SetProperty(*second, Smi::FromInt(2), NONE); obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked();
CHECK(obj->HasLocalProperty(*first)); CHECK(obj->HasLocalProperty(*first));
CHECK(obj->HasLocalProperty(*second)); CHECK(obj->HasLocalProperty(*second));
@ -572,8 +588,8 @@ TEST(ObjectProperties) {
CHECK(!obj->HasLocalProperty(*second)); CHECK(!obj->HasLocalProperty(*second));
// add first and then second // add first and then second
obj->SetProperty(*first, Smi::FromInt(1), NONE); obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
obj->SetProperty(*second, Smi::FromInt(2), NONE); obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked();
CHECK(obj->HasLocalProperty(*first)); CHECK(obj->HasLocalProperty(*first));
CHECK(obj->HasLocalProperty(*second)); CHECK(obj->HasLocalProperty(*second));
@ -587,14 +603,14 @@ TEST(ObjectProperties) {
// check string and symbol match // check string and symbol match
static const char* string1 = "fisk"; static const char* string1 = "fisk";
Handle<String> s1 = Factory::NewStringFromAscii(CStrVector(string1)); Handle<String> s1 = Factory::NewStringFromAscii(CStrVector(string1));
obj->SetProperty(*s1, Smi::FromInt(1), NONE); obj->SetProperty(*s1, Smi::FromInt(1), NONE)->ToObjectChecked();
Handle<String> s1_symbol = Factory::LookupAsciiSymbol(string1); Handle<String> s1_symbol = Factory::LookupAsciiSymbol(string1);
CHECK(obj->HasLocalProperty(*s1_symbol)); CHECK(obj->HasLocalProperty(*s1_symbol));
// check symbol and string match // check symbol and string match
static const char* string2 = "fugl"; static const char* string2 = "fugl";
Handle<String> s2_symbol = Factory::LookupAsciiSymbol(string2); Handle<String> s2_symbol = Factory::LookupAsciiSymbol(string2);
obj->SetProperty(*s2_symbol, Smi::FromInt(1), NONE); obj->SetProperty(*s2_symbol, Smi::FromInt(1), NONE)->ToObjectChecked();
Handle<String> s2 = Factory::NewStringFromAscii(CStrVector(string2)); Handle<String> s2 = Factory::NewStringFromAscii(CStrVector(string2));
CHECK(obj->HasLocalProperty(*s2)); CHECK(obj->HasLocalProperty(*s2));
} }
@ -615,7 +631,7 @@ TEST(JSObjectMaps) {
Handle<JSObject> obj = Factory::NewJSObject(function); Handle<JSObject> obj = Factory::NewJSObject(function);
// Set a propery // Set a propery
obj->SetProperty(*prop_name, Smi::FromInt(23), NONE); obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name));
// Check the map has changed // Check the map has changed
@ -628,33 +644,31 @@ TEST(JSArray) {
v8::HandleScope sc; v8::HandleScope sc;
Handle<String> name = Factory::LookupAsciiSymbol("Array"); Handle<String> name = Factory::LookupAsciiSymbol("Array");
Object* raw_object =
Top::context()->global()->GetProperty(*name)->ToObjectChecked();
Handle<JSFunction> function = Handle<JSFunction>( Handle<JSFunction> function = Handle<JSFunction>(
JSFunction::cast(Top::context()->global()->GetProperty(*name))); JSFunction::cast(raw_object));
// Allocate the object. // Allocate the object.
Handle<JSObject> object = Factory::NewJSObject(function); Handle<JSObject> object = Factory::NewJSObject(function);
Handle<JSArray> array = Handle<JSArray>::cast(object); Handle<JSArray> array = Handle<JSArray>::cast(object);
Object* ok = array->Initialize(0);
// We just initialized the VM, no heap allocation failure yet. // We just initialized the VM, no heap allocation failure yet.
CHECK(!ok->IsFailure()); Object* ok = array->Initialize(0)->ToObjectChecked();
// Set array length to 0. // Set array length to 0.
ok = array->SetElementsLength(Smi::FromInt(0)); ok = array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked();
CHECK(!ok->IsFailure());
CHECK_EQ(Smi::FromInt(0), array->length()); CHECK_EQ(Smi::FromInt(0), array->length());
CHECK(array->HasFastElements()); // Must be in fast mode. CHECK(array->HasFastElements()); // Must be in fast mode.
// array[length] = name. // array[length] = name.
ok = array->SetElement(0, *name); ok = array->SetElement(0, *name)->ToObjectChecked();
CHECK(!ok->IsFailure());
CHECK_EQ(Smi::FromInt(1), array->length()); CHECK_EQ(Smi::FromInt(1), array->length());
CHECK_EQ(array->GetElement(0), *name); CHECK_EQ(array->GetElement(0), *name);
// Set array length with larger than smi value. // Set array length with larger than smi value.
Handle<Object> length = Handle<Object> length =
Factory::NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1); Factory::NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1);
ok = array->SetElementsLength(*length); ok = array->SetElementsLength(*length)->ToObjectChecked();
CHECK(!ok->IsFailure());
uint32_t int_length = 0; uint32_t int_length = 0;
CHECK(length->ToArrayIndex(&int_length)); CHECK(length->ToArrayIndex(&int_length));
@ -662,8 +676,7 @@ TEST(JSArray) {
CHECK(array->HasDictionaryElements()); // Must be in slow mode. CHECK(array->HasDictionaryElements()); // Must be in slow mode.
// array[length] = name. // array[length] = name.
ok = array->SetElement(int_length, *name); ok = array->SetElement(int_length, *name)->ToObjectChecked();
CHECK(!ok->IsFailure());
uint32_t new_int_length = 0; uint32_t new_int_length = 0;
CHECK(array->length()->ToArrayIndex(&new_int_length)); CHECK(array->length()->ToArrayIndex(&new_int_length));
CHECK_EQ(static_cast<double>(int_length), new_int_length - 1); CHECK_EQ(static_cast<double>(int_length), new_int_length - 1);
@ -677,21 +690,20 @@ TEST(JSObjectCopy) {
v8::HandleScope sc; v8::HandleScope sc;
String* object_symbol = String::cast(Heap::Object_symbol()); String* object_symbol = String::cast(Heap::Object_symbol());
JSFunction* object_function = Object* raw_object =
JSFunction::cast(Top::context()->global()->GetProperty(object_symbol)); Top::context()->global()->GetProperty(object_symbol)->ToObjectChecked();
JSFunction* object_function = JSFunction::cast(raw_object);
Handle<JSFunction> constructor(object_function); Handle<JSFunction> constructor(object_function);
Handle<JSObject> obj = Factory::NewJSObject(constructor); Handle<JSObject> obj = Factory::NewJSObject(constructor);
Handle<String> first = Factory::LookupAsciiSymbol("first"); Handle<String> first = Factory::LookupAsciiSymbol("first");
Handle<String> second = Factory::LookupAsciiSymbol("second"); Handle<String> second = Factory::LookupAsciiSymbol("second");
obj->SetProperty(*first, Smi::FromInt(1), NONE); obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked();
obj->SetProperty(*second, Smi::FromInt(2), NONE); obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked();
Object* ok = obj->SetElement(0, *first); Object* ok = obj->SetElement(0, *first)->ToObjectChecked();
CHECK(!ok->IsFailure());
ok = obj->SetElement(1, *second); ok = obj->SetElement(1, *second)->ToObjectChecked();
CHECK(!ok->IsFailure());
// Make the clone. // Make the clone.
Handle<JSObject> clone = Copy(obj); Handle<JSObject> clone = Copy(obj);
@ -704,13 +716,11 @@ TEST(JSObjectCopy) {
CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second)); CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second));
// Flip the values. // Flip the values.
clone->SetProperty(*first, Smi::FromInt(2), NONE); clone->SetProperty(*first, Smi::FromInt(2), NONE)->ToObjectChecked();
clone->SetProperty(*second, Smi::FromInt(1), NONE); clone->SetProperty(*second, Smi::FromInt(1), NONE)->ToObjectChecked();
ok = clone->SetElement(0, *second); ok = clone->SetElement(0, *second)->ToObjectChecked();
CHECK(!ok->IsFailure()); ok = clone->SetElement(1, *first)->ToObjectChecked();
ok = clone->SetElement(1, *first);
CHECK(!ok->IsFailure());
CHECK_EQ(obj->GetElement(1), clone->GetElement(0)); CHECK_EQ(obj->GetElement(1), clone->GetElement(0));
CHECK_EQ(obj->GetElement(0), clone->GetElement(1)); CHECK_EQ(obj->GetElement(0), clone->GetElement(1));
@ -836,7 +846,7 @@ TEST(LargeObjectSpaceContains) {
kPointerSize; kPointerSize;
CHECK_EQ(bytes_to_allocate, FixedArray::SizeFor(n_elements)); CHECK_EQ(bytes_to_allocate, FixedArray::SizeFor(n_elements));
FixedArray* array = FixedArray::cast( FixedArray* array = FixedArray::cast(
Heap::AllocateFixedArray(n_elements)); Heap::AllocateFixedArray(n_elements)->ToObjectChecked());
int index = n_elements - 1; int index = n_elements - 1;
CHECK_EQ(flags_ptr, CHECK_EQ(flags_ptr,
@ -908,8 +918,8 @@ TEST(Regression39128) {
Address* limit_addr = new_space->allocation_limit_address(); Address* limit_addr = new_space->allocation_limit_address();
while ((*limit_addr - *top_addr) > allocation_amount) { while ((*limit_addr - *top_addr) > allocation_amount) {
CHECK(!Heap::always_allocate()); CHECK(!Heap::always_allocate());
Object* array = Heap::AllocateFixedArray(allocation_len); Object* array =
CHECK(!array->IsFailure()); Heap::AllocateFixedArray(allocation_len)->ToObjectChecked();
CHECK(new_space->Contains(array)); CHECK(new_space->Contains(array));
} }
@ -919,12 +929,11 @@ TEST(Regression39128) {
CHECK(fixed_array_len < FixedArray::kMaxLength); CHECK(fixed_array_len < FixedArray::kMaxLength);
CHECK(!Heap::always_allocate()); CHECK(!Heap::always_allocate());
Object* array = Heap::AllocateFixedArray(fixed_array_len); Object* array =
CHECK(!array->IsFailure()); Heap::AllocateFixedArray(fixed_array_len)->ToObjectChecked();
CHECK(new_space->Contains(array)); CHECK(new_space->Contains(array));
Object* object = Heap::AllocateJSObjectFromMap(*my_map); Object* object = Heap::AllocateJSObjectFromMap(*my_map)->ToObjectChecked();
CHECK(!object->IsFailure());
CHECK(new_space->Contains(object)); CHECK(new_space->Contains(object));
JSObject* jsobject = JSObject::cast(object); JSObject* jsobject = JSObject::cast(object);
CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length()); CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length());
@ -938,8 +947,7 @@ TEST(Regression39128) {
// in old pointer space. // in old pointer space.
Address old_pointer_space_top = Heap::old_pointer_space()->top(); Address old_pointer_space_top = Heap::old_pointer_space()->top();
AlwaysAllocateScope aa_scope; AlwaysAllocateScope aa_scope;
Object* clone_obj = Heap::CopyJSObject(jsobject); Object* clone_obj = Heap::CopyJSObject(jsobject)->ToObjectChecked();
CHECK(!object->IsFailure());
JSObject* clone = JSObject::cast(clone_obj); JSObject* clone = JSObject::cast(clone_obj);
if (clone->address() != old_pointer_space_top) { if (clone->address() != old_pointer_space_top) {
// Alas, got allocated from free list, we cannot do checks. // Alas, got allocated from free list, we cannot do checks.
@ -973,7 +981,8 @@ TEST(TestCodeFlushing) {
CompileRun(source); CompileRun(source);
// Check function is compiled. // Check function is compiled.
Object* func_value = Top::context()->global()->GetProperty(*foo_name); Object* func_value =
Top::context()->global()->GetProperty(*foo_name)->ToObjectChecked();
CHECK(func_value->IsJSFunction()); CHECK(func_value->IsJSFunction());
Handle<JSFunction> function(JSFunction::cast(func_value)); Handle<JSFunction> function(JSFunction::cast(func_value));
CHECK(function->shared()->is_compiled()); CHECK(function->shared()->is_compiled());

36
deps/v8/test/cctest/test-log-stack-tracer.cc

@ -199,13 +199,6 @@ static void InitializeVM() {
} }
static Handle<JSFunction> CompileFunction(const char* source) {
Handle<JSFunction> result(JSFunction::cast(
*v8::Utils::OpenHandle(*Script::Compile(String::New(source)))));
return result;
}
static void CheckJSFunctionAtAddress(const char* func_name, Address addr) { static void CheckJSFunctionAtAddress(const char* func_name, Address addr) {
i::Object* obj = i::HeapObject::FromAddress(addr); i::Object* obj = i::HeapObject::FromAddress(addr);
CHECK(obj->IsJSFunction()); CHECK(obj->IsJSFunction());
@ -218,16 +211,6 @@ static void CheckJSFunctionAtAddress(const char* func_name, Address addr) {
} }
static void SetGlobalProperty(const char* name, Local<Value> value) {
env->Global()->Set(String::New(name), value);
}
static Handle<v8::internal::String> NewString(const char* s) {
return i::Factory::NewStringFromAscii(i::CStrVector(s));
}
// This C++ function is called as a constructor, to grab the frame pointer // This C++ function is called as a constructor, to grab the frame pointer
// from the calling function. When this function runs, the stack contains // from the calling function. When this function runs, the stack contains
// a C_Entry frame and a Construct frame above the calling function's frame. // a C_Entry frame and a Construct frame above the calling function's frame.
@ -273,25 +256,18 @@ static void CreateTraceCallerFunction(const char* func_name,
const char* trace_func_name) { const char* trace_func_name) {
i::EmbeddedVector<char, 256> trace_call_buf; i::EmbeddedVector<char, 256> trace_call_buf;
i::OS::SNPrintF(trace_call_buf, i::OS::SNPrintF(trace_call_buf,
"fp = new FPGrabber(); %s(fp.low_bits, fp.high_bits);", "function %s() {"
trace_func_name); " fp = new FPGrabber();"
" %s(fp.low_bits, fp.high_bits);"
"}",
func_name, trace_func_name);
// Create the FPGrabber function, which grabs the caller's frame pointer // Create the FPGrabber function, which grabs the caller's frame pointer
// when called as a constructor. // when called as a constructor.
CreateFramePointerGrabberConstructor("FPGrabber"); CreateFramePointerGrabberConstructor("FPGrabber");
// Compile the script. // Compile the script.
Handle<JSFunction> func = CompileFunction(trace_call_buf.start()); CompileRun(trace_call_buf.start());
CHECK(!func.is_null());
func->shared()->set_name(*NewString(func_name));
#ifdef DEBUG
v8::internal::Code* func_code = func->code();
CHECK(func_code->IsCode());
func_code->Print();
#endif
SetGlobalProperty(func_name, v8::ToApi<Value>(func));
} }

4
deps/v8/test/cctest/test-log.cc

@ -337,8 +337,8 @@ TEST(ProfLazyMode) {
} }
// Profiling multiple threads that use V8 is currently only available on Linux. // BUG(913). Need to implement support for profiling multiple VM threads.
#ifdef __linux__ #if 0
namespace { namespace {

95
deps/v8/test/cctest/test-mark-compact.cc

@ -85,8 +85,7 @@ TEST(Promotion) {
int array_size = int array_size =
(Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) /
(kPointerSize * 4); (kPointerSize * 4);
Object* obj = Heap::AllocateFixedArray(array_size); Object* obj = Heap::AllocateFixedArray(array_size)->ToObjectChecked();
CHECK(!obj->IsFailure());
Handle<FixedArray> array(FixedArray::cast(obj)); Handle<FixedArray> array(FixedArray::cast(obj));
@ -116,7 +115,7 @@ TEST(NoPromotion) {
// Allocate a big Fixed array in the new space. // Allocate a big Fixed array in the new space.
int size = (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / int size = (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) /
kPointerSize; kPointerSize;
Object* obj = Heap::AllocateFixedArray(size); Object* obj = Heap::AllocateFixedArray(size)->ToObjectChecked();
Handle<FixedArray> array(FixedArray::cast(obj)); Handle<FixedArray> array(FixedArray::cast(obj));
@ -126,8 +125,10 @@ TEST(NoPromotion) {
// Allocate objects in the old space until out of memory. // Allocate objects in the old space until out of memory.
FixedArray* host = *array; FixedArray* host = *array;
while (true) { while (true) {
Object* obj = Heap::AllocateFixedArray(100, TENURED); Object* obj;
if (obj->IsFailure()) break; { MaybeObject* maybe_obj = Heap::AllocateFixedArray(100, TENURED);
if (!maybe_obj->ToObject(&obj)) break;
}
host->set(0, obj); host->set(0, obj);
host = FixedArray::cast(obj); host = FixedArray::cast(obj);
@ -151,59 +152,75 @@ TEST(MarkCompactCollector) {
// keep allocating garbage in new space until it fails // keep allocating garbage in new space until it fails
const int ARRAY_SIZE = 100; const int ARRAY_SIZE = 100;
Object* array; Object* array;
MaybeObject* maybe_array;
do { do {
array = Heap::AllocateFixedArray(ARRAY_SIZE); maybe_array = Heap::AllocateFixedArray(ARRAY_SIZE);
} while (!array->IsFailure()); } while (maybe_array->ToObject(&array));
Heap::CollectGarbage(NEW_SPACE); Heap::CollectGarbage(NEW_SPACE);
array = Heap::AllocateFixedArray(ARRAY_SIZE); array = Heap::AllocateFixedArray(ARRAY_SIZE)->ToObjectChecked();
CHECK(!array->IsFailure());
// keep allocating maps until it fails // keep allocating maps until it fails
Object* mapp; Object* mapp;
MaybeObject* maybe_mapp;
do { do {
mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); maybe_mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
} while (!mapp->IsFailure()); } while (maybe_mapp->ToObject(&mapp));
Heap::CollectGarbage(MAP_SPACE); Heap::CollectGarbage(MAP_SPACE);
mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); mapp = Heap::AllocateMap(JS_OBJECT_TYPE,
CHECK(!mapp->IsFailure()); JSObject::kHeaderSize)->ToObjectChecked();
// allocate a garbage // allocate a garbage
String* func_name = String::cast(Heap::LookupAsciiSymbol("theFunction")); String* func_name =
SharedFunctionInfo* function_share = String::cast(Heap::LookupAsciiSymbol("theFunction")->ToObjectChecked());
SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name)); SharedFunctionInfo* function_share = SharedFunctionInfo::cast(
JSFunction* function = Heap::AllocateSharedFunctionInfo(func_name)->ToObjectChecked());
JSFunction::cast(Heap::AllocateFunction(*Top::function_map(), JSFunction* function = JSFunction::cast(
function_share, Heap::AllocateFunction(*Top::function_map(),
Heap::undefined_value())); function_share,
Heap::undefined_value())->ToObjectChecked());
Map* initial_map = Map* initial_map =
Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize)); Map::cast(Heap::AllocateMap(JS_OBJECT_TYPE,
JSObject::kHeaderSize)->ToObjectChecked());
function->set_initial_map(initial_map); function->set_initial_map(initial_map);
Top::context()->global()->SetProperty(func_name, function, NONE); Top::context()->global()->SetProperty(func_name,
function,
NONE)->ToObjectChecked();
JSObject* obj = JSObject::cast(Heap::AllocateJSObject(function)); JSObject* obj =
JSObject::cast(Heap::AllocateJSObject(function)->ToObjectChecked());
Heap::CollectGarbage(OLD_POINTER_SPACE); Heap::CollectGarbage(OLD_POINTER_SPACE);
func_name = String::cast(Heap::LookupAsciiSymbol("theFunction")); func_name =
String::cast(Heap::LookupAsciiSymbol("theFunction")->ToObjectChecked());
CHECK(Top::context()->global()->HasLocalProperty(func_name)); CHECK(Top::context()->global()->HasLocalProperty(func_name));
Object* func_value = Top::context()->global()->GetProperty(func_name); Object* func_value =
Top::context()->global()->GetProperty(func_name)->ToObjectChecked();
CHECK(func_value->IsJSFunction()); CHECK(func_value->IsJSFunction());
function = JSFunction::cast(func_value); function = JSFunction::cast(func_value);
obj = JSObject::cast(Heap::AllocateJSObject(function)); obj = JSObject::cast(Heap::AllocateJSObject(function)->ToObjectChecked());
String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject")); String* obj_name =
Top::context()->global()->SetProperty(obj_name, obj, NONE); String::cast(Heap::LookupAsciiSymbol("theObject")->ToObjectChecked());
String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot")); Top::context()->global()->SetProperty(obj_name,
obj->SetProperty(prop_name, Smi::FromInt(23), NONE); obj,
NONE)->ToObjectChecked();
String* prop_name =
String::cast(Heap::LookupAsciiSymbol("theSlot")->ToObjectChecked());
obj->SetProperty(prop_name, Smi::FromInt(23), NONE)->ToObjectChecked();
Heap::CollectGarbage(OLD_POINTER_SPACE); Heap::CollectGarbage(OLD_POINTER_SPACE);
obj_name = String::cast(Heap::LookupAsciiSymbol("theObject")); obj_name =
String::cast(Heap::LookupAsciiSymbol("theObject")->ToObjectChecked());
CHECK(Top::context()->global()->HasLocalProperty(obj_name)); CHECK(Top::context()->global()->HasLocalProperty(obj_name));
CHECK(Top::context()->global()->GetProperty(obj_name)->IsJSObject()); CHECK(Top::context()->global()->
obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name)); GetProperty(obj_name)->ToObjectChecked()->IsJSObject());
prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot")); obj = JSObject::cast(
CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23)); Top::context()->global()->GetProperty(obj_name)->ToObjectChecked());
prop_name =
String::cast(Heap::LookupAsciiSymbol("theSlot")->ToObjectChecked());
CHECK(obj->GetProperty(prop_name)->ToObjectChecked() == Smi::FromInt(23));
} }
@ -283,9 +300,9 @@ TEST(ObjectGroups) {
v8::HandleScope handle_scope; v8::HandleScope handle_scope;
Handle<Object> g1s1 = Handle<Object> g1s1 =
GlobalHandles::Create(Heap::AllocateFixedArray(1)); GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked());
Handle<Object> g1s2 = Handle<Object> g1s2 =
GlobalHandles::Create(Heap::AllocateFixedArray(1)); GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked());
GlobalHandles::MakeWeak(g1s1.location(), GlobalHandles::MakeWeak(g1s1.location(),
reinterpret_cast<void*>(1234), reinterpret_cast<void*>(1234),
&WeakPointerCallback); &WeakPointerCallback);
@ -294,9 +311,9 @@ TEST(ObjectGroups) {
&WeakPointerCallback); &WeakPointerCallback);
Handle<Object> g2s1 = Handle<Object> g2s1 =
GlobalHandles::Create(Heap::AllocateFixedArray(1)); GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked());
Handle<Object> g2s2 = Handle<Object> g2s2 =
GlobalHandles::Create(Heap::AllocateFixedArray(1)); GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked());
GlobalHandles::MakeWeak(g2s1.location(), GlobalHandles::MakeWeak(g2s1.location(),
reinterpret_cast<void*>(1234), reinterpret_cast<void*>(1234),
&WeakPointerCallback); &WeakPointerCallback);

14
deps/v8/test/cctest/test-serialize.cc

@ -576,7 +576,8 @@ TEST(LinearAllocation) {
for (int i = 0; for (int i = 0;
i + kSmallFixedArraySize <= new_space_size; i + kSmallFixedArraySize <= new_space_size;
i += kSmallFixedArraySize) { i += kSmallFixedArraySize) {
Object* obj = Heap::AllocateFixedArray(kSmallFixedArrayLength); Object* obj =
Heap::AllocateFixedArray(kSmallFixedArrayLength)->ToObjectChecked();
if (new_last != NULL) { if (new_last != NULL) {
CHECK(reinterpret_cast<char*>(obj) == CHECK(reinterpret_cast<char*>(obj) ==
reinterpret_cast<char*>(new_last) + kSmallFixedArraySize); reinterpret_cast<char*>(new_last) + kSmallFixedArraySize);
@ -588,7 +589,8 @@ TEST(LinearAllocation) {
for (int i = 0; for (int i = 0;
i + kSmallFixedArraySize <= size; i + kSmallFixedArraySize <= size;
i += kSmallFixedArraySize) { i += kSmallFixedArraySize) {
Object* obj = Heap::AllocateFixedArray(kSmallFixedArrayLength, TENURED); Object* obj = Heap::AllocateFixedArray(kSmallFixedArrayLength,
TENURED)->ToObjectChecked();
int old_page_fullness = i % Page::kPageSize; int old_page_fullness = i % Page::kPageSize;
int page_fullness = (i + kSmallFixedArraySize) % Page::kPageSize; int page_fullness = (i + kSmallFixedArraySize) % Page::kPageSize;
if (page_fullness < old_page_fullness || if (page_fullness < old_page_fullness ||
@ -605,7 +607,8 @@ TEST(LinearAllocation) {
Object* data_last = NULL; Object* data_last = NULL;
for (int i = 0; i + kSmallStringSize <= size; i += kSmallStringSize) { for (int i = 0; i + kSmallStringSize <= size; i += kSmallStringSize) {
Object* obj = Heap::AllocateRawAsciiString(kSmallStringLength, TENURED); Object* obj = Heap::AllocateRawAsciiString(kSmallStringLength,
TENURED)->ToObjectChecked();
int old_page_fullness = i % Page::kPageSize; int old_page_fullness = i % Page::kPageSize;
int page_fullness = (i + kSmallStringSize) % Page::kPageSize; int page_fullness = (i + kSmallStringSize) % Page::kPageSize;
if (page_fullness < old_page_fullness || if (page_fullness < old_page_fullness ||
@ -622,7 +625,8 @@ TEST(LinearAllocation) {
Object* map_last = NULL; Object* map_last = NULL;
for (int i = 0; i + kMapSize <= size; i += kMapSize) { for (int i = 0; i + kMapSize <= size; i += kMapSize) {
Object* obj = Heap::AllocateMap(JS_OBJECT_TYPE, 42 * kPointerSize); Object* obj = Heap::AllocateMap(JS_OBJECT_TYPE,
42 * kPointerSize)->ToObjectChecked();
int old_page_fullness = i % Page::kPageSize; int old_page_fullness = i % Page::kPageSize;
int page_fullness = (i + kMapSize) % Page::kPageSize; int page_fullness = (i + kMapSize) % Page::kPageSize;
if (page_fullness < old_page_fullness || if (page_fullness < old_page_fullness ||
@ -644,7 +648,7 @@ TEST(LinearAllocation) {
int large_object_array_length = int large_object_array_length =
(size - FixedArray::kHeaderSize) / kPointerSize; (size - FixedArray::kHeaderSize) / kPointerSize;
Object* obj = Heap::AllocateFixedArray(large_object_array_length, Object* obj = Heap::AllocateFixedArray(large_object_array_length,
TENURED); TENURED)->ToObjectChecked();
CHECK(!obj->IsFailure()); CHECK(!obj->IsFailure());
} }
} }

18
deps/v8/test/cctest/test-spaces.cc

@ -160,8 +160,8 @@ TEST(NewSpace) {
CHECK(new_space.HasBeenSetup()); CHECK(new_space.HasBeenSetup());
while (new_space.Available() >= Page::kMaxHeapObjectSize) { while (new_space.Available() >= Page::kMaxHeapObjectSize) {
Object* obj = new_space.AllocateRaw(Page::kMaxHeapObjectSize); Object* obj =
CHECK(!obj->IsFailure()); new_space.AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked();
CHECK(new_space.Contains(HeapObject::cast(obj))); CHECK(new_space.Contains(HeapObject::cast(obj)));
} }
@ -188,8 +188,7 @@ TEST(OldSpace) {
CHECK(s->Setup(start, size)); CHECK(s->Setup(start, size));
while (s->Available() > 0) { while (s->Available() > 0) {
Object* obj = s->AllocateRaw(Page::kMaxHeapObjectSize); s->AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked();
CHECK(!obj->IsFailure());
} }
s->TearDown(); s->TearDown();
@ -207,8 +206,7 @@ TEST(LargeObjectSpace) {
Map* faked_map = reinterpret_cast<Map*>(HeapObject::FromAddress(0)); Map* faked_map = reinterpret_cast<Map*>(HeapObject::FromAddress(0));
int lo_size = Page::kPageSize; int lo_size = Page::kPageSize;
Object* obj = lo->AllocateRaw(lo_size); Object* obj = lo->AllocateRaw(lo_size)->ToObjectUnchecked();
CHECK(!obj->IsFailure());
CHECK(obj->IsHeapObject()); CHECK(obj->IsHeapObject());
HeapObject* ho = HeapObject::cast(obj); HeapObject* ho = HeapObject::cast(obj);
@ -222,16 +220,16 @@ TEST(LargeObjectSpace) {
while (true) { while (true) {
intptr_t available = lo->Available(); intptr_t available = lo->Available();
obj = lo->AllocateRaw(lo_size); { MaybeObject* maybe_obj = lo->AllocateRaw(lo_size);
if (obj->IsFailure()) break; if (!maybe_obj->ToObject(&obj)) break;
}
HeapObject::cast(obj)->set_map(faked_map); HeapObject::cast(obj)->set_map(faked_map);
CHECK(lo->Available() < available); CHECK(lo->Available() < available);
}; };
CHECK(!lo->IsEmpty()); CHECK(!lo->IsEmpty());
obj = lo->AllocateRaw(lo_size); CHECK(lo->AllocateRaw(lo_size)->IsFailure());
CHECK(obj->IsFailure());
lo->TearDown(); lo->TearDown();
delete lo; delete lo;

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

@ -476,7 +476,7 @@ TEST(CachedHashOverflow) {
CHECK_EQ(results[i]->IsUndefined(), result->IsUndefined()); CHECK_EQ(results[i]->IsUndefined(), result->IsUndefined());
CHECK_EQ(results[i]->IsNumber(), result->IsNumber()); CHECK_EQ(results[i]->IsNumber(), result->IsNumber());
if (result->IsNumber()) { if (result->IsNumber()) {
CHECK_EQ(Smi::cast(results[i]->ToSmi())->value(), CHECK_EQ(Smi::cast(results[i]->ToSmi()->ToObjectChecked())->value(),
result->ToInt32()->Value()); result->ToInt32()->Value());
} }
} }

48
deps/v8/test/cctest/test-strtod.cc

@ -198,10 +198,58 @@ TEST(Strtod) {
CHECK_EQ(1234e304, StrtodChar("0000000123400000", 299)); CHECK_EQ(1234e304, StrtodChar("0000000123400000", 299));
CHECK_EQ(V8_INFINITY, StrtodChar("00000000180000000", 300)); CHECK_EQ(V8_INFINITY, StrtodChar("00000000180000000", 300));
CHECK_EQ(17e307, StrtodChar("00000000170000000", 300)); CHECK_EQ(17e307, StrtodChar("00000000170000000", 300));
CHECK_EQ(1.7976931348623157E+308, StrtodChar("17976931348623157", 292));
CHECK_EQ(1.7976931348623158E+308, StrtodChar("17976931348623158", 292));
CHECK_EQ(V8_INFINITY, StrtodChar("17976931348623159", 292));
// The following number is the result of 89255.0/1e-22. Both floating-point // The following number is the result of 89255.0/1e-22. Both floating-point
// numbers can be accurately represented with doubles. However on Linux,x86 // numbers can be accurately represented with doubles. However on Linux,x86
// the floating-point stack is set to 80bits and the double-rounding // the floating-point stack is set to 80bits and the double-rounding
// introduces an error. // introduces an error.
CHECK_EQ(89255e-22, StrtodChar("89255", -22)); CHECK_EQ(89255e-22, StrtodChar("89255", -22));
CHECK_EQ(104110013277974872254e-225,
StrtodChar("104110013277974872254", -225));
CHECK_EQ(123456789e108, StrtodChar("123456789", 108));
CHECK_EQ(123456789e109, StrtodChar("123456789", 109));
CHECK_EQ(123456789e110, StrtodChar("123456789", 110));
CHECK_EQ(123456789e111, StrtodChar("123456789", 111));
CHECK_EQ(123456789e112, StrtodChar("123456789", 112));
CHECK_EQ(123456789e113, StrtodChar("123456789", 113));
CHECK_EQ(123456789e114, StrtodChar("123456789", 114));
CHECK_EQ(123456789e115, StrtodChar("123456789", 115));
CHECK_EQ(1234567890123456789012345e108,
StrtodChar("1234567890123456789012345", 108));
CHECK_EQ(1234567890123456789012345e109,
StrtodChar("1234567890123456789012345", 109));
CHECK_EQ(1234567890123456789012345e110,
StrtodChar("1234567890123456789012345", 110));
CHECK_EQ(1234567890123456789012345e111,
StrtodChar("1234567890123456789012345", 111));
CHECK_EQ(1234567890123456789012345e112,
StrtodChar("1234567890123456789012345", 112));
CHECK_EQ(1234567890123456789012345e113,
StrtodChar("1234567890123456789012345", 113));
CHECK_EQ(1234567890123456789012345e114,
StrtodChar("1234567890123456789012345", 114));
CHECK_EQ(1234567890123456789012345e115,
StrtodChar("1234567890123456789012345", 115));
CHECK_EQ(1234567890123456789052345e108,
StrtodChar("1234567890123456789052345", 108));
CHECK_EQ(1234567890123456789052345e109,
StrtodChar("1234567890123456789052345", 109));
CHECK_EQ(1234567890123456789052345e110,
StrtodChar("1234567890123456789052345", 110));
CHECK_EQ(1234567890123456789052345e111,
StrtodChar("1234567890123456789052345", 111));
CHECK_EQ(1234567890123456789052345e112,
StrtodChar("1234567890123456789052345", 112));
CHECK_EQ(1234567890123456789052345e113,
StrtodChar("1234567890123456789052345", 113));
CHECK_EQ(1234567890123456789052345e114,
StrtodChar("1234567890123456789052345", 114));
CHECK_EQ(1234567890123456789052345e115,
StrtodChar("1234567890123456789052345", 115));
} }

44
deps/v8/test/mjsunit/bugs/bug-617.js

@ -0,0 +1,44 @@
// Copyright 2010 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// See http://code.google.com/p/v8/issues/detail?id=617 comment 5
var got_here = 0;
function make_sure_we_dont_get_here() {
got_here = 1;
}
RegExp.prototype.exec = make_sure_we_dont_get_here;
var re = /foo/;
re.exec = make_sure_we_dont_get_here;
re("foo");
assertEquals(got_here, 0);

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

Loading…
Cancel
Save