diff options
104 files changed, 6294 insertions, 4270 deletions
diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index 36ed4fcdbc..07859597bf 100644 --- a/deps/v8/ChangeLog +++ b/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 Fixed bug causing spurious out of memory exceptions diff --git a/deps/v8/SConstruct b/deps/v8/SConstruct index 05213fba7f..7107e917df 100644 --- a/deps/v8/SConstruct +++ b/deps/v8/SConstruct @@ -207,7 +207,6 @@ LIBRARY_FLAGS = { 'simulator:arm': { 'CCFLAGS': ['-m32'], 'LINKFLAGS': ['-m32'], - 'CPPDEFINES': ['USE_SIMULATOR'] }, 'arch:mips': { 'CPPDEFINES': ['V8_TARGET_ARCH_MIPS'], @@ -219,7 +218,6 @@ LIBRARY_FLAGS = { 'simulator:mips': { 'CCFLAGS': ['-m32'], 'LINKFLAGS': ['-m32'], - 'CPPDEFINES': ['USE_SIMULATOR'] }, 'arch:x64': { 'CPPDEFINES': ['V8_TARGET_ARCH_X64'], diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index ef9a41168c..89502cb915 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -467,16 +467,21 @@ class V8EXPORT HandleScope { // typedef in the ImplementationUtilities class. class V8EXPORT Data { public: - int extensions; internal::Object** next; internal::Object** limit; + int level; + inline void Initialize() { - extensions = -1; 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 // from the HandleScope being closed to the next top most HandleScope. diff --git a/deps/v8/src/accessors.cc b/deps/v8/src/accessors.cc index 3c49846601..7c21659ebc 100644 --- a/deps/v8/src/accessors.cc +++ b/deps/v8/src/accessors.cc @@ -50,7 +50,7 @@ static C* FindInPrototypeChain(Object* obj, bool* found_it) { // Entry point that never should be called. -Object* Accessors::IllegalSetter(JSObject*, Object*, void*) { +MaybeObject* Accessors::IllegalSetter(JSObject*, Object*, void*) { UNREACHABLE(); 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 // read-only properties must be silently ignored. 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. bool found_it = false; 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); // 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; if (object->IsJSValue()) value = JSValue::cast(object)->value(); 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(); 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(); 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(); 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(); 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(); 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(); 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(); 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(); 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; Handle<Script> script(Script::cast(JSValue::cast(object)->value())); 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(); 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(); if (!Script::cast(script)->eval_from_shared()->IsUndefined()) { 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; 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(); Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast( 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; JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); if (!found_it) return Heap::undefined_value(); if (!function->has_prototype()) { - Object* prototype = Heap::AllocateFunctionPrototype(function); - if (prototype->IsFailure()) return prototype; - Object* result = function->SetPrototype(prototype); - if (result->IsFailure()) return result; + Object* prototype; + { MaybeObject* maybe_prototype = Heap::AllocateFunctionPrototype(function); + if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; + } + Object* result; + { MaybeObject* maybe_result = function->SetPrototype(prototype); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return function->prototype(); } -Object* Accessors::FunctionSetPrototype(JSObject* object, - Object* value, - void*) { +MaybeObject* Accessors::FunctionSetPrototype(JSObject* object, + Object* value, + void*) { bool found_it = false; JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); if (!found_it) return Heap::undefined_value(); if (function->has_initial_map()) { // If the function has allocated the initial map // replace it with a copy containing the new prototype. - Object* new_map = function->initial_map()->CopyDropTransitions(); - if (new_map->IsFailure()) return new_map; + Object* 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)); } - Object* prototype = function->SetPrototype(value); - if (prototype->IsFailure()) return prototype; + Object* prototype; + { MaybeObject* maybe_prototype = function->SetPrototype(value); + if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; + } ASSERT(function->prototype() == value); 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; JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it); 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; JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); 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; bool found_it = false; 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; + AssertNoAllocation no_alloc; bool found_it = false; JSFunction* holder = FindInPrototypeChain<JSFunction>(object, &found_it); 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(); while (current->IsJSObject() && JSObject::cast(current)->map()->is_hidden_prototype()) { @@ -643,9 +653,9 @@ Object* Accessors::ObjectGetPrototype(Object* receiver, void*) { } -Object* Accessors::ObjectSetPrototype(JSObject* receiver, - Object* value, - void*) { +MaybeObject* Accessors::ObjectSetPrototype(JSObject* receiver, + Object* value, + void*) { const bool skip_hidden_prototypes = true; // To be consistent with other Set functions, return the value. return receiver->SetPrototype(value, skip_hidden_prototypes); diff --git a/deps/v8/src/accessors.h b/deps/v8/src/accessors.h index eeab2acfe4..96d742ef6a 100644 --- a/deps/v8/src/accessors.h +++ b/deps/v8/src/accessors.h @@ -75,40 +75,44 @@ class Accessors : public AllStatic { }; // Accessor functions called directly from the runtime system. - MUST_USE_RESULT static Object* FunctionGetPrototype(Object* object, void*); - MUST_USE_RESULT static Object* FunctionSetPrototype(JSObject* object, - Object* value, - void*); + MUST_USE_RESULT static MaybeObject* FunctionGetPrototype(Object* object, + void*); + MUST_USE_RESULT static MaybeObject* FunctionSetPrototype(JSObject* object, + Object* value, + void*); private: // Accessor functions only used through the descriptor. - static Object* FunctionGetLength(Object* object, void*); - static Object* FunctionGetName(Object* object, void*); - static Object* FunctionGetArguments(Object* object, void*); - static Object* FunctionGetCaller(Object* object, void*); - static Object* ArraySetLength(JSObject* object, Object* value, void*); - static Object* ArrayGetLength(Object* object, void*); - static Object* StringGetLength(Object* object, void*); - static Object* ScriptGetName(Object* object, void*); - static Object* ScriptGetId(Object* object, void*); - static Object* ScriptGetSource(Object* object, void*); - static Object* ScriptGetLineOffset(Object* object, void*); - static Object* ScriptGetColumnOffset(Object* object, void*); - static Object* ScriptGetData(Object* object, void*); - static Object* ScriptGetType(Object* object, void*); - static Object* ScriptGetCompilationType(Object* object, void*); - static Object* ScriptGetLineEnds(Object* object, void*); - static Object* ScriptGetContextData(Object* object, void*); - static Object* ScriptGetEvalFromScript(Object* object, void*); - static Object* ScriptGetEvalFromScriptPosition(Object* object, void*); - static Object* ScriptGetEvalFromFunctionName(Object* object, void*); - static Object* ObjectGetPrototype(Object* receiver, void*); - static Object* ObjectSetPrototype(JSObject* receiver, Object* value, void*); + static MaybeObject* FunctionGetLength(Object* object, void*); + static MaybeObject* FunctionGetName(Object* object, void*); + static MaybeObject* FunctionGetArguments(Object* object, void*); + static MaybeObject* FunctionGetCaller(Object* object, void*); + MUST_USE_RESULT static MaybeObject* ArraySetLength(JSObject* object, + Object* value, void*); + static MaybeObject* ArrayGetLength(Object* object, void*); + static MaybeObject* StringGetLength(Object* object, void*); + static MaybeObject* ScriptGetName(Object* object, void*); + static MaybeObject* ScriptGetId(Object* object, void*); + static MaybeObject* ScriptGetSource(Object* object, void*); + static MaybeObject* ScriptGetLineOffset(Object* object, void*); + static MaybeObject* ScriptGetColumnOffset(Object* object, void*); + static MaybeObject* ScriptGetData(Object* object, void*); + static MaybeObject* ScriptGetType(Object* object, void*); + static MaybeObject* ScriptGetCompilationType(Object* object, void*); + static MaybeObject* ScriptGetLineEnds(Object* object, void*); + static MaybeObject* ScriptGetContextData(Object* object, void*); + static MaybeObject* ScriptGetEvalFromScript(Object* object, void*); + static MaybeObject* ScriptGetEvalFromScriptPosition(Object* object, void*); + static MaybeObject* ScriptGetEvalFromFunctionName(Object* object, void*); + static MaybeObject* ObjectGetPrototype(Object* receiver, void*); + static MaybeObject* ObjectSetPrototype(JSObject* receiver, + Object* value, + void*); // Helper functions. 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* ReadOnlySetAccessor(JSObject*, Object* value, void*); + static MaybeObject* ReadOnlySetAccessor(JSObject*, Object* value, void*); }; } } // namespace v8::internal diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 962723d4e8..2df31df353 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -457,19 +457,37 @@ void V8::DisposeGlobal(i::Object** obj) { // --- 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"); - i::HandleScope::Enter(&previous_); + i::HandleScope::current_.level++; } HandleScope::~HandleScope() { 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() { return i::HandleScope::NumberOfHandles(); } @@ -553,7 +571,7 @@ i::Object** v8::HandleScope::RawClose(i::Object** value) { result = *value; } is_closed_ = true; - i::HandleScope::Leave(&previous_); + Leave(); if (value == NULL) { return NULL; @@ -1489,7 +1507,8 @@ static i::Handle<i::Object> CallV8HeapFunction(const char* name, i::Object** argv[], bool* has_pending_exception) { 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>(i::JSFunction::cast(object_fun)); i::Handle<i::Object> value = @@ -1605,7 +1624,8 @@ Local<StackFrame> StackTrace::GetFrame(uint32_t index) const { ENTER_V8; HandleScope scope; 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)); } @@ -2521,10 +2541,12 @@ Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain( self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup); if (lookup.IsProperty()) { PropertyAttributes attributes; - i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, - &lookup, - *key_obj, - &attributes)); + i::Object* property = + self_obj->GetProperty(*self_obj, + &lookup, + *key_obj, + &attributes)->ToObjectUnchecked(); + i::Handle<i::Object> result(property); return Utils::ToLocal(result); } 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); if (lookup.IsProperty()) { PropertyAttributes attributes; - i::Handle<i::Object> result(self_obj->GetProperty(*self_obj, - &lookup, - *key_obj, - &attributes)); + i::Object* property = + self_obj->GetProperty(*self_obj, + &lookup, + *key_obj, + &attributes)->ToObjectUnchecked(); + i::Handle<i::Object> result(property); return Utils::ToLocal(result); } return Local<Value>(); // No real property was found in prototype chain. diff --git a/deps/v8/src/api.h b/deps/v8/src/api.h index e179e35672..e36160cf4a 100644 --- a/deps/v8/src/api.h +++ b/deps/v8/src/api.h @@ -353,7 +353,7 @@ class HandleScopeImplementer { inline internal::Object** GetSpareOrNewBlock(); - inline void DeleteExtensions(int extensions); + inline void DeleteExtensions(internal::Object** prev_limit); inline void IncrementCallDepth() {call_depth_++;} inline void DecrementCallDepth() {call_depth_--;} @@ -465,25 +465,28 @@ internal::Object** HandleScopeImplementer::GetSpareOrNewBlock() { } -void HandleScopeImplementer::DeleteExtensions(int extensions) { - if (spare_ != NULL) { - DeleteArray(spare_); - spare_ = NULL; - } - for (int i = extensions; i > 1; --i) { - internal::Object** block = blocks_.RemoveLast(); +void HandleScopeImplementer::DeleteExtensions(internal::Object** prev_limit) { + while (!blocks_.is_empty()) { + internal::Object** block_start = blocks_.last(); + internal::Object** block_limit = block_start + kHandleBlockSize; #ifdef DEBUG - v8::ImplementationUtilities::ZapHandleRange(block, - &block[kHandleBlockSize]); + // NoHandleAllocation may make the prev_limit to point inside the block. + if (block_start <= prev_limit && prev_limit <= block_limit) break; +#else + if (prev_limit == block_limit) break; #endif - DeleteArray(block); - } - spare_ = blocks_.RemoveLast(); + + blocks_.RemoveLast(); #ifdef DEBUG - v8::ImplementationUtilities::ZapHandleRange( - spare_, - &spare_[kHandleBlockSize]); + v8::ImplementationUtilities::ZapHandleRange(block_start, block_limit); #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 diff --git a/deps/v8/src/arm/codegen-arm.cc b/deps/v8/src/arm/codegen-arm.cc index 684106c339..0c060f0f6f 100644 --- a/deps/v8/src/arm/codegen-arm.cc +++ b/deps/v8/src/arm/codegen-arm.cc @@ -1180,20 +1180,23 @@ void DeferredInlineSmiOperation::GenerateNonSmiInput() { void DeferredInlineSmiOperation::GenerateAnswerOutOfRange() { // 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 - // result to be converted. + // into a Smi, so we store it into a heap number. VirtualFrame::scratch0() + // 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(!reversed_); + Register untagged_result = VirtualFrame::scratch0(); + if (FLAG_debug_code) { __ Abort("Should not fall through!"); } __ bind(&answer_out_of_range_); if (((value_ & 0x1f) == 0) && (op_ == Token::SHR)) { - // >>> 0 is a special case where the result is already tagged but wrong - // because the Smi is negative. We untag it. - __ mov(tos_register_, Operand(tos_register_, ASR, kSmiTagSize)); + // >>> 0 is a special case where the untagged_result register is not set up + // yet. We untag the input to get it. + __ mov(untagged_result, Operand(tos_register_, ASR, kSmiTagSize)); } // 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. // Allocate the result heap number. - Register heap_number_map = r7; + Register heap_number_map = VirtualFrame::scratch1(); Register heap_number = r4; __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); // If the allocation fails, fall back to the GenericBinaryOpStub. __ 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)); Exit(); @@ -1474,25 +1477,29 @@ void CodeGenerator::SmiOperation(Token::Value op, switch (op) { case Token::SHL: { if (shift_value != 0) { - Register scratch = VirtualFrame::scratch0(); + Register untagged_result = VirtualFrame::scratch0(); + Register scratch = VirtualFrame::scratch1(); int adjusted_shift = shift_value - kSmiTagSize; ASSERT(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. - __ add(scratch, tos, Operand(0x40000000), SetCC); + __ add(scratch, untagged_result, Operand(0x40000000), SetCC); deferred->JumpToAnswerOutOfRange(mi); - __ mov(tos, Operand(tos, LSL, kSmiTagSize)); + __ mov(tos, Operand(untagged_result, LSL, kSmiTagSize)); } break; } case Token::SHR: { if (shift_value != 0) { - Register scratch = VirtualFrame::scratch0(); - __ mov(scratch, Operand(tos, ASR, kSmiTagSize)); // Remove tag. - __ mov(tos, Operand(scratch, LSR, shift_value)); + Register untagged_result = VirtualFrame::scratch0(); + // Remove tag. + __ mov(untagged_result, Operand(tos, ASR, kSmiTagSize)); + __ mov(untagged_result, Operand(untagged_result, LSR, shift_value)); if (shift_value == 1) { // Check that the *unsigned* result fits in a smi. // Neither of the two high-order bits can be set: @@ -1501,17 +1508,10 @@ void CodeGenerator::SmiOperation(Token::Value op, // tagging. // These two cases can only happen with shifts by 0 or 1 when // handed a valid smi. - __ tst(tos, 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); - } + __ tst(untagged_result, Operand(0xc0000000)); deferred->JumpToAnswerOutOfRange(ne); } - __ mov(tos, Operand(tos, LSL, kSmiTagSize)); + __ mov(tos, Operand(untagged_result, LSL, kSmiTagSize)); } else { __ cmp(tos, Operand(0, RelocInfo::NONE)); deferred->JumpToAnswerOutOfRange(mi); @@ -4733,6 +4733,7 @@ void CodeGenerator::GenerateMathSqrt(ZoneList<Expression*>* args) { runtime.set_entry_frame(frame_); Register heap_number_map = r6; + Register new_heap_number = r5; __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); // 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. __ vsqrt(d0, d0); - __ AllocateHeapNumberWithValue( - tos, d0, scratch1, scratch2, heap_number_map, runtime.entry_label()); + __ AllocateHeapNumberWithValue(new_heap_number, + d0, + scratch1, scratch2, + heap_number_map, + runtime.entry_label()); + __ mov(tos, Operand(new_heap_number)); done.Jump(); runtime.Bind(); diff --git a/deps/v8/src/arm/cpu-arm.cc b/deps/v8/src/arm/cpu-arm.cc index 3d3e6ae9d4..a3bf48328d 100644 --- a/deps/v8/src/arm/cpu-arm.cc +++ b/deps/v8/src/arm/cpu-arm.cc @@ -36,10 +36,7 @@ #include "cpu.h" #include "macro-assembler.h" - -#ifndef __arm__ -#include "simulator-arm.h" // for cache flushing. -#endif +#include "simulator.h" // for cache flushing. namespace v8 { namespace internal { @@ -50,7 +47,7 @@ void CPU::Setup() { 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 // building an ARM emulator based target. We should notify the simulator // that the Icache was flushed. diff --git a/deps/v8/src/arm/ic-arm.cc b/deps/v8/src/arm/ic-arm.cc index 7f83d14af9..c460f9ca6f 100644 --- a/deps/v8/src/arm/ic-arm.cc +++ b/deps/v8/src/arm/ic-arm.cc @@ -1410,9 +1410,12 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm, __ bind(&box_int); // 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); - __ 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)) { CpuFeatures::Scope scope(VFP3); diff --git a/deps/v8/src/arm/macro-assembler-arm.cc b/deps/v8/src/arm/macro-assembler-arm.cc index 0e2c49ec42..7f6090bc50 100644 --- a/deps/v8/src/arm/macro-assembler-arm.cc +++ b/deps/v8/src/arm/macro-assembler-arm.cc @@ -908,6 +908,17 @@ void MacroAssembler::AllocateInNewSpace(int object_size, Register scratch2, Label* gc_required, 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(!scratch1.is(scratch2)); @@ -959,6 +970,17 @@ void MacroAssembler::AllocateInNewSpace(Register object_size, Register scratch2, Label* gc_required, 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(!scratch1.is(scratch2)); diff --git a/deps/v8/src/arm/regexp-macro-assembler-arm.cc b/deps/v8/src/arm/regexp-macro-assembler-arm.cc index 37bb1f0aae..fbcc9f7f66 100644 --- a/deps/v8/src/arm/regexp-macro-assembler-arm.cc +++ b/deps/v8/src/arm/regexp-macro-assembler-arm.cc @@ -1030,7 +1030,7 @@ int RegExpMacroAssemblerARM::CheckStackGuardState(Address* return_address, ASSERT(*return_address <= 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 int delta = *code_handle - re_code; diff --git a/deps/v8/src/arm/simulator-arm.cc b/deps/v8/src/arm/simulator-arm.cc index 84d9d01d08..534e394af1 100644 --- a/deps/v8/src/arm/simulator-arm.cc +++ b/deps/v8/src/arm/simulator-arm.cc @@ -37,7 +37,7 @@ #include "arm/constants-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. namespace assembler { @@ -2840,6 +2840,6 @@ uintptr_t Simulator::PopAddress() { } } // namespace assembler::arm -#endif // !__arm__ || USE_SIMULATOR +#endif // USE_SIMULATOR #endif // V8_TARGET_ARCH_ARM diff --git a/deps/v8/src/arm/simulator-arm.h b/deps/v8/src/arm/simulator-arm.h index d4c8250b33..e0658fc997 100644 --- a/deps/v8/src/arm/simulator-arm.h +++ b/deps/v8/src/arm/simulator-arm.h @@ -38,12 +38,24 @@ #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. #define CALL_GENERATED_CODE(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 // generated code. Because generated code on arm uses the C stack, we // just use the C stack limit. @@ -60,38 +72,14 @@ class SimulatorStack : public v8::internal::AllStatic { static inline void UnregisterCTryCatch() { } }; +} } // namespace v8::internal -// Call the generated regexp code directly. The entry function pointer should -// 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) - - -#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)) - +#else // !defined(USE_SIMULATOR) +// Running with a simulator. #include "constants-arm.h" #include "hashmap.h" - namespace assembler { namespace arm { @@ -334,6 +322,24 @@ class Simulator { } } // 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 C-based native code. Setting the c_limit to indicate a very small // 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_ diff --git a/deps/v8/src/arm/stub-cache-arm.cc b/deps/v8/src/arm/stub-cache-arm.cc index 97f94952d7..fbad6698bd 100644 --- a/deps/v8/src/arm/stub-cache-arm.cc +++ b/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 // the property cell at compilation time if no cell exists for the // property. -static Object* GenerateCheckPropertyCell(MacroAssembler* masm, - GlobalObject* global, - String* name, - Register scratch, - Label* miss) { - Object* probe = global->EnsurePropertyCell(name); - if (probe->IsFailure()) return probe; +MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( + MacroAssembler* masm, + GlobalObject* global, + String* name, + Register scratch, + Label* miss) { + Object* probe; + { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); ASSERT(cell->value()->IsTheHole()); __ mov(scratch, Operand(Handle<Object>(cell))); @@ -894,12 +897,12 @@ Register StubCompiler::CheckPrototypes(JSObject* object, !current->IsJSGlobalObject() && !current->IsJSGlobalProxy()) { if (!name->IsSymbol()) { - Object* lookup_result = Heap::LookupSymbol(name); + MaybeObject* lookup_result = Heap::LookupSymbol(name); if (lookup_result->IsFailure()) { set_failure(Failure::cast(lookup_result)); return reg; } else { - name = String::cast(lookup_result); + name = String::cast(lookup_result->ToObjectUnchecked()); } } ASSERT(current->property_dictionary()->FindEntry(name) == @@ -974,11 +977,11 @@ Register StubCompiler::CheckPrototypes(JSObject* object, current = object; while (current != holder) { if (current->IsGlobalObject()) { - Object* cell = GenerateCheckPropertyCell(masm(), - GlobalObject::cast(current), - name, - scratch1, - miss); + MaybeObject* cell = GenerateCheckPropertyCell(masm(), + GlobalObject::cast(current), + name, + scratch1, + miss); if (cell->IsFailure()) { set_failure(Failure::cast(cell)); return reg; @@ -1281,18 +1284,21 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, } -Object* CallStubCompiler::GenerateMissBranch() { - Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); - if (obj->IsFailure()) return obj; +MaybeObject* CallStubCompiler::GenerateMissBranch() { + Object* 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); return obj; } -Object* CallStubCompiler::CompileCallField(JSObject* object, - JSObject* holder, - int index, - String* name) { +MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, + JSObject* holder, + int index, + String* name) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -1317,19 +1323,21 @@ Object* CallStubCompiler::CompileCallField(JSObject* object, // Handle call cache miss. __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(FIELD, name); } -Object* CallStubCompiler::CompileArrayPushCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -1361,19 +1369,21 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, // Handle call cache miss. __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileArrayPopCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -1405,15 +1415,17 @@ Object* CallStubCompiler::CompileArrayPopCall(Object* object, // Handle call cache miss. __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileStringCharCodeAtCall( +MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( Object* object, JSObject* holder, JSGlobalPropertyCell* cell, @@ -1477,19 +1489,22 @@ Object* CallStubCompiler::CompileStringCharCodeAtCall( __ Ret(); __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileStringCharAtCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileStringCharAtCall( + Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- r2 : function name // -- lr : return address @@ -1551,15 +1566,17 @@ Object* CallStubCompiler::CompileStringCharAtCall(Object* object, __ Ret(); __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileStringFromCharCodeCall( +MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( Object* object, JSObject* holder, JSGlobalPropertyCell* cell, @@ -1625,29 +1642,31 @@ Object* CallStubCompiler::CompileStringFromCharCodeCall( __ bind(&miss); // r2: function name. - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } -Object* CallStubCompiler::CompileMathFloorCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // TODO(872): implement this. return Heap::undefined_value(); } -Object* CallStubCompiler::CompileMathAbsCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- r2 : function name // -- lr : return address @@ -1737,19 +1756,21 @@ Object* CallStubCompiler::CompileMathAbsCall(Object* object, __ bind(&miss); // r2: function name. - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } -Object* CallStubCompiler::CompileCallConstant(Object* object, - JSObject* holder, - JSFunction* function, - String* name, - CheckType check) { +MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, + JSObject* holder, + JSFunction* function, + String* name, + CheckType check) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -1757,8 +1778,10 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, SharedFunctionInfo* function_info = function->shared(); if (function_info->HasCustomCallGenerator()) { const int id = function_info->custom_call_generator_id(); - Object* result = CompileCustomCall( + MaybeObject* maybe_result = CompileCustomCall( id, object, holder, NULL, function, name); + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // undefined means bail out to regular compiler. if (!result->IsUndefined()) { return result; @@ -1891,17 +1914,19 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, } __ bind(&miss_in_smi_check); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, - JSObject* holder, - String* name) { +MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, + JSObject* holder, + String* name) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -1941,19 +1966,21 @@ Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, // Handle call cache miss. __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(INTERCEPTOR, name); } -Object* CallStubCompiler::CompileCallGlobal(JSObject* object, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- r2 : name // -- lr : return address @@ -1962,8 +1989,10 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, SharedFunctionInfo* function_info = function->shared(); if (function_info->HasCustomCallGenerator()) { const int id = function_info->custom_call_generator_id(); - Object* result = CompileCustomCall( + MaybeObject* maybe_result = CompileCustomCall( id, object, holder, cell, function, name); + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // undefined means bail out to regular compiler. if (!result->IsUndefined()) return result; } @@ -2000,18 +2029,20 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, // Handle call cache miss. __ bind(&miss); __ IncrementCounter(&Counters::call_global_inline_miss, 1, r1, r3); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(NORMAL, name); } -Object* StoreStubCompiler::CompileStoreField(JSObject* object, - int index, - Map* transition, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, + int index, + Map* transition, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2035,9 +2066,9 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object, } -Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, - AccessorInfo* callback, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, + AccessorInfo* callback, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2083,8 +2114,8 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, } -Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2128,9 +2159,9 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, } -Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, - JSGlobalPropertyCell* cell, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, + JSGlobalPropertyCell* cell, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : receiver @@ -2162,9 +2193,9 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, } -Object* LoadStubCompiler::CompileLoadNonexistent(String* name, - JSObject* object, - JSObject* last) { +MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, + JSObject* object, + JSObject* last) { // ----------- S t a t e ------------- // -- r0 : receiver // -- lr : return address @@ -2181,11 +2212,11 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name, // If the last object in the prototype chain is a global object, // check that the global property cell is empty. if (last->IsGlobalObject()) { - Object* cell = GenerateCheckPropertyCell(masm(), - GlobalObject::cast(last), - name, - r1, - &miss); + MaybeObject* cell = GenerateCheckPropertyCell(masm(), + GlobalObject::cast(last), + name, + r1, + &miss); if (cell->IsFailure()) { miss.Unuse(); return cell; @@ -2205,10 +2236,10 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name, } -Object* LoadStubCompiler::CompileLoadField(JSObject* object, - JSObject* holder, - int index, - String* name) { +MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, + JSObject* holder, + int index, + String* name) { // ----------- S t a t e ------------- // -- r0 : receiver // -- r2 : name @@ -2225,10 +2256,10 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object, } -Object* LoadStubCompiler::CompileLoadCallback(String* name, - JSObject* object, - JSObject* holder, - AccessorInfo* callback) { +MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, + JSObject* object, + JSObject* holder, + AccessorInfo* callback) { // ----------- S t a t e ------------- // -- r0 : receiver // -- r2 : name @@ -2252,10 +2283,10 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name, } -Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, - JSObject* holder, - Object* value, - String* name) { +MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, + JSObject* holder, + Object* value, + String* name) { // ----------- S t a t e ------------- // -- r0 : receiver // -- r2 : name @@ -2272,9 +2303,9 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, } -Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, - JSObject* holder, - String* name) { +MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, + JSObject* holder, + String* name) { // ----------- S t a t e ------------- // -- r0 : receiver // -- r2 : name @@ -2302,11 +2333,11 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, } -Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - String* name, - bool is_dont_delete) { +MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + String* name, + bool is_dont_delete) { // ----------- S t a t e ------------- // -- r0 : receiver // -- r2 : name @@ -2349,10 +2380,10 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, } -Object* KeyedLoadStubCompiler::CompileLoadField(String* name, - JSObject* receiver, - JSObject* holder, - int index) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, + JSObject* receiver, + JSObject* holder, + int index) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key @@ -2372,10 +2403,11 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name, } -Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, - JSObject* receiver, - JSObject* holder, - AccessorInfo* callback) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( + String* name, + JSObject* receiver, + JSObject* holder, + AccessorInfo* callback) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key @@ -2402,10 +2434,10 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, } -Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, - JSObject* receiver, - JSObject* holder, - Object* value) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, + JSObject* receiver, + JSObject* holder, + Object* value) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key @@ -2426,9 +2458,9 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, } -Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, - JSObject* holder, - String* name) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, + JSObject* holder, + String* name) { // ----------- S t a t e ------------- // -- lr : return address // -- 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 ------------- // -- lr : return address // -- 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 ------------- // -- lr : return address // -- r0 : key @@ -2503,7 +2535,7 @@ Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { // TODO(1224671): implement the fast case. -Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { // ----------- S t a t e ------------- // -- lr : return address // -- r0 : key @@ -2515,10 +2547,10 @@ Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { } -Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, - int index, - Map* transition, - String* name) { +MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, + int index, + Map* transition, + String* name) { // ----------- S t a t e ------------- // -- r0 : value // -- r1 : key @@ -2553,7 +2585,7 @@ Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, } -Object* ConstructStubCompiler::CompileConstructStub( +MaybeObject* ConstructStubCompiler::CompileConstructStub( SharedFunctionInfo* shared) { // ----------- S t a t e ------------- // -- r0 : argc diff --git a/deps/v8/src/assembler.cc b/deps/v8/src/assembler.cc index b6efdb97e5..ce90dceacb 100644 --- a/deps/v8/src/assembler.cc +++ b/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() { return ExternalReference(Redirect(FUNCTION_ADDR(V8::Random))); } @@ -653,8 +659,8 @@ ExternalReference ExternalReference::new_space_allocation_limit_address() { } -ExternalReference ExternalReference::handle_scope_extensions_address() { - return ExternalReference(HandleScope::current_extensions_address()); +ExternalReference ExternalReference::handle_scope_level_address() { + return ExternalReference(HandleScope::current_level_address()); } diff --git a/deps/v8/src/assembler.h b/deps/v8/src/assembler.h index d28bf43709..66811777fa 100644 --- a/deps/v8/src/assembler.h +++ b/deps/v8/src/assembler.h @@ -482,6 +482,7 @@ class ExternalReference BASE_EMBEDDED { static ExternalReference fill_heap_number_with_random_function(); static ExternalReference random_uint32_function(); static ExternalReference transcendental_cache_array_address(); + static ExternalReference delete_handle_scope_extensions(); // Static data in the keyed lookup cache. static ExternalReference keyed_lookup_cache_keys(); @@ -519,9 +520,9 @@ class ExternalReference BASE_EMBEDDED { static ExternalReference double_fp_operation(Token::Value operation); static ExternalReference compare_doubles(); - static ExternalReference handle_scope_extensions_address(); static ExternalReference handle_scope_next_address(); static ExternalReference handle_scope_limit_address(); + static ExternalReference handle_scope_level_address(); static ExternalReference scheduled_exception_address(); diff --git a/deps/v8/src/bootstrapper.cc b/deps/v8/src/bootstrapper.cc index d7491e1f1f..0e49966bbd 100644 --- a/deps/v8/src/bootstrapper.cc +++ b/deps/v8/src/bootstrapper.cc @@ -1009,11 +1009,10 @@ bool Genesis::CompileScriptCached(Vector<const char> name, } -#define INSTALL_NATIVE(Type, name, var) \ - Handle<String> var##_name = Factory::LookupAsciiSymbol(name); \ - global_context()->set_##var(Type::cast(global_context()-> \ - builtins()-> \ - GetProperty(*var##_name))); +#define INSTALL_NATIVE(Type, name, var) \ + Handle<String> var##_name = Factory::LookupAsciiSymbol(name); \ + global_context()->set_##var(Type::cast( \ + global_context()->builtins()->GetPropertyNoExceptionThrown(*var##_name))); void Genesis::InstallNativeFunctions() { HandleScope scope; @@ -1369,7 +1368,8 @@ static void InstallCustomCallGenerator(Handle<JSObject> holder, const char* function_name, int id) { 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)); } @@ -1584,8 +1584,9 @@ bool Genesis::InstallJSBuiltins(Handle<JSBuiltinsObject> builtins) { for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) { Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i); Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id)); + Object* function_object = builtins->GetPropertyNoExceptionThrown(*name); Handle<JSFunction> function - = Handle<JSFunction>(JSFunction::cast(builtins->GetProperty(*name))); + = Handle<JSFunction>(JSFunction::cast(function_object)); builtins->set_javascript_builtin(id, *function); Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(function->shared()); diff --git a/deps/v8/src/builtins.cc b/deps/v8/src/builtins.cc index b4f4a0611a..52d5530cec 100644 --- a/deps/v8/src/builtins.cc +++ b/deps/v8/src/builtins.cc @@ -121,18 +121,21 @@ BUILTIN_LIST_C(DEF_ARG_TYPE) #ifdef DEBUG -#define BUILTIN(name) \ - static Object* Builtin_Impl_##name(name##ArgumentsType args); \ - static Object* Builtin_##name(name##ArgumentsType args) { \ - args.Verify(); \ - return Builtin_Impl_##name(args); \ - } \ - static Object* Builtin_Impl_##name(name##ArgumentsType args) +#define BUILTIN(name) \ + MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ + name##ArgumentsType args); \ + MUST_USE_RESULT static MaybeObject* Builtin_##name( \ + name##ArgumentsType args) { \ + args.Verify(); \ + return Builtin_Impl_##name(args); \ + } \ + MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \ + name##ArgumentsType args) #else // For release mode. -#define BUILTIN(name) \ - static Object* Builtin_##name(name##ArgumentsType args) +#define BUILTIN(name) \ + static MaybeObject* Builtin_##name(name##ArgumentsType args) #endif @@ -189,8 +192,10 @@ BUILTIN(ArrayCodeGeneric) { // Allocate the JS Array JSFunction* constructor = Top::context()->global_context()->array_function(); - Object* obj = Heap::AllocateJSObject(constructor); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateJSObject(constructor); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } array = JSArray::cast(obj); } @@ -204,15 +209,18 @@ BUILTIN(ArrayCodeGeneric) { if (obj->IsSmi()) { int len = Smi::cast(obj)->value(); if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) { - Object* obj = Heap::AllocateFixedArrayWithHoles(len); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } array->SetContent(FixedArray::cast(obj)); return array; } } // Take the argument as the length. - obj = array->Initialize(0); - if (obj->IsFailure()) return obj; + { MaybeObject* maybe_obj = array->Initialize(0); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return array->SetElementsLength(args[1]); } @@ -224,8 +232,10 @@ BUILTIN(ArrayCodeGeneric) { // Take the arguments as elements. int number_of_elements = args.length() - 1; Smi* len = Smi::FromInt(number_of_elements); - Object* obj = Heap::AllocateFixedArrayWithHoles(len->value()); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(len->value()); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } AssertNoAllocation no_gc; 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 = Top::context()->global_context()->array_function(); - Object* result = Heap::AllocateJSObject(array_function); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::AllocateJSObject(array_function); + if (!maybe_result->ToObject(&result)) return maybe_result; + } return result; } -MUST_USE_RESULT static Object* AllocateEmptyJSArray() { - Object* result = AllocateJSArray(); - if (result->IsFailure()) return result; +MUST_USE_RESULT static MaybeObject* AllocateEmptyJSArray() { + Object* result; + { MaybeObject* maybe_result = AllocateJSArray(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } JSArray* result_array = JSArray::cast(result); result_array->set_length(Smi::FromInt(0)); 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; JSArray* array = JSArray::cast(receiver); HeapObject* elms = HeapObject::cast(array->elements()); @@ -381,8 +397,9 @@ static inline bool IsJSArrayFastElementMovingAllowed(JSArray* receiver) { } -static Object* CallJsBuiltin(const char* name, - BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { +MUST_USE_RESULT static MaybeObject* CallJsBuiltin( + const char* name, + BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { HandleScope handleScope; Handle<Object> js_builtin = @@ -408,9 +425,12 @@ static Object* CallJsBuiltin(const char* name, BUILTIN(ArrayPush) { Object* receiver = *args.receiver(); - Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); - if (elms_obj == NULL) return CallJsBuiltin("ArrayPush", args); - if (elms_obj->IsFailure()) return elms_obj; + Object* elms_obj; + { MaybeObject* maybe_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); JSArray* array = JSArray::cast(receiver); @@ -428,8 +448,10 @@ BUILTIN(ArrayPush) { if (new_length > elms->length()) { // New backing storage is needed. int capacity = new_length + (new_length >> 1) + 16; - Object* obj = Heap::AllocateUninitializedFixedArray(capacity); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray* new_elms = FixedArray::cast(obj); AssertNoAllocation no_gc; @@ -457,9 +479,12 @@ BUILTIN(ArrayPush) { BUILTIN(ArrayPop) { Object* receiver = *args.receiver(); - Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); - if (elms_obj == NULL) return CallJsBuiltin("ArrayPop", args); - if (elms_obj->IsFailure()) return elms_obj; + Object* elms_obj; + { MaybeObject* maybe_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); JSArray* array = JSArray::cast(receiver); @@ -467,7 +492,7 @@ BUILTIN(ArrayPop) { if (len == 0) return Heap::undefined_value(); // Get top element - Object* top = elms->get(len - 1); + MaybeObject* top = elms->get(len - 1); // Set the length. array->set_length(Smi::FromInt(len - 1)); @@ -486,8 +511,11 @@ BUILTIN(ArrayPop) { BUILTIN(ArrayShift) { Object* receiver = *args.receiver(); - Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); - if (elms_obj->IsFailure()) return elms_obj; + Object* elms_obj; + { MaybeObject* maybe_elms_obj = + EnsureJSArrayWithWritableFastElements(receiver); + if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; + } if (elms_obj == NULL || !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { return CallJsBuiltin("ArrayShift", args); @@ -525,8 +553,11 @@ BUILTIN(ArrayShift) { BUILTIN(ArrayUnshift) { Object* receiver = *args.receiver(); - Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); - if (elms_obj->IsFailure()) return elms_obj; + Object* elms_obj; + { MaybeObject* maybe_elms_obj = + EnsureJSArrayWithWritableFastElements(receiver); + if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; + } if (elms_obj == NULL || !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { return CallJsBuiltin("ArrayUnshift", args); @@ -545,8 +576,10 @@ BUILTIN(ArrayUnshift) { if (new_length > elms->length()) { // New backing storage is needed. int capacity = new_length + (new_length >> 1) + 16; - Object* obj = Heap::AllocateUninitializedFixedArray(capacity); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(capacity); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray* new_elms = FixedArray::cast(obj); AssertNoAllocation no_gc; @@ -577,8 +610,11 @@ BUILTIN(ArrayUnshift) { BUILTIN(ArraySlice) { Object* receiver = *args.receiver(); - Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); - if (elms_obj->IsFailure()) return elms_obj; + Object* elms_obj; + { MaybeObject* maybe_elms_obj = + EnsureJSArrayWithWritableFastElements(receiver); + if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; + } if (elms_obj == NULL || !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { return CallJsBuiltin("ArraySlice", args); @@ -627,12 +663,16 @@ BUILTIN(ArraySlice) { return AllocateEmptyJSArray(); } - Object* result = AllocateJSArray(); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateJSArray(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } JSArray* result_array = JSArray::cast(result); - result = Heap::AllocateUninitializedFixedArray(result_len); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = + Heap::AllocateUninitializedFixedArray(result_len); + if (!maybe_result->ToObject(&result)) return maybe_result; + } FixedArray* result_elms = FixedArray::cast(result); AssertNoAllocation no_gc; @@ -649,8 +689,11 @@ BUILTIN(ArraySlice) { BUILTIN(ArraySplice) { Object* receiver = *args.receiver(); - Object* elms_obj = EnsureJSArrayWithWritableFastElements(receiver); - if (elms_obj->IsFailure()) return elms_obj; + Object* elms_obj; + { MaybeObject* maybe_elms_obj = + EnsureJSArrayWithWritableFastElements(receiver); + if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; + } if (elms_obj == NULL || !IsJSArrayFastElementMovingAllowed(JSArray::cast(receiver))) { return CallJsBuiltin("ArraySplice", args); @@ -695,17 +738,23 @@ BUILTIN(ArraySplice) { JSArray* result_array = NULL; if (actual_delete_count == 0) { - Object* result = AllocateEmptyJSArray(); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateEmptyJSArray(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } result_array = JSArray::cast(result); } else { // Allocate result array. - Object* result = AllocateJSArray(); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateJSArray(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } result_array = JSArray::cast(result); - result = Heap::AllocateUninitializedFixedArray(actual_delete_count); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = + Heap::AllocateUninitializedFixedArray(actual_delete_count); + if (!maybe_result->ToObject(&result)) return maybe_result; + } FixedArray* result_elms = FixedArray::cast(result); AssertNoAllocation no_gc; @@ -758,8 +807,11 @@ BUILTIN(ArraySplice) { if (new_length > elms->length()) { // New backing storage is needed. int capacity = new_length + (new_length >> 1) + 16; - Object* obj = Heap::AllocateUninitializedFixedArray(capacity); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + Heap::AllocateUninitializedFixedArray(capacity); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray* new_elms = FixedArray::cast(obj); AssertNoAllocation no_gc; @@ -838,12 +890,16 @@ BUILTIN(ArrayConcat) { } // Allocate result. - Object* result = AllocateJSArray(); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateJSArray(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } JSArray* result_array = JSArray::cast(result); - result = Heap::AllocateUninitializedFixedArray(result_len); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = + Heap::AllocateUninitializedFixedArray(result_len); + if (!maybe_result->ToObject(&result)) return maybe_result; + } FixedArray* result_elms = FixedArray::cast(result); // Copy data. @@ -921,7 +977,7 @@ static inline Object* TypeCheck(int argc, template <bool is_construct> -static Object* HandleApiCallHelper( +MUST_USE_RESULT static MaybeObject* HandleApiCallHelper( BuiltinArguments<NEEDS_CALLED_FUNCTION> args) { ASSERT(is_construct == CalledAsConstructor()); @@ -1079,7 +1135,7 @@ BUILTIN(FastHandleApiCall) { // 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 // a function (without new). -static Object* HandleApiCallAsFunctionOrConstructor( +MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor( bool is_construct_call, BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { // 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; masm.GetCode(&desc); Code::Flags flags = functions[i].flags; - Object* code; + Object* code = 0; { // During startup it's OK to always allocate and defer GC to later. // This simplifies things because we don't need to retry. AlwaysAllocateScope __scope__; - code = Heap::CreateCode(desc, flags, masm.CodeObject()); - if (code->IsFailure()) { - v8::internal::V8::FatalProcessOutOfMemory("CreateCode"); + { MaybeObject* maybe_code = + Heap::CreateCode(desc, flags, masm.CodeObject()); + if (!maybe_code->ToObject(&code)) { + v8::internal::V8::FatalProcessOutOfMemory("CreateCode"); + } } } // Log the event and add the code to the builtins array. @@ -1536,5 +1594,4 @@ const char* Builtins::Lookup(byte* pc) { return NULL; } - } } // namespace v8::internal diff --git a/deps/v8/src/cached-powers.cc b/deps/v8/src/cached-powers.cc index 8f822862bd..43dbc7855e 100644 --- a/deps/v8/src/cached-powers.cc +++ b/deps/v8/src/cached-powers.cc @@ -42,6 +42,11 @@ struct CachedPower { }; 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(0xab70fe17, c79ac6ca), -1060, -300}, {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 kCachedPowersOffset = -kCachedPowers[0].decimal_exponent; 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; +const int PowersOfTenCache::kMinDecimalExponent = + kCachedPowers[0].decimal_exponent; +const int PowersOfTenCache::kMaxDecimalExponent = + kCachedPowers[kCachedPowersLength - 1].decimal_exponent; -void GetCachedPowerForBinaryExponentRange(int min_exponent, - int max_exponent, - DiyFp* power, - int* decimal_exponent) { - int kQ = DiyFp::kSignificandSize; - double k = ceiling((min_exponent + kQ - 1) * kD_1_LOG2_10); - int foo = kCachedPowersOffset; - int index = - (foo + static_cast<int>(k) - 1) / kCachedPowersDecimalDistance + 1; - ASSERT(0 <= index && index < kCachedPowersLength); - CachedPower cached_power = kCachedPowers[index]; - ASSERT(min_exponent <= cached_power.binary_exponent); - ASSERT(cached_power.binary_exponent <= max_exponent); - *decimal_exponent = cached_power.decimal_exponent; - *power = DiyFp(cached_power.significand, cached_power.binary_exponent); +void PowersOfTenCache::GetCachedPowerForBinaryExponentRange( + int min_exponent, + int max_exponent, + DiyFp* power, + int* decimal_exponent) { + int kQ = DiyFp::kSignificandSize; + double k = ceiling((min_exponent + kQ - 1) * kD_1_LOG2_10); + int foo = kCachedPowersOffset; + int index = + (foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1; + ASSERT(0 <= index && index < kCachedPowersLength); + CachedPower cached_power = kCachedPowers[index]; + ASSERT(min_exponent <= cached_power.binary_exponent); + ASSERT(cached_power.binary_exponent <= max_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 diff --git a/deps/v8/src/cached-powers.h b/deps/v8/src/cached-powers.h index 0c78343170..2ae56196a3 100644 --- a/deps/v8/src/cached-powers.h +++ b/deps/v8/src/cached-powers.h @@ -33,10 +33,32 @@ namespace v8 { namespace internal { -void GetCachedPowerForBinaryExponentRange(int min_exponent, - int max_exponent, - DiyFp* power, - int* decimal_exponent); +class PowersOfTenCache { + public: + + // 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 diff --git a/deps/v8/src/code-stubs.cc b/deps/v8/src/code-stubs.cc index 78062b4036..787ec2a7a1 100644 --- a/deps/v8/src/code-stubs.cc +++ b/deps/v8/src/code-stubs.cc @@ -123,7 +123,7 @@ Handle<Code> CodeStub::GetCode() { } -Object* CodeStub::TryGetCode() { +MaybeObject* CodeStub::TryGetCode() { Code* code; if (!FindCodeInCache(&code)) { // Generate the new code. @@ -139,8 +139,11 @@ Object* CodeStub::TryGetCode() { static_cast<Code::Kind>(GetCodeKind()), InLoop(), GetICState()); - Object* new_object = Heap::CreateCode(desc, flags, masm.CodeObject()); - if (new_object->IsFailure()) return new_object; + Object* 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); RecordCodeGeneration(code, &masm); @@ -148,8 +151,9 @@ Object* CodeStub::TryGetCode() { SetCustomCache(code); } else { // Try to update the code cache but do not fail if unable. - new_object = Heap::code_stubs()->AtNumberPut(GetKey(), code); - if (!new_object->IsFailure()) { + MaybeObject* maybe_new_object = + Heap::code_stubs()->AtNumberPut(GetKey(), code); + if (maybe_new_object->ToObject(&new_object)) { Heap::public_set_code_stubs(NumberDictionary::cast(new_object)); } } diff --git a/deps/v8/src/code-stubs.h b/deps/v8/src/code-stubs.h index 912d43d4af..c0a8d3063c 100644 --- a/deps/v8/src/code-stubs.h +++ b/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 // generate the code if not already generated and instead return a // retry after GC Failure object. - Object* TryGetCode(); + MUST_USE_RESULT MaybeObject* TryGetCode(); static Major MajorKeyFromKey(uint32_t key) { return static_cast<Major>(MajorKeyBits::decode(key)); @@ -536,7 +536,7 @@ class ApiGetterEntryStub : public CodeStub { virtual void SetCustomCache(Code* value); static const int kStackSpace = 5; - static const int kArgc = 4; + static const int kArgc = 2; private: Handle<AccessorInfo> info() { return info_; } ApiFunction* fun() { return fun_; } diff --git a/deps/v8/src/compilation-cache.cc b/deps/v8/src/compilation-cache.cc index b0449c47f4..6e4e4bff5a 100644 --- a/deps/v8/src/compilation-cache.cc +++ b/deps/v8/src/compilation-cache.cc @@ -110,7 +110,7 @@ class CompilationCacheScript : public CompilationSubCache { void Put(Handle<String> source, Handle<SharedFunctionInfo> function_info); private: - MUST_USE_RESULT Object* TryTablePut( + MUST_USE_RESULT MaybeObject* TryTablePut( Handle<String> source, Handle<SharedFunctionInfo> function_info); // Note: Returns a new hash table if operation results in expansion. @@ -140,7 +140,7 @@ class CompilationCacheEval: public CompilationSubCache { Handle<SharedFunctionInfo> function_info); private: - MUST_USE_RESULT Object* TryTablePut( + MUST_USE_RESULT MaybeObject* TryTablePut( Handle<String> source, Handle<Context> context, Handle<SharedFunctionInfo> function_info); @@ -168,9 +168,9 @@ class CompilationCacheRegExp: public CompilationSubCache { JSRegExp::Flags flags, Handle<FixedArray> data); private: - MUST_USE_RESULT Object* TryTablePut(Handle<String> source, - JSRegExp::Flags flags, - Handle<FixedArray> data); + MUST_USE_RESULT MaybeObject* TryTablePut(Handle<String> source, + JSRegExp::Flags flags, + Handle<FixedArray> data); // Note: Returns a new hash table if operation results in expansion. 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<SharedFunctionInfo> function_info) { Handle<CompilationCacheTable> table = GetFirstTable(); @@ -386,7 +386,7 @@ Handle<SharedFunctionInfo> CompilationCacheEval::Lookup( } -Object* CompilationCacheEval::TryTablePut( +MaybeObject* CompilationCacheEval::TryTablePut( Handle<String> source, Handle<Context> context, Handle<SharedFunctionInfo> function_info) { @@ -442,7 +442,7 @@ Handle<FixedArray> CompilationCacheRegExp::Lookup(Handle<String> source, } -Object* CompilationCacheRegExp::TryTablePut( +MaybeObject* CompilationCacheRegExp::TryTablePut( Handle<String> source, JSRegExp::Flags flags, Handle<FixedArray> data) { diff --git a/deps/v8/src/debug.cc b/deps/v8/src/debug.cc index 53773acaf5..5c6ddbe355 100644 --- a/deps/v8/src/debug.cc +++ b/deps/v8/src/debug.cc @@ -1038,7 +1038,7 @@ bool Debug::CheckBreakPoint(Handle<Object> break_point_object) { Factory::LookupAsciiSymbol("IsBreakPointTriggered"); Handle<JSFunction> check_break_point = Handle<JSFunction>(JSFunction::cast( - debug_context()->global()->GetProperty( + debug_context()->global()->GetPropertyNoExceptionThrown( *is_break_point_triggered_symbol))); // Get the break id as an object. @@ -1847,7 +1847,8 @@ void Debug::ClearMirrorCache() { // Clear the mirror cache. Handle<String> function_name = Factory::LookupSymbol(CStrVector("ClearMirrorCache")); - Handle<Object> fun(Top::global()->GetProperty(*function_name)); + Handle<Object> fun(Top::global()->GetPropertyNoExceptionThrown( + *function_name)); ASSERT(fun->IsJSFunction()); bool caught_exception; Handle<Object> js_object = Execution::TryCall( @@ -1954,7 +1955,8 @@ Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name, // Create the execution state object. 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()); if (!constructor->IsJSFunction()) { *caught_exception = true; @@ -2181,8 +2183,8 @@ void Debugger::OnAfterCompile(Handle<Script> script, Handle<String> update_script_break_points_symbol = Factory::LookupAsciiSymbol("UpdateScriptBreakPoints"); Handle<Object> update_script_break_points = - Handle<Object>(Debug::debug_context()->global()->GetProperty( - *update_script_break_points_symbol)); + Handle<Object>(Debug::debug_context()->global()-> + GetPropertyNoExceptionThrown(*update_script_break_points_symbol)); if (!update_script_break_points->IsJSFunction()) { return; } diff --git a/deps/v8/src/double.h b/deps/v8/src/double.h index 65f8c9444b..e805173e07 100644 --- a/deps/v8/src/double.h +++ b/deps/v8/src/double.h @@ -45,10 +45,14 @@ class Double { static const uint64_t kSignificandMask = V8_2PART_UINT64_C(0x000FFFFF, FFFFFFFF); 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) {} explicit Double(double d) : d64_(double_to_uint64(d)) {} explicit Double(uint64_t d64) : d64_(d64) {} + explicit Double(DiyFp diy_fp) + : d64_(DiyFpToUint64(diy_fp)) {} DiyFp AsDiyFp() const { ASSERT(!IsSpecial()); @@ -67,9 +71,9 @@ class Double { f <<= 1; e--; } - // Do the final shifts in one go. Don't forget the hidden bit (the '-1'). - f <<= DiyFp::kSignificandSize - kSignificandSize - 1; - e -= DiyFp::kSignificandSize - kSignificandSize - 1; + // Do the final shifts in one go. + f <<= DiyFp::kSignificandSize - kSignificandSize; + e -= DiyFp::kSignificandSize - kSignificandSize; return DiyFp(f, e); } @@ -82,7 +86,8 @@ class Double { if (IsDenormal()) return kDenormalExponent; 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; } @@ -156,12 +161,54 @@ class Double { 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: - static const int kSignificandSize = 52; // Excludes the hidden bit. - static const int kExponentBias = 0x3FF + kSignificandSize; + static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; 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 diff --git a/deps/v8/src/execution.cc b/deps/v8/src/execution.cc index 6862324747..3bbac0fa07 100644 --- a/deps/v8/src/execution.cc +++ b/deps/v8/src/execution.cc @@ -50,7 +50,7 @@ static Handle<Object> Invoke(bool construct, VMState state(JS); // Placeholder for return value. - Object* value = reinterpret_cast<Object*>(kZapValue); + MaybeObject* value = reinterpret_cast<Object*>(kZapValue); typedef Object* (*JSEntryFunction)( byte* entry, @@ -109,7 +109,7 @@ static Handle<Object> Invoke(bool construct, 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. if (object->IsJSRegExp()) { 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 @@ -517,8 +527,8 @@ Handle<JSFunction> Execution::InstantiateFunction( Handle<FunctionTemplateInfo> data, bool* exc) { // Fast case: see if the function has already been instantiated int serial_number = Smi::cast(data->serial_number())->value(); - Object* elm = - Top::global_context()->function_cache()->GetElement(serial_number); + Object* elm = Top::global_context()->function_cache()-> + GetElementNoExceptionThrown(serial_number); if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm)); // The function has not yet been instantiated in this context; do it. Object** args[1] = { Handle<Object>::cast(data).location() }; @@ -671,7 +681,7 @@ void Execution::ProcessDebugMesssages(bool debug_command_only) { #endif -Object* Execution::HandleStackGuardInterrupt() { +MaybeObject* Execution::HandleStackGuardInterrupt() { #ifdef ENABLE_DEBUGGER_SUPPORT if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) { DebugBreakHelper(); diff --git a/deps/v8/src/execution.h b/deps/v8/src/execution.h index 15d85ef40d..5547803be7 100644 --- a/deps/v8/src/execution.h +++ b/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 // 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 // object. Used for support calling objects as functions. diff --git a/deps/v8/src/factory.cc b/deps/v8/src/factory.cc index 7c8c934044..a05ff6cc7e 100644 --- a/deps/v8/src/factory.cc +++ b/deps/v8/src/factory.cc @@ -431,7 +431,8 @@ Handle<Object> Factory::NewError(const char* maker, const char* type, Handle<JSArray> args) { 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 // constructor may not have been defined. Bail out. if (!fun_obj->IsJSFunction()) @@ -464,7 +465,7 @@ Handle<Object> Factory::NewError(const char* constructor, Handle<JSFunction> fun = Handle<JSFunction>( JSFunction::cast( - Top::builtins()->GetProperty(*constr))); + Top::builtins()->GetPropertyNoExceptionThrown(*constr))); Object** argv[1] = { Handle<Object>::cast(message).location() }; // 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, - String* key, - Object* value, - PropertyAttributes attributes) { +MUST_USE_RESULT static inline MaybeObject* DoCopyInsert( + DescriptorArray* array, + String* key, + Object* value, + PropertyAttributes attributes) { CallbacksDescriptor desc(key, value, attributes); - Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS); + MaybeObject* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS); return obj; } @@ -921,11 +923,15 @@ Handle<MapCache> Factory::NewMapCache(int at_least_space_for) { } -static Object* UpdateMapCacheWith(Context* context, - FixedArray* keys, - Map* map) { - Object* result = MapCache::cast(context->map_cache())->Put(keys, map); - if (!result->IsFailure()) context->set_map_cache(MapCache::cast(result)); +MUST_USE_RESULT static MaybeObject* UpdateMapCacheWith(Context* context, + FixedArray* keys, + Map* map) { + Object* 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; } diff --git a/deps/v8/src/fast-dtoa.cc b/deps/v8/src/fast-dtoa.cc index ce825f9db0..c7f6aa1756 100644 --- a/deps/v8/src/fast-dtoa.cc +++ b/deps/v8/src/fast-dtoa.cc @@ -613,9 +613,10 @@ static bool Grisu3(double v, kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize); int ten_mk_maximal_binary_exponent = kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize); - GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent, - ten_mk_maximal_binary_exponent, - &ten_mk, &mk); + PowersOfTenCache::GetCachedPowerForBinaryExponentRange( + ten_mk_minimal_binary_exponent, + ten_mk_maximal_binary_exponent, + &ten_mk, &mk); ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + DiyFp::kSignificandSize) && (kMaximalTargetExponent >= w.e() + ten_mk.e() + @@ -671,9 +672,10 @@ static bool Grisu3Counted(double v, kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize); int ten_mk_maximal_binary_exponent = kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize); - GetCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent, - ten_mk_maximal_binary_exponent, - &ten_mk, &mk); + PowersOfTenCache::GetCachedPowerForBinaryExponentRange( + ten_mk_minimal_binary_exponent, + ten_mk_maximal_binary_exponent, + &ten_mk, &mk); ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + DiyFp::kSignificandSize) && (kMaximalTargetExponent >= w.e() + ten_mk.e() + diff --git a/deps/v8/src/global-handles.cc b/deps/v8/src/global-handles.cc index 0207322755..9ede908528 100644 --- a/deps/v8/src/global-handles.cc +++ b/deps/v8/src/global-handles.cc @@ -372,14 +372,13 @@ void GlobalHandles::IdentifyWeakHandles(WeakSlotCallback f) { int post_gc_processing_count = 0; -bool GlobalHandles::PostGarbageCollectionProcessing() { +void GlobalHandles::PostGarbageCollectionProcessing() { // Process weak global handle callbacks. This must be done after the // GC is completely done, because the callbacks may invoke arbitrary // API functions. // At the same time deallocate all DESTROYED nodes. ASSERT(Heap::gc_state() == Heap::NOT_IN_GC); const int initial_post_gc_processing_count = ++post_gc_processing_count; - bool weak_callback_invoked = false; Node** p = &head_; while (*p != NULL) { if ((*p)->PostGarbageCollectionProcessing()) { @@ -390,7 +389,6 @@ bool GlobalHandles::PostGarbageCollectionProcessing() { // restart the processing). break; } - weak_callback_invoked = true; } if ((*p)->state_ == Node::DESTROYED) { // Delete the link. @@ -409,7 +407,6 @@ bool GlobalHandles::PostGarbageCollectionProcessing() { if (first_deallocated()) { first_deallocated()->set_next(head()); } - return weak_callback_invoked; } diff --git a/deps/v8/src/global-handles.h b/deps/v8/src/global-handles.h index c4c59fdf4d..659f86eca7 100644 --- a/deps/v8/src/global-handles.h +++ b/deps/v8/src/global-handles.h @@ -95,9 +95,8 @@ class GlobalHandles : public AllStatic { // Tells whether global handle is weak. static bool IsWeak(Object** location); - // Process pending weak handles. Returns true if any weak handle - // callback has been invoked. - static bool PostGarbageCollectionProcessing(); + // Process pending weak handles. + static void PostGarbageCollectionProcessing(); // Iterates over all strong handles. static void IterateStrongRoots(ObjectVisitor* v); diff --git a/deps/v8/src/globals.h b/deps/v8/src/globals.h index fbc749da85..c218f80dc1 100644 --- a/deps/v8/src/globals.h +++ b/deps/v8/src/globals.h @@ -93,6 +93,18 @@ namespace internal { #error Target architecture mips is only supported on mips and ia32 host #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. #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_IA32) #define V8_TARGET_CAN_READ_UNALIGNED 1 @@ -189,9 +201,11 @@ const int kIntptrSize = sizeof(intptr_t); // NOLINT #if V8_HOST_ARCH_64_BIT const int kPointerSizeLog2 = 3; const intptr_t kIntptrSignBit = V8_INT64_C(0x8000000000000000); +const uintptr_t kUintptrAllBitsSet = V8_UINT64_C(0xFFFFFFFFFFFFFFFF); #else const int kPointerSizeLog2 = 2; const intptr_t kIntptrSignBit = 0x80000000; +const uintptr_t kUintptrAllBitsSet = 0xFFFFFFFFu; #endif // Mask for the sign bit in a smi. @@ -324,6 +338,7 @@ class MarkCompactCollector; class NewSpace; class NodeVisitor; class Object; +class MaybeObject; class OldSpace; class Property; class Proxy; @@ -542,8 +557,8 @@ union IeeeDoubleBigEndianArchType { // AccessorCallback struct AccessorDescriptor { - Object* (*getter)(Object* object, void* data); - Object* (*setter)(JSObject* object, Object* value, void* data); + MaybeObject* (*getter)(Object* object, void* data); + MaybeObject* (*setter)(JSObject* object, Object* value, void* data); void* data; }; diff --git a/deps/v8/src/handles-inl.h b/deps/v8/src/handles-inl.h index bf19f5f864..b31351256e 100644 --- a/deps/v8/src/handles-inl.h +++ b/deps/v8/src/handles-inl.h @@ -55,18 +55,22 @@ inline T* Handle<T>::operator*() const { inline NoHandleAllocation::NoHandleAllocation() { v8::ImplementationUtilities::HandleScopeData* current = v8::ImplementationUtilities::CurrentHandleScope(); - extensions_ = current->extensions; // Shrink the current handle scope to make it impossible to do // handle allocations without an explicit handle scope. current->limit = current->next; - current->extensions = -1; + + level_ = current->level; + current->level = 0; } inline NoHandleAllocation::~NoHandleAllocation() { // Restore state in current handle scope to re-enable handle // allocations. - v8::ImplementationUtilities::CurrentHandleScope()->extensions = extensions_; + v8::ImplementationUtilities::HandleScopeData* current = + v8::ImplementationUtilities::CurrentHandleScope(); + ASSERT_EQ(0, current->level); + current->level = level_; } #endif diff --git a/deps/v8/src/handles.cc b/deps/v8/src/handles.cc index 8fe29bb7a0..7a46bc3ea2 100644 --- a/deps/v8/src/handles.cc +++ b/deps/v8/src/handles.cc @@ -44,7 +44,7 @@ namespace internal { v8::ImplementationUtilities::HandleScopeData HandleScope::current_ = - { -1, NULL, NULL }; + { NULL, NULL, 0 }; int HandleScope::NumberOfHandles() { @@ -61,7 +61,7 @@ Object** HandleScope::Extend() { ASSERT(result == current_.limit); // Make sure there's at least one scope on the stack and that the // top of the scope stack isn't a barrier. - if (current_.extensions < 0) { + if (current_.level == 0) { Utils::ReportApiFailure("v8::HandleScope::CreateHandle()", "Cannot create a handle without a HandleScope"); return NULL; @@ -73,6 +73,7 @@ Object** HandleScope::Extend() { Object** limit = &impl->blocks()->last()[kHandleBlockSize]; if (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 // extension as part of the current scope. impl->blocks()->Add(result); - current_.extensions++; current_.limit = &result[kHandleBlockSize]; } @@ -93,21 +93,20 @@ Object** HandleScope::Extend() { void HandleScope::DeleteExtensions() { - ASSERT(current_.extensions != 0); - HandleScopeImplementer::instance()->DeleteExtensions(current_.extensions); + HandleScopeImplementer::instance()->DeleteExtensions(current_.limit); } void HandleScope::ZapRange(Object** start, Object** end) { - if (start == NULL) return; - for (Object** p = start; p < end; p++) { + ASSERT(end - start <= kHandleBlockSize); + for (Object** p = start; p != end; p++) { *reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue; } } -Address HandleScope::current_extensions_address() { - return reinterpret_cast<Address>(¤t_.extensions); +Address HandleScope::current_level_address() { + return reinterpret_cast<Address>(¤t_.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) { CALL_HEAP_FUNCTION_VOID(string->TryFlatten()); } diff --git a/deps/v8/src/handles.h b/deps/v8/src/handles.h index 69170ff203..2e18ab347d 100644 --- a/deps/v8/src/handles.h +++ b/deps/v8/src/handles.h @@ -107,12 +107,20 @@ class Handle { // for which the handle scope has been deleted is undefined. class HandleScope { public: - HandleScope() : previous_(current_) { - current_.extensions = 0; + HandleScope() : prev_next_(current_.next), prev_limit_(current_.limit) { + current_.level++; } ~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. @@ -136,9 +144,9 @@ class HandleScope { // Deallocates any extensions used by the current scope. static void DeleteExtensions(); - static Address current_extensions_address(); static Address current_next_address(); static Address current_limit_address(); + static Address current_level_address(); private: // Prevent heap allocation or illegal handle scopes. @@ -148,27 +156,8 @@ class HandleScope { void operator delete(void* size_t); static v8::ImplementationUtilities::HandleScopeData current_; - const v8::ImplementationUtilities::HandleScopeData previous_; - - // 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 - } + Object** const prev_next_; + Object** const prev_limit_; // Extend the handle scope making room for more handles. static internal::Object** Extend(); @@ -193,6 +182,10 @@ void NormalizeProperties(Handle<JSObject> object, void NormalizeElements(Handle<JSObject> object); void TransformToFastProperties(Handle<JSObject> object, int unused_property_fields); +void NumberDictionarySet(Handle<NumberDictionary> dictionary, + uint32_t index, + Handle<Object> value, + PropertyDetails details); // Flattens a string. void FlattenString(Handle<String> str); @@ -358,7 +351,7 @@ class NoHandleAllocation BASE_EMBEDDED { inline NoHandleAllocation(); inline ~NoHandleAllocation(); private: - int extensions_; + int level_; #endif }; diff --git a/deps/v8/src/heap-inl.h b/deps/v8/src/heap-inl.h index 104292df9c..15feb9d5fb 100644 --- a/deps/v8/src/heap-inl.h +++ b/deps/v8/src/heap-inl.h @@ -35,38 +35,28 @@ namespace v8 { 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() { return Page::kMaxHeapObjectSize; } -Object* Heap::AllocateSymbol(Vector<const char> str, - int chars, - uint32_t hash_field) { +MaybeObject* Heap::AllocateSymbol(Vector<const char> str, + int chars, + uint32_t hash_field) { unibrow::Utf8InputBuffer<> buffer(str.start(), static_cast<unsigned>(str.length())); return AllocateInternalSymbol(&buffer, chars, hash_field); } -Object* Heap::CopyFixedArray(FixedArray* src) { +MaybeObject* Heap::CopyFixedArray(FixedArray* src) { return CopyFixedArrayWithMap(src, src->map()); } -Object* Heap::AllocateRaw(int size_in_bytes, - AllocationSpace space, - AllocationSpace retry_space) { +MaybeObject* Heap::AllocateRaw(int size_in_bytes, + AllocationSpace space, + AllocationSpace retry_space) { ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); ASSERT(space != NEW_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_young.Increment(); #endif - Object* result; + MaybeObject* result; if (NEW_SPACE == space) { result = new_space_.AllocateRaw(size_in_bytes); 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); // Bypass NumberFromDouble to avoid various redundant checks. 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)) { return Smi::FromInt((int32_t)value); } @@ -144,12 +134,12 @@ void Heap::FinalizeExternalString(String* string) { } -Object* Heap::AllocateRawMap() { +MaybeObject* Heap::AllocateRawMap() { #ifdef DEBUG Counters::objs_since_last_full.Increment(); Counters::objs_since_last_young.Increment(); #endif - Object* result = map_space_->AllocateRaw(Map::kSize); + MaybeObject* result = map_space_->AllocateRaw(Map::kSize); if (result->IsFailure()) old_gen_exhausted_ = true; #ifdef DEBUG if (!result->IsFailure()) { @@ -162,12 +152,12 @@ Object* Heap::AllocateRawMap() { } -Object* Heap::AllocateRawCell() { +MaybeObject* Heap::AllocateRawCell() { #ifdef DEBUG Counters::objs_since_last_full.Increment(); Counters::objs_since_last_young.Increment(); #endif - Object* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize); + MaybeObject* result = cell_space_->AllocateRaw(JSGlobalPropertyCell::kSize); if (result->IsFailure()) old_gen_exhausted_ = true; 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 // after we have accumulated a certain amount we failed to flatten. static const int kMaxAlwaysFlattenLength = 32; static const int kFlattenLongThreshold = 16*KB; const int length = str->length(); - Object* obj = str->TryFlatten(); + MaybeObject* obj = str->TryFlatten(); if (length <= kMaxAlwaysFlattenLength || unflattened_strings_length_ >= kFlattenLongThreshold) { return obj; @@ -401,34 +391,36 @@ void Heap::SetLastScriptId(Object* last_script_id) { // to guarantee that any allocations performed during the call will // succeed if there's enough memory. -// Warning: Do not use the identifiers __object__ or __scope__ in a -// call to this macro. +// Warning: Do not use the identifiers __object__, __maybe_object__ or +// __scope__ in a call to this macro. #define CALL_AND_RETRY(FUNCTION_CALL, RETURN_VALUE, RETURN_EMPTY) \ do { \ GC_GREEDY_CHECK(); \ - Object* __object__ = FUNCTION_CALL; \ - if (!__object__->IsFailure()) RETURN_VALUE; \ - if (__object__->IsOutOfMemoryFailure()) { \ + MaybeObject* __maybe_object__ = FUNCTION_CALL; \ + Object* __object__ = NULL; \ + if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \ + if (__maybe_object__->IsOutOfMemory()) { \ v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\ } \ - if (!__object__->IsRetryAfterGC()) RETURN_EMPTY; \ - Heap::CollectGarbage(Failure::cast(__object__)->allocation_space()); \ - __object__ = FUNCTION_CALL; \ - if (!__object__->IsFailure()) RETURN_VALUE; \ - if (__object__->IsOutOfMemoryFailure()) { \ + if (!__maybe_object__->IsRetryAfterGC()) RETURN_EMPTY; \ + Heap::CollectGarbage(Failure::cast(__maybe_object__)-> \ + allocation_space()); \ + __maybe_object__ = FUNCTION_CALL; \ + if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \ + if (__maybe_object__->IsOutOfMemory()) { \ 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(); \ - Heap::CollectAllAvailableGarbage(); \ + Heap::CollectAllGarbage(false); \ { \ AlwaysAllocateScope __scope__; \ - __object__ = FUNCTION_CALL; \ + __maybe_object__ = FUNCTION_CALL; \ } \ - if (!__object__->IsFailure()) RETURN_VALUE; \ - if (__object__->IsOutOfMemoryFailure() || \ - __object__->IsRetryAfterGC()) { \ + if (__maybe_object__->ToObject(&__object__)) RETURN_VALUE; \ + if (__maybe_object__->IsOutOfMemory() || \ + __maybe_object__->IsRetryAfterGC()) { \ /* TODO(1181417): Fix this. */ \ v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2", true);\ } \ diff --git a/deps/v8/src/heap.cc b/deps/v8/src/heap.cc index 675639a341..fc90866552 100644 --- a/deps/v8/src/heap.cc +++ b/deps/v8/src/heap.cc @@ -56,6 +56,7 @@ String* Heap::hidden_symbol_; Object* Heap::roots_[Heap::kRootListLength]; Object* Heap::global_contexts_list_; + NewSpace Heap::new_space_; OldSpace* Heap::old_pointer_space_ = NULL; OldSpace* Heap::old_data_space_ = NULL; @@ -64,6 +65,9 @@ MapSpace* Heap::map_space_ = NULL; CellSpace* Heap::cell_space_ = NULL; LargeObjectSpace* Heap::lo_space_ = NULL; +static const intptr_t kMinimumPromotionLimit = 2 * MB; +static const intptr_t kMinimumAllocationLimit = 8 * MB; + intptr_t Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit; intptr_t Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit; @@ -415,25 +419,17 @@ void Heap::GarbageCollectionEpilogue() { } -void Heap::CollectAllGarbage(bool force_compaction, - CollectionPolicy collectionPolicy) { +void Heap::CollectAllGarbage(bool force_compaction) { // Since we are ignoring the return value, the exact choice of space does // not matter, so long as we do not specify NEW_SPACE, which would not // cause a full GC. MarkCompactCollector::SetForceCompaction(force_compaction); - CollectGarbage(OLD_POINTER_SPACE, collectionPolicy); + CollectGarbage(OLD_POINTER_SPACE); MarkCompactCollector::SetForceCompaction(false); } -void Heap::CollectAllAvailableGarbage() { - CompilationCache::Clear(); - CollectAllGarbage(true, AGGRESSIVE); -} - - -void Heap::CollectGarbage(AllocationSpace space, - CollectionPolicy collectionPolicy) { +void Heap::CollectGarbage(AllocationSpace space) { // The VM is in the GC state until exiting this function. VMState state(GC); @@ -460,7 +456,7 @@ void Heap::CollectGarbage(AllocationSpace space, ? &Counters::gc_scavenger : &Counters::gc_compactor; rate->Start(); - PerformGarbageCollection(collector, &tracer, collectionPolicy); + PerformGarbageCollection(collector, &tracer); rate->Stop(); GarbageCollectionEpilogue(); @@ -476,7 +472,7 @@ void Heap::CollectGarbage(AllocationSpace space, void Heap::PerformScavenge() { GCTracer tracer; - PerformGarbageCollection(SCAVENGER, &tracer, NORMAL); + PerformGarbageCollection(SCAVENGER, &tracer); } @@ -661,8 +657,7 @@ void Heap::UpdateSurvivalRateTrend(int start_new_space_size) { } void Heap::PerformGarbageCollection(GarbageCollector collector, - GCTracer* tracer, - CollectionPolicy collectionPolicy) { + GCTracer* tracer) { if (collector != SCAVENGER) { PROFILE(CodeMovingGCEvent()); } @@ -696,45 +691,25 @@ void Heap::PerformGarbageCollection(GarbageCollector collector, UpdateSurvivalRateTrend(start_new_space_size); - UpdateOldSpaceLimits(); - - // Major GC would invoke weak handle callbacks on weakly reachable - // handles, but won't collect weakly reachable objects until next - // major GC. Therefore if we collect aggressively and weak handle callback - // has been invoked, we rerun major GC to release objects which become - // garbage. - if (collectionPolicy == AGGRESSIVE) { - // Note: as weak callbacks can execute arbitrary code, we cannot - // hope that eventually there will be no weak callbacks invocations. - // Therefore stop recollecting after several attempts. - const int kMaxNumberOfAttempts = 7; - for (int attempt = 0; attempt < kMaxNumberOfAttempts; attempt++) { - { DisableAssertNoAllocation allow_allocation; - GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); - if (!GlobalHandles::PostGarbageCollectionProcessing()) break; - } - MarkCompact(tracer); - // Weak handle callbacks can allocate data, so keep limits correct. - UpdateOldSpaceLimits(); - } - } else { - if (high_survival_rate_during_scavenges && - IsStableOrIncreasingSurvivalTrend()) { - // Stable high survival rates of young objects both during partial and - // full collection indicate that mutator is either building or modifying - // a structure with a long lifetime. - // In this case we aggressively raise old generation memory limits to - // postpone subsequent mark-sweep collection and thus trade memory - // space for the mutation speed. - old_gen_promotion_limit_ *= 2; - old_gen_allocation_limit_ *= 2; - } + 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); + + if (high_survival_rate_during_scavenges && + IsStableOrIncreasingSurvivalTrend()) { + // Stable high survival rates of young objects both during partial and + // full collection indicate that mutator is either building or modifying + // a structure with a long lifetime. + // In this case we aggressively raise old generation memory limits to + // postpone subsequent mark-sweep collection and thus trade memory + // space for the mutation speed. + old_gen_promotion_limit_ *= 2; + old_gen_allocation_limit_ *= 2; } - { DisableAssertNoAllocation allow_allocation; - GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); - GlobalHandles::PostGarbageCollectionProcessing(); - } + old_gen_exhausted_ = false; } else { tracer_ = tracer; Scavenge(); @@ -745,6 +720,12 @@ void Heap::PerformGarbageCollection(GarbageCollector collector, Counters::objs_since_last_young.Set(0); + if (collector == MARK_COMPACTOR) { + DisableAssertNoAllocation allow_allocation; + GCTracer::Scope scope(tracer, GCTracer::Scope::EXTERNAL); + GlobalHandles::PostGarbageCollectionProcessing(); + } + // Update relocatables. Relocatable::PostGarbageCollectionProcessing(); @@ -821,11 +802,12 @@ void Heap::MarkCompactPrologue(bool is_compacting) { Object* Heap::FindCodeObject(Address a) { - Object* obj = code_space_->FindObject(a); - if (obj->IsFailure()) { - obj = lo_space_->FindObject(a); + Object* obj = NULL; // Initialization to please compiler. + { MaybeObject* maybe_obj = code_space_->FindObject(a); + if (!maybe_obj->ToObject(&obj)) { + obj = lo_space_->FindObject(a)->ToObjectUnchecked(); + } } - ASSERT(!obj->IsFailure()); return obj; } @@ -1279,20 +1261,21 @@ class ScavengingVisitor : public StaticVisitorBase { ASSERT(object->Size() == object_size); if (Heap::ShouldBePromoted(object->address(), object_size)) { - Object* result; + MaybeObject* maybe_result; if ((size_restriction != SMALL) && (object_size > Page::kMaxHeapObjectSize)) { - result = Heap::lo_space()->AllocateRawFixedArray(object_size); + maybe_result = Heap::lo_space()->AllocateRawFixedArray(object_size); } else { if (object_contents == DATA_OBJECT) { - result = Heap::old_data_space()->AllocateRaw(object_size); + maybe_result = Heap::old_data_space()->AllocateRaw(object_size); } else { - result = Heap::old_pointer_space()->AllocateRaw(object_size); + maybe_result = Heap::old_pointer_space()->AllocateRaw(object_size); } } - if (!result->IsFailure()) { + Object* result = NULL; // Initialization to please compiler. + if (maybe_result->ToObject(&result)) { HeapObject* target = HeapObject::cast(result); *slot = MigrateObject(object, target, object_size); @@ -1304,8 +1287,8 @@ class ScavengingVisitor : public StaticVisitorBase { return; } } - Object* result = Heap::new_space()->AllocateRaw(object_size); - ASSERT(!result->IsFailure()); + Object* result = + Heap::new_space()->AllocateRaw(object_size)->ToObjectUnchecked(); *slot = MigrateObject(object, HeapObject::cast(result), object_size); return; } @@ -1427,10 +1410,12 @@ void Heap::ScavengePointer(HeapObject** p) { } -Object* Heap::AllocatePartialMap(InstanceType instance_type, - int instance_size) { - Object* result = AllocateRawMap(); - if (result->IsFailure()) return result; +MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type, + int instance_size) { + Object* result; + { MaybeObject* maybe_result = AllocateRawMap(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Map::cast cannot be used due to uninitialized map field. reinterpret_cast<Map*>(result)->set_map(raw_unchecked_meta_map()); @@ -1448,9 +1433,11 @@ Object* Heap::AllocatePartialMap(InstanceType instance_type, } -Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) { - Object* result = AllocateRawMap(); - if (result->IsFailure()) return result; +MaybeObject* Heap::AllocateMap(InstanceType instance_type, int instance_size) { + Object* result; + { MaybeObject* maybe_result = AllocateRawMap(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Map* map = reinterpret_cast<Map*>(result); map->set_map(meta_map()); @@ -1478,9 +1465,11 @@ Object* Heap::AllocateMap(InstanceType instance_type, int instance_size) { } -Object* Heap::AllocateCodeCache() { - Object* result = AllocateStruct(CODE_CACHE_TYPE); - if (result->IsFailure()) return result; +MaybeObject* Heap::AllocateCodeCache() { + Object* result; + { MaybeObject* maybe_result = AllocateStruct(CODE_CACHE_TYPE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } CodeCache* code_cache = CodeCache::cast(result); code_cache->set_default_cache(empty_fixed_array()); code_cache->set_normal_type_cache(undefined_value()); @@ -1513,33 +1502,41 @@ const Heap::StructTable Heap::struct_table[] = { bool Heap::CreateInitialMaps() { - Object* obj = AllocatePartialMap(MAP_TYPE, Map::kSize); - if (obj->IsFailure()) return false; + Object* obj; + { MaybeObject* maybe_obj = AllocatePartialMap(MAP_TYPE, Map::kSize); + if (!maybe_obj->ToObject(&obj)) return false; + } // Map::cast cannot be used due to uninitialized map field. Map* new_meta_map = reinterpret_cast<Map*>(obj); set_meta_map(new_meta_map); new_meta_map->set_map(new_meta_map); - obj = AllocatePartialMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocatePartialMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } set_fixed_array_map(Map::cast(obj)); - obj = AllocatePartialMap(ODDBALL_TYPE, Oddball::kSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocatePartialMap(ODDBALL_TYPE, Oddball::kSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_oddball_map(Map::cast(obj)); // Allocate the empty array. - obj = AllocateEmptyFixedArray(); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); + if (!maybe_obj->ToObject(&obj)) return false; + } set_empty_fixed_array(FixedArray::cast(obj)); - obj = Allocate(oddball_map(), OLD_DATA_SPACE); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_DATA_SPACE); + if (!maybe_obj->ToObject(&obj)) return false; + } set_null_value(obj); // Allocate the empty descriptor array. - obj = AllocateEmptyFixedArray(); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateEmptyFixedArray(); + if (!maybe_obj->ToObject(&obj)) return false; + } set_empty_descriptor_array(DescriptorArray::cast(obj)); // Fix the instance_descriptors for the existing maps. @@ -1562,124 +1559,157 @@ bool Heap::CreateInitialMaps() { oddball_map()->set_prototype(null_value()); oddball_map()->set_constructor(null_value()); - obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } set_fixed_cow_array_map(Map::cast(obj)); ASSERT(fixed_array_map() != fixed_cow_array_map()); - obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(HEAP_NUMBER_TYPE, HeapNumber::kSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_heap_number_map(Map::cast(obj)); - obj = AllocateMap(PROXY_TYPE, Proxy::kSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(PROXY_TYPE, Proxy::kSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_proxy_map(Map::cast(obj)); for (unsigned i = 0; i < ARRAY_SIZE(string_type_table); i++) { const StringTypeTable& entry = string_type_table[i]; - obj = AllocateMap(entry.type, entry.size); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size); + if (!maybe_obj->ToObject(&obj)) return false; + } roots_[entry.index] = Map::cast(obj); } - obj = AllocateMap(STRING_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(STRING_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } set_undetectable_string_map(Map::cast(obj)); Map::cast(obj)->set_is_undetectable(); - obj = AllocateMap(ASCII_STRING_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateMap(ASCII_STRING_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } set_undetectable_ascii_string_map(Map::cast(obj)); Map::cast(obj)->set_is_undetectable(); - obj = AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateMap(BYTE_ARRAY_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } set_byte_array_map(Map::cast(obj)); - obj = AllocateMap(PIXEL_ARRAY_TYPE, PixelArray::kAlignedSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateMap(PIXEL_ARRAY_TYPE, PixelArray::kAlignedSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_pixel_array_map(Map::cast(obj)); - obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE, - ExternalArray::kAlignedSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_BYTE_ARRAY_TYPE, + ExternalArray::kAlignedSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_external_byte_array_map(Map::cast(obj)); - obj = AllocateMap(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE, - ExternalArray::kAlignedSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE, + ExternalArray::kAlignedSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_external_unsigned_byte_array_map(Map::cast(obj)); - obj = AllocateMap(EXTERNAL_SHORT_ARRAY_TYPE, - ExternalArray::kAlignedSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_SHORT_ARRAY_TYPE, + ExternalArray::kAlignedSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_external_short_array_map(Map::cast(obj)); - obj = AllocateMap(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE, - ExternalArray::kAlignedSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE, + ExternalArray::kAlignedSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_external_unsigned_short_array_map(Map::cast(obj)); - obj = AllocateMap(EXTERNAL_INT_ARRAY_TYPE, - ExternalArray::kAlignedSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_INT_ARRAY_TYPE, + ExternalArray::kAlignedSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_external_int_array_map(Map::cast(obj)); - obj = AllocateMap(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE, - ExternalArray::kAlignedSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_UNSIGNED_INT_ARRAY_TYPE, + ExternalArray::kAlignedSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_external_unsigned_int_array_map(Map::cast(obj)); - obj = AllocateMap(EXTERNAL_FLOAT_ARRAY_TYPE, - ExternalArray::kAlignedSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(EXTERNAL_FLOAT_ARRAY_TYPE, + ExternalArray::kAlignedSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_external_float_array_map(Map::cast(obj)); - obj = AllocateMap(CODE_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(CODE_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } set_code_map(Map::cast(obj)); - obj = AllocateMap(JS_GLOBAL_PROPERTY_CELL_TYPE, - JSGlobalPropertyCell::kSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(JS_GLOBAL_PROPERTY_CELL_TYPE, + JSGlobalPropertyCell::kSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_global_property_cell_map(Map::cast(obj)); - obj = AllocateMap(FILLER_TYPE, kPointerSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, kPointerSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_one_pointer_filler_map(Map::cast(obj)); - obj = AllocateMap(FILLER_TYPE, 2 * kPointerSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(FILLER_TYPE, 2 * kPointerSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_two_pointer_filler_map(Map::cast(obj)); for (unsigned i = 0; i < ARRAY_SIZE(struct_table); i++) { const StructTable& entry = struct_table[i]; - obj = AllocateMap(entry.type, entry.size); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(entry.type, entry.size); + if (!maybe_obj->ToObject(&obj)) return false; + } roots_[entry.index] = Map::cast(obj); } - obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } set_hash_table_map(Map::cast(obj)); - obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } set_context_map(Map::cast(obj)); - obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } set_catch_context_map(Map::cast(obj)); - obj = AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateMap(FIXED_ARRAY_TYPE, kVariableSizeSentinel); + if (!maybe_obj->ToObject(&obj)) return false; + } Map* global_context_map = Map::cast(obj); global_context_map->set_visitor_id(StaticVisitorBase::kVisitGlobalContext); set_global_context_map(global_context_map); - obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE, - SharedFunctionInfo::kAlignedSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(SHARED_FUNCTION_INFO_TYPE, + SharedFunctionInfo::kAlignedSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_shared_function_info_map(Map::cast(obj)); ASSERT(!Heap::InNewSpace(Heap::empty_fixed_array())); @@ -1687,14 +1717,17 @@ bool Heap::CreateInitialMaps() { } -Object* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) { +MaybeObject* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) { // Statically ensure that it is safe to allocate heap numbers in paged // spaces. STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize); AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; - Object* result = AllocateRaw(HeapNumber::kSize, space, OLD_DATA_SPACE); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + AllocateRaw(HeapNumber::kSize, space, OLD_DATA_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } HeapObject::cast(result)->set_map(heap_number_map()); HeapNumber::cast(result)->set_value(value); @@ -1702,7 +1735,7 @@ Object* Heap::AllocateHeapNumber(double value, PretenureFlag pretenure) { } -Object* Heap::AllocateHeapNumber(double value) { +MaybeObject* Heap::AllocateHeapNumber(double value) { // Use general version, if we're forced to always allocate. if (always_allocate()) return AllocateHeapNumber(value, TENURED); @@ -1710,27 +1743,33 @@ Object* Heap::AllocateHeapNumber(double value) { // allocation in new space. STATIC_ASSERT(HeapNumber::kSize <= Page::kMaxHeapObjectSize); ASSERT(allocation_allowed_ && gc_state_ == NOT_IN_GC); - Object* result = new_space_.AllocateRaw(HeapNumber::kSize); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = new_space_.AllocateRaw(HeapNumber::kSize); + if (!maybe_result->ToObject(&result)) return maybe_result; + } HeapObject::cast(result)->set_map(heap_number_map()); HeapNumber::cast(result)->set_value(value); return result; } -Object* Heap::AllocateJSGlobalPropertyCell(Object* value) { - Object* result = AllocateRawCell(); - if (result->IsFailure()) return result; +MaybeObject* Heap::AllocateJSGlobalPropertyCell(Object* value) { + Object* result; + { MaybeObject* maybe_result = AllocateRawCell(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } HeapObject::cast(result)->set_map(global_property_cell_map()); JSGlobalPropertyCell::cast(result)->set_value(value); return result; } -Object* Heap::CreateOddball(const char* to_string, - Object* to_number) { - Object* result = Allocate(oddball_map(), OLD_DATA_SPACE); - if (result->IsFailure()) return result; +MaybeObject* Heap::CreateOddball(const char* to_string, + Object* to_number) { + Object* result; + { MaybeObject* maybe_result = Allocate(oddball_map(), OLD_DATA_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } return Oddball::cast(result)->Initialize(to_string, to_number); } @@ -1738,14 +1777,18 @@ Object* Heap::CreateOddball(const char* to_string, bool Heap::CreateApiObjects() { Object* obj; - obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); + if (!maybe_obj->ToObject(&obj)) return false; + } set_neander_map(Map::cast(obj)); - obj = Heap::AllocateJSObjectFromMap(neander_map()); - if (obj->IsFailure()) return false; - Object* elements = AllocateFixedArray(2); - if (elements->IsFailure()) return false; + { MaybeObject* maybe_obj = Heap::AllocateJSObjectFromMap(neander_map()); + if (!maybe_obj->ToObject(&obj)) return false; + } + Object* elements; + { MaybeObject* maybe_elements = AllocateFixedArray(2); + if (!maybe_elements->ToObject(&elements)) return false; + } FixedArray::cast(elements)->set(0, Smi::FromInt(0)); JSObject::cast(obj)->set_elements(FixedArray::cast(elements)); set_message_listeners(JSObject::cast(obj)); @@ -1807,64 +1850,82 @@ bool Heap::CreateInitialObjects() { Object* obj; // The -0 value must be set before NumberFromDouble works. - obj = AllocateHeapNumber(-0.0, TENURED); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateHeapNumber(-0.0, TENURED); + if (!maybe_obj->ToObject(&obj)) return false; + } set_minus_zero_value(obj); ASSERT(signbit(minus_zero_value()->Number()) != 0); - obj = AllocateHeapNumber(OS::nan_value(), TENURED); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateHeapNumber(OS::nan_value(), TENURED); + if (!maybe_obj->ToObject(&obj)) return false; + } set_nan_value(obj); - obj = Allocate(oddball_map(), OLD_DATA_SPACE); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = Allocate(oddball_map(), OLD_DATA_SPACE); + if (!maybe_obj->ToObject(&obj)) return false; + } set_undefined_value(obj); ASSERT(!InNewSpace(undefined_value())); // Allocate initial symbol table. - obj = SymbolTable::Allocate(kInitialSymbolTableSize); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = SymbolTable::Allocate(kInitialSymbolTableSize); + if (!maybe_obj->ToObject(&obj)) return false; + } // Don't use set_symbol_table() due to asserts. roots_[kSymbolTableRootIndex] = obj; // Assign the print strings for oddballs after creating symboltable. - Object* symbol = LookupAsciiSymbol("undefined"); - if (symbol->IsFailure()) return false; + Object* symbol; + { MaybeObject* maybe_symbol = LookupAsciiSymbol("undefined"); + if (!maybe_symbol->ToObject(&symbol)) return false; + } Oddball::cast(undefined_value())->set_to_string(String::cast(symbol)); Oddball::cast(undefined_value())->set_to_number(nan_value()); // Allocate the null_value - obj = Oddball::cast(null_value())->Initialize("null", Smi::FromInt(0)); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + Oddball::cast(null_value())->Initialize("null", Smi::FromInt(0)); + if (!maybe_obj->ToObject(&obj)) return false; + } - obj = CreateOddball("true", Smi::FromInt(1)); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = CreateOddball("true", Smi::FromInt(1)); + if (!maybe_obj->ToObject(&obj)) return false; + } set_true_value(obj); - obj = CreateOddball("false", Smi::FromInt(0)); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = CreateOddball("false", Smi::FromInt(0)); + if (!maybe_obj->ToObject(&obj)) return false; + } set_false_value(obj); - obj = CreateOddball("hole", Smi::FromInt(-1)); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = CreateOddball("hole", Smi::FromInt(-1)); + if (!maybe_obj->ToObject(&obj)) return false; + } set_the_hole_value(obj); - obj = CreateOddball("no_interceptor_result_sentinel", Smi::FromInt(-2)); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + CreateOddball("no_interceptor_result_sentinel", Smi::FromInt(-2)); + if (!maybe_obj->ToObject(&obj)) return false; + } set_no_interceptor_result_sentinel(obj); - obj = CreateOddball("termination_exception", Smi::FromInt(-3)); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + CreateOddball("termination_exception", Smi::FromInt(-3)); + if (!maybe_obj->ToObject(&obj)) return false; + } set_termination_exception(obj); // Allocate the empty string. - obj = AllocateRawAsciiString(0, TENURED); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateRawAsciiString(0, TENURED); + if (!maybe_obj->ToObject(&obj)) return false; + } set_empty_string(String::cast(obj)); for (unsigned i = 0; i < ARRAY_SIZE(constant_symbol_table); i++) { - obj = LookupAsciiSymbol(constant_symbol_table[i].contents); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + LookupAsciiSymbol(constant_symbol_table[i].contents); + if (!maybe_obj->ToObject(&obj)) return false; + } roots_[constant_symbol_table[i].index] = String::cast(obj); } @@ -1874,25 +1935,31 @@ bool Heap::CreateInitialObjects() { // loop above because it needs to be allocated manually with the special // hash code in place. The hash code for the hidden_symbol is zero to ensure // that it will always be at the first entry in property descriptors. - obj = AllocateSymbol(CStrVector(""), 0, String::kZeroHash); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateSymbol(CStrVector(""), 0, String::kZeroHash); + if (!maybe_obj->ToObject(&obj)) return false; + } hidden_symbol_ = String::cast(obj); // Allocate the proxy for __proto__. - obj = AllocateProxy((Address) &Accessors::ObjectPrototype); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateProxy((Address) &Accessors::ObjectPrototype); + if (!maybe_obj->ToObject(&obj)) return false; + } set_prototype_accessors(Proxy::cast(obj)); // Allocate the code_stubs dictionary. The initial size is set to avoid // expanding the dictionary during bootstrapping. - obj = NumberDictionary::Allocate(128); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = NumberDictionary::Allocate(128); + if (!maybe_obj->ToObject(&obj)) return false; + } set_code_stubs(NumberDictionary::cast(obj)); // Allocate the non_monomorphic_cache used in stub-cache.cc. The initial size // is set to avoid expanding the dictionary during bootstrapping. - obj = NumberDictionary::Allocate(64); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = NumberDictionary::Allocate(64); + if (!maybe_obj->ToObject(&obj)) return false; + } set_non_monomorphic_cache(NumberDictionary::cast(obj)); set_instanceof_cache_function(Smi::FromInt(0)); @@ -1902,22 +1969,27 @@ bool Heap::CreateInitialObjects() { CreateFixedStubs(); // Allocate the dictionary of intrinsic function names. - obj = StringDictionary::Allocate(Runtime::kNumFunctions); - if (obj->IsFailure()) return false; - obj = Runtime::InitializeIntrinsicFunctionNames(obj); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = StringDictionary::Allocate(Runtime::kNumFunctions); + if (!maybe_obj->ToObject(&obj)) return false; + } + { MaybeObject* maybe_obj = Runtime::InitializeIntrinsicFunctionNames(obj); + if (!maybe_obj->ToObject(&obj)) return false; + } set_intrinsic_function_names(StringDictionary::cast(obj)); if (InitializeNumberStringCache()->IsFailure()) return false; // Allocate cache for single character ASCII strings. - obj = AllocateFixedArray(String::kMaxAsciiCharCode + 1, TENURED); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = + AllocateFixedArray(String::kMaxAsciiCharCode + 1, TENURED); + if (!maybe_obj->ToObject(&obj)) return false; + } set_single_character_string_cache(FixedArray::cast(obj)); // Allocate cache for external strings pointing to native source code. - obj = AllocateFixedArray(Natives::GetBuiltinsCount()); - if (obj->IsFailure()) return false; + { MaybeObject* maybe_obj = AllocateFixedArray(Natives::GetBuiltinsCount()); + if (!maybe_obj->ToObject(&obj)) return false; + } set_natives_source_cache(FixedArray::cast(obj)); // Handling of script id generation is in Factory::NewScript. @@ -1939,15 +2011,17 @@ bool Heap::CreateInitialObjects() { } -Object* Heap::InitializeNumberStringCache() { +MaybeObject* Heap::InitializeNumberStringCache() { // Compute the size of the number string cache based on the max heap size. // max_semispace_size_ == 512 KB => number_string_cache_size = 32. // max_semispace_size_ == 8 MB => number_string_cache_size = 16KB. int number_string_cache_size = max_semispace_size_ / 512; number_string_cache_size = Max(32, Min(16*KB, number_string_cache_size)); - Object* obj = AllocateFixedArray(number_string_cache_size * 2, TENURED); - if (!obj->IsFailure()) set_number_string_cache(FixedArray::cast(obj)); - return obj; + Object* obj; + MaybeObject* maybe_obj = + AllocateFixedArray(number_string_cache_size * 2, TENURED); + if (maybe_obj->ToObject(&obj)) set_number_string_cache(FixedArray::cast(obj)); + return maybe_obj; } @@ -2005,7 +2079,8 @@ void Heap::SetNumberStringCache(Object* number, String* string) { } -Object* Heap::NumberToString(Object* number, bool check_number_string_cache) { +MaybeObject* Heap::NumberToString(Object* number, + bool check_number_string_cache) { Counters::number_to_string_runtime.Increment(); if (check_number_string_cache) { Object* cached = GetNumberStringCache(number); @@ -2024,12 +2099,13 @@ Object* Heap::NumberToString(Object* number, bool check_number_string_cache) { double num = HeapNumber::cast(number)->value(); str = DoubleToCString(num, buffer); } - Object* result = AllocateStringFromAscii(CStrVector(str)); - if (!result->IsFailure()) { - SetNumberStringCache(number, String::cast(result)); + Object* js_string; + MaybeObject* maybe_js_string = AllocateStringFromAscii(CStrVector(str)); + if (maybe_js_string->ToObject(&js_string)) { + SetNumberStringCache(number, String::cast(js_string)); } - return result; + return maybe_js_string; } @@ -2062,7 +2138,7 @@ Heap::RootListIndex Heap::RootIndexForExternalArrayType( } -Object* Heap::NumberFromDouble(double value, PretenureFlag pretenure) { +MaybeObject* Heap::NumberFromDouble(double value, PretenureFlag pretenure) { // We need to distinguish the minus zero value and this cannot be // done after conversion to int. Doing this by comparing bit // patterns is faster than using fpclassify() et al. @@ -2083,21 +2159,26 @@ Object* Heap::NumberFromDouble(double value, PretenureFlag pretenure) { } -Object* Heap::AllocateProxy(Address proxy, PretenureFlag pretenure) { +MaybeObject* Heap::AllocateProxy(Address proxy, PretenureFlag pretenure) { // Statically ensure that it is safe to allocate proxies in paged spaces. STATIC_ASSERT(Proxy::kSize <= Page::kMaxHeapObjectSize); AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; - Object* result = Allocate(proxy_map(), space); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Allocate(proxy_map(), space); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Proxy::cast(result)->set_proxy(proxy); return result; } -Object* Heap::AllocateSharedFunctionInfo(Object* name) { - Object* result = Allocate(shared_function_info_map(), OLD_POINTER_SPACE); - if (result->IsFailure()) return result; +MaybeObject* Heap::AllocateSharedFunctionInfo(Object* name) { + Object* result; + { MaybeObject* maybe_result = + Allocate(shared_function_info_map(), OLD_POINTER_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } SharedFunctionInfo* share = SharedFunctionInfo::cast(result); share->set_name(name); @@ -2133,7 +2214,9 @@ static inline bool Between(uint32_t character, uint32_t from, uint32_t to) { } -static inline Object* MakeOrFindTwoCharacterString(uint32_t c1, uint32_t c2) { +MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString( + uint32_t c1, + uint32_t c2) { String* symbol; // Numeric strings have a different hash algorithm not known by // LookupTwoCharsSymbolIfExists, so we skip this step for such strings. @@ -2144,15 +2227,19 @@ static inline Object* MakeOrFindTwoCharacterString(uint32_t c1, uint32_t c2) { // when building the new string. } else if ((c1 | c2) <= String::kMaxAsciiCharCodeU) { // We can do this ASSERT(IsPowerOf2(String::kMaxAsciiCharCodeU + 1)); // because of this. - Object* result = Heap::AllocateRawAsciiString(2); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::AllocateRawAsciiString(2); + if (!maybe_result->ToObject(&result)) return maybe_result; + } char* dest = SeqAsciiString::cast(result)->GetChars(); dest[0] = c1; dest[1] = c2; return result; } else { - Object* result = Heap::AllocateRawTwoByteString(2); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::AllocateRawTwoByteString(2); + if (!maybe_result->ToObject(&result)) return maybe_result; + } uc16* dest = SeqTwoByteString::cast(result)->GetChars(); dest[0] = c1; dest[1] = c2; @@ -2161,7 +2248,7 @@ static inline Object* MakeOrFindTwoCharacterString(uint32_t c1, uint32_t c2) { } -Object* Heap::AllocateConsString(String* first, String* second) { +MaybeObject* Heap::AllocateConsString(String* first, String* second) { int first_length = first->length(); if (first_length == 0) { return second; @@ -2211,8 +2298,10 @@ Object* Heap::AllocateConsString(String* first, String* second) { ASSERT(first->IsFlat()); ASSERT(second->IsFlat()); if (is_ascii) { - Object* result = AllocateRawAsciiString(length); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateRawAsciiString(length); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Copy the characters into the new object. char* dest = SeqAsciiString::cast(result)->GetChars(); // Copy first part. @@ -2233,8 +2322,10 @@ Object* Heap::AllocateConsString(String* first, String* second) { return result; } else { if (is_ascii_data_in_two_byte_string) { - Object* result = AllocateRawAsciiString(length); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateRawAsciiString(length); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Copy the characters into the new object. char* dest = SeqAsciiString::cast(result)->GetChars(); String::WriteToFlat(first, dest, 0, first_length); @@ -2242,8 +2333,10 @@ Object* Heap::AllocateConsString(String* first, String* second) { return result; } - Object* result = AllocateRawTwoByteString(length); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateRawTwoByteString(length); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Copy the characters into the new object. uc16* dest = SeqTwoByteString::cast(result)->GetChars(); String::WriteToFlat(first, dest, 0, first_length); @@ -2255,8 +2348,10 @@ Object* Heap::AllocateConsString(String* first, String* second) { Map* map = (is_ascii || is_ascii_data_in_two_byte_string) ? cons_ascii_string_map() : cons_string_map(); - Object* result = Allocate(map, NEW_SPACE); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } AssertNoAllocation no_gc; ConsString* cons_string = ConsString::cast(result); @@ -2269,7 +2364,7 @@ Object* Heap::AllocateConsString(String* first, String* second) { } -Object* Heap::AllocateSubString(String* buffer, +MaybeObject* Heap::AllocateSubString(String* buffer, int start, int end, PretenureFlag pretenure) { @@ -2290,10 +2385,12 @@ Object* Heap::AllocateSubString(String* buffer, // Make an attempt to flatten the buffer to reduce access time. buffer = buffer->TryFlattenGetString(); - Object* result = buffer->IsAsciiRepresentation() - ? AllocateRawAsciiString(length, pretenure ) - : AllocateRawTwoByteString(length, pretenure); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = buffer->IsAsciiRepresentation() + ? AllocateRawAsciiString(length, pretenure ) + : AllocateRawTwoByteString(length, pretenure); + if (!maybe_result->ToObject(&result)) return maybe_result; + } String* string_result = String::cast(result); // Copy the characters into the new object. if (buffer->IsAsciiRepresentation()) { @@ -2310,7 +2407,7 @@ Object* Heap::AllocateSubString(String* buffer, } -Object* Heap::AllocateExternalStringFromAscii( +MaybeObject* Heap::AllocateExternalStringFromAscii( ExternalAsciiString::Resource* resource) { size_t length = resource->length(); if (length > static_cast<size_t>(String::kMaxLength)) { @@ -2319,8 +2416,10 @@ Object* Heap::AllocateExternalStringFromAscii( } Map* map = external_ascii_string_map(); - Object* result = Allocate(map, NEW_SPACE); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } ExternalAsciiString* external_string = ExternalAsciiString::cast(result); external_string->set_length(static_cast<int>(length)); @@ -2331,7 +2430,7 @@ Object* Heap::AllocateExternalStringFromAscii( } -Object* Heap::AllocateExternalStringFromTwoByte( +MaybeObject* Heap::AllocateExternalStringFromTwoByte( ExternalTwoByteString::Resource* resource) { size_t length = resource->length(); if (length > static_cast<size_t>(String::kMaxLength)) { @@ -2356,8 +2455,10 @@ Object* Heap::AllocateExternalStringFromTwoByte( Map* map = is_ascii ? Heap::external_string_with_ascii_data_map() : Heap::external_string_map(); - Object* result = Allocate(map, NEW_SPACE); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Allocate(map, NEW_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } ExternalTwoByteString* external_string = ExternalTwoByteString::cast(result); external_string->set_length(static_cast<int>(length)); @@ -2368,29 +2469,32 @@ Object* Heap::AllocateExternalStringFromTwoByte( } -Object* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { +MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) { if (code <= String::kMaxAsciiCharCode) { Object* value = Heap::single_character_string_cache()->get(code); if (value != Heap::undefined_value()) return value; char buffer[1]; buffer[0] = static_cast<char>(code); - Object* result = LookupSymbol(Vector<const char>(buffer, 1)); + Object* result; + MaybeObject* maybe_result = LookupSymbol(Vector<const char>(buffer, 1)); - if (result->IsFailure()) return result; + if (!maybe_result->ToObject(&result)) return maybe_result; Heap::single_character_string_cache()->set(code, result); return result; } - Object* result = Heap::AllocateRawTwoByteString(1); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::AllocateRawTwoByteString(1); + if (!maybe_result->ToObject(&result)) return maybe_result; + } String* answer = String::cast(result); answer->Set(0, code); return answer; } -Object* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { +MaybeObject* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { if (length < 0 || length > ByteArray::kMaxLength) { return Failure::OutOfMemoryException(); } @@ -2398,10 +2502,12 @@ Object* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { return AllocateByteArray(length); } int size = ByteArray::SizeFor(length); - Object* result = (size <= MaxObjectSizeInPagedSpace()) - ? old_data_space_->AllocateRaw(size) - : lo_space_->AllocateRaw(size); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = (size <= MaxObjectSizeInPagedSpace()) + ? old_data_space_->AllocateRaw(size) + : lo_space_->AllocateRaw(size); + if (!maybe_result->ToObject(&result)) return maybe_result; + } reinterpret_cast<ByteArray*>(result)->set_map(byte_array_map()); reinterpret_cast<ByteArray*>(result)->set_length(length); @@ -2409,15 +2515,17 @@ Object* Heap::AllocateByteArray(int length, PretenureFlag pretenure) { } -Object* Heap::AllocateByteArray(int length) { +MaybeObject* Heap::AllocateByteArray(int length) { if (length < 0 || length > ByteArray::kMaxLength) { return Failure::OutOfMemoryException(); } int size = ByteArray::SizeFor(length); AllocationSpace space = (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : NEW_SPACE; - Object* result = AllocateRaw(size, space, OLD_DATA_SPACE); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateRaw(size, space, OLD_DATA_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } reinterpret_cast<ByteArray*>(result)->set_map(byte_array_map()); reinterpret_cast<ByteArray*>(result)->set_length(length); @@ -2439,12 +2547,15 @@ void Heap::CreateFillerObjectAt(Address addr, int size) { } -Object* Heap::AllocatePixelArray(int length, +MaybeObject* Heap::AllocatePixelArray(int length, uint8_t* external_pointer, PretenureFlag pretenure) { AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; - Object* result = AllocateRaw(PixelArray::kAlignedSize, space, OLD_DATA_SPACE); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + AllocateRaw(PixelArray::kAlignedSize, space, OLD_DATA_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } reinterpret_cast<PixelArray*>(result)->set_map(pixel_array_map()); reinterpret_cast<PixelArray*>(result)->set_length(length); @@ -2454,15 +2565,17 @@ Object* Heap::AllocatePixelArray(int length, } -Object* Heap::AllocateExternalArray(int length, - ExternalArrayType array_type, - void* external_pointer, - PretenureFlag pretenure) { +MaybeObject* Heap::AllocateExternalArray(int length, + ExternalArrayType array_type, + void* external_pointer, + PretenureFlag pretenure) { AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; - Object* result = AllocateRaw(ExternalArray::kAlignedSize, - space, - OLD_DATA_SPACE); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateRaw(ExternalArray::kAlignedSize, + space, + OLD_DATA_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } reinterpret_cast<ExternalArray*>(result)->set_map( MapForExternalArrayType(array_type)); @@ -2474,26 +2587,29 @@ Object* Heap::AllocateExternalArray(int length, } -Object* Heap::CreateCode(const CodeDesc& desc, - Code::Flags flags, - Handle<Object> self_reference) { +MaybeObject* Heap::CreateCode(const CodeDesc& desc, + Code::Flags flags, + Handle<Object> self_reference) { // Allocate ByteArray before the Code object, so that we do not risk // leaving uninitialized Code object (and breaking the heap). - Object* reloc_info = AllocateByteArray(desc.reloc_size, TENURED); - if (reloc_info->IsFailure()) return reloc_info; + Object* reloc_info; + { MaybeObject* maybe_reloc_info = AllocateByteArray(desc.reloc_size, TENURED); + if (!maybe_reloc_info->ToObject(&reloc_info)) return maybe_reloc_info; + } // Compute size int body_size = RoundUp(desc.instr_size, kObjectAlignment); int obj_size = Code::SizeFor(body_size); ASSERT(IsAligned(static_cast<intptr_t>(obj_size), kCodeAlignment)); - Object* result; + MaybeObject* maybe_result; if (obj_size > MaxObjectSizeInPagedSpace()) { - result = lo_space_->AllocateRawCode(obj_size); + maybe_result = lo_space_->AllocateRawCode(obj_size); } else { - result = code_space_->AllocateRaw(obj_size); + maybe_result = code_space_->AllocateRaw(obj_size); } - if (result->IsFailure()) return result; + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // Initialize the object HeapObject::cast(result)->set_map(code_map()); @@ -2521,17 +2637,18 @@ Object* Heap::CreateCode(const CodeDesc& desc, } -Object* Heap::CopyCode(Code* code) { +MaybeObject* Heap::CopyCode(Code* code) { // Allocate an object the same size as the code object. int obj_size = code->Size(); - Object* result; + MaybeObject* maybe_result; if (obj_size > MaxObjectSizeInPagedSpace()) { - result = lo_space_->AllocateRawCode(obj_size); + maybe_result = lo_space_->AllocateRawCode(obj_size); } else { - result = code_space_->AllocateRaw(obj_size); + maybe_result = code_space_->AllocateRaw(obj_size); } - if (result->IsFailure()) return result; + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // Copy code object. Address old_addr = code->address(); @@ -2545,11 +2662,16 @@ Object* Heap::CopyCode(Code* code) { } -Object* Heap::CopyCode(Code* code, Vector<byte> reloc_info) { +MaybeObject* Heap::CopyCode(Code* code, Vector<byte> reloc_info) { // Allocate ByteArray before the Code object, so that we do not risk // leaving uninitialized Code object (and breaking the heap). - Object* reloc_info_array = AllocateByteArray(reloc_info.length(), TENURED); - if (reloc_info_array->IsFailure()) return reloc_info_array; + Object* reloc_info_array; + { MaybeObject* maybe_reloc_info_array = + AllocateByteArray(reloc_info.length(), TENURED); + if (!maybe_reloc_info_array->ToObject(&reloc_info_array)) { + return maybe_reloc_info_array; + } + } int new_body_size = RoundUp(code->instruction_size(), kObjectAlignment); @@ -2560,14 +2682,15 @@ Object* Heap::CopyCode(Code* code, Vector<byte> reloc_info) { size_t relocation_offset = static_cast<size_t>(code->instruction_end() - old_addr); - Object* result; + MaybeObject* maybe_result; if (new_obj_size > MaxObjectSizeInPagedSpace()) { - result = lo_space_->AllocateRawCode(new_obj_size); + maybe_result = lo_space_->AllocateRawCode(new_obj_size); } else { - result = code_space_->AllocateRaw(new_obj_size); + maybe_result = code_space_->AllocateRaw(new_obj_size); } - if (result->IsFailure()) return result; + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // Copy code object. Address new_addr = reinterpret_cast<HeapObject*>(result)->address(); @@ -2592,16 +2715,18 @@ Object* Heap::CopyCode(Code* code, Vector<byte> reloc_info) { } -Object* Heap::Allocate(Map* map, AllocationSpace space) { +MaybeObject* Heap::Allocate(Map* map, AllocationSpace space) { ASSERT(gc_state_ == NOT_IN_GC); ASSERT(map->instance_type() != MAP_TYPE); // If allocation failures are disallowed, we may allocate in a different // space when new space is full and the object is not a large object. AllocationSpace retry_space = (space != NEW_SPACE) ? space : TargetSpaceId(map->instance_type()); - Object* result = - AllocateRaw(map->instance_size(), space, retry_space); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + AllocateRaw(map->instance_size(), space, retry_space); + if (!maybe_result->ToObject(&result)) return maybe_result; + } HeapObject::cast(result)->set_map(map); #ifdef ENABLE_LOGGING_AND_PROFILING ProducerHeapProfile::RecordJSObjectAllocation(result); @@ -2610,9 +2735,9 @@ Object* Heap::Allocate(Map* map, AllocationSpace space) { } -Object* Heap::InitializeFunction(JSFunction* function, - SharedFunctionInfo* shared, - Object* prototype) { +MaybeObject* Heap::InitializeFunction(JSFunction* function, + SharedFunctionInfo* shared, + Object* prototype) { ASSERT(!prototype->IsMap()); function->initialize_properties(); function->initialize_elements(); @@ -2625,38 +2750,44 @@ Object* Heap::InitializeFunction(JSFunction* function, } -Object* Heap::AllocateFunctionPrototype(JSFunction* function) { +MaybeObject* Heap::AllocateFunctionPrototype(JSFunction* function) { // Allocate the prototype. Make sure to use the object function // from the function's context, since the function can be from a // different context. JSFunction* object_function = function->context()->global_context()->object_function(); - Object* prototype = AllocateJSObject(object_function); - if (prototype->IsFailure()) return prototype; + Object* prototype; + { MaybeObject* maybe_prototype = AllocateJSObject(object_function); + if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; + } // When creating the prototype for the function we must set its // constructor to the function. - Object* result = - JSObject::cast(prototype)->SetProperty(constructor_symbol(), - function, - DONT_ENUM); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + JSObject::cast(prototype)->SetProperty(constructor_symbol(), + function, + DONT_ENUM); + if (!maybe_result->ToObject(&result)) return maybe_result; + } return prototype; } -Object* Heap::AllocateFunction(Map* function_map, - SharedFunctionInfo* shared, - Object* prototype, - PretenureFlag pretenure) { +MaybeObject* Heap::AllocateFunction(Map* function_map, + SharedFunctionInfo* shared, + Object* prototype, + PretenureFlag pretenure) { AllocationSpace space = (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; - Object* result = Allocate(function_map, space); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Allocate(function_map, space); + if (!maybe_result->ToObject(&result)) return maybe_result; + } return InitializeFunction(JSFunction::cast(result), shared, prototype); } -Object* Heap::AllocateArgumentsObject(Object* callee, int length) { +MaybeObject* Heap::AllocateArgumentsObject(Object* callee, int length) { // To get fast allocation and map sharing for arguments objects we // allocate them based on an arguments boilerplate. @@ -2673,9 +2804,11 @@ Object* Heap::AllocateArgumentsObject(Object* callee, int length) { ASSERT(kArgumentsObjectSize == boilerplate->map()->instance_size()); // Do the allocation. - Object* result = - AllocateRaw(kArgumentsObjectSize, NEW_SPACE, OLD_POINTER_SPACE); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + AllocateRaw(kArgumentsObjectSize, NEW_SPACE, OLD_POINTER_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Copy the content. The arguments boilerplate doesn't have any // fields that point to new space so it's safe to skip the write @@ -2713,23 +2846,27 @@ static bool HasDuplicates(DescriptorArray* descriptors) { } -Object* Heap::AllocateInitialMap(JSFunction* fun) { +MaybeObject* Heap::AllocateInitialMap(JSFunction* fun) { ASSERT(!fun->has_initial_map()); // First create a new map with the size and number of in-object properties // suggested by the function. int instance_size = fun->shared()->CalculateInstanceSize(); int in_object_properties = fun->shared()->CalculateInObjectProperties(); - Object* map_obj = Heap::AllocateMap(JS_OBJECT_TYPE, instance_size); - if (map_obj->IsFailure()) return map_obj; + Object* map_obj; + { MaybeObject* maybe_map_obj = + Heap::AllocateMap(JS_OBJECT_TYPE, instance_size); + if (!maybe_map_obj->ToObject(&map_obj)) return maybe_map_obj; + } // Fetch or allocate prototype. Object* prototype; if (fun->has_instance_prototype()) { prototype = fun->instance_prototype(); } else { - prototype = AllocateFunctionPrototype(fun); - if (prototype->IsFailure()) return prototype; + { MaybeObject* maybe_prototype = AllocateFunctionPrototype(fun); + if (!maybe_prototype->ToObject(&prototype)) return maybe_prototype; + } } Map* map = Map::cast(map_obj); map->set_inobject_properties(in_object_properties); @@ -2749,8 +2886,12 @@ Object* Heap::AllocateInitialMap(JSFunction* fun) { // Inline constructor can only handle inobject properties. fun->shared()->ForbidInlineConstructor(); } else { - Object* descriptors_obj = DescriptorArray::Allocate(count); - if (descriptors_obj->IsFailure()) return descriptors_obj; + Object* descriptors_obj; + { MaybeObject* maybe_descriptors_obj = DescriptorArray::Allocate(count); + if (!maybe_descriptors_obj->ToObject(&descriptors_obj)) { + return maybe_descriptors_obj; + } + } DescriptorArray* descriptors = DescriptorArray::cast(descriptors_obj); for (int i = 0; i < count; i++) { String* name = fun->shared()->GetThisPropertyAssignmentName(i); @@ -2811,7 +2952,7 @@ void Heap::InitializeJSObjectFromMap(JSObject* obj, } -Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) { +MaybeObject* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) { // JSFunctions should be allocated using AllocateFunction to be // properly initialized. ASSERT(map->instance_type() != JS_FUNCTION_TYPE); @@ -2827,15 +2968,19 @@ Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) { map->unused_property_fields() - map->inobject_properties(); ASSERT(prop_size >= 0); - Object* properties = AllocateFixedArray(prop_size, pretenure); - if (properties->IsFailure()) return properties; + Object* properties; + { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, pretenure); + if (!maybe_properties->ToObject(&properties)) return maybe_properties; + } // Allocate the JSObject. AllocationSpace space = (pretenure == TENURED) ? OLD_POINTER_SPACE : NEW_SPACE; if (map->instance_size() > MaxObjectSizeInPagedSpace()) space = LO_SPACE; - Object* obj = Allocate(map, space); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Allocate(map, space); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Initialize the JSObject. InitializeJSObjectFromMap(JSObject::cast(obj), @@ -2846,25 +2991,30 @@ Object* Heap::AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure) { } -Object* Heap::AllocateJSObject(JSFunction* constructor, - PretenureFlag pretenure) { +MaybeObject* Heap::AllocateJSObject(JSFunction* constructor, + PretenureFlag pretenure) { // Allocate the initial map if absent. if (!constructor->has_initial_map()) { - Object* initial_map = AllocateInitialMap(constructor); - if (initial_map->IsFailure()) return initial_map; + Object* initial_map; + { MaybeObject* maybe_initial_map = AllocateInitialMap(constructor); + if (!maybe_initial_map->ToObject(&initial_map)) return maybe_initial_map; + } constructor->set_initial_map(Map::cast(initial_map)); Map::cast(initial_map)->set_constructor(constructor); } // Allocate the object based on the constructors initial map. - Object* result = + MaybeObject* result = AllocateJSObjectFromMap(constructor->initial_map(), pretenure); +#ifdef DEBUG // Make sure result is NOT a global object if valid. - ASSERT(result->IsFailure() || !result->IsGlobalObject()); + Object* non_failure; + ASSERT(!result->ToObject(&non_failure) || !non_failure->IsGlobalObject()); +#endif return result; } -Object* Heap::AllocateGlobalObject(JSFunction* constructor) { +MaybeObject* Heap::AllocateGlobalObject(JSFunction* constructor) { ASSERT(constructor->has_initial_map()); Map* map = constructor->initial_map(); @@ -2884,10 +3034,12 @@ Object* Heap::AllocateGlobalObject(JSFunction* constructor) { int initial_size = map->instance_type() == JS_GLOBAL_OBJECT_TYPE ? 64 : 512; // Allocate a dictionary object for backing storage. - Object* obj = - StringDictionary::Allocate( - map->NumberOfDescribedProperties() * 2 + initial_size); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + StringDictionary::Allocate( + map->NumberOfDescribedProperties() * 2 + initial_size); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } StringDictionary* dictionary = StringDictionary::cast(obj); // The global object might be created from an object template with accessors. @@ -2899,23 +3051,28 @@ Object* Heap::AllocateGlobalObject(JSFunction* constructor) { PropertyDetails d = PropertyDetails(details.attributes(), CALLBACKS, details.index()); Object* value = descs->GetCallbacksObject(i); - value = Heap::AllocateJSGlobalPropertyCell(value); - if (value->IsFailure()) return value; + { MaybeObject* maybe_value = Heap::AllocateJSGlobalPropertyCell(value); + if (!maybe_value->ToObject(&value)) return maybe_value; + } - Object* result = dictionary->Add(descs->GetKey(i), value, d); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = dictionary->Add(descs->GetKey(i), value, d); + if (!maybe_result->ToObject(&result)) return maybe_result; + } dictionary = StringDictionary::cast(result); } // Allocate the global object and initialize it with the backing store. - obj = Allocate(map, OLD_POINTER_SPACE); - if (obj->IsFailure()) return obj; + { MaybeObject* maybe_obj = Allocate(map, OLD_POINTER_SPACE); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } JSObject* global = JSObject::cast(obj); InitializeJSObjectFromMap(global, dictionary, map); // Create a new map for the global object. - obj = map->CopyDropDescriptors(); - if (obj->IsFailure()) return obj; + { MaybeObject* maybe_obj = map->CopyDropDescriptors(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } Map* new_map = Map::cast(obj); // Setup the global object as a normalized object. @@ -2930,7 +3087,7 @@ Object* Heap::AllocateGlobalObject(JSFunction* constructor) { } -Object* Heap::CopyJSObject(JSObject* source) { +MaybeObject* Heap::CopyJSObject(JSObject* source) { // Never used to copy functions. If functions need to be copied we // have to be careful to clear the literals array. ASSERT(!source->IsJSFunction()); @@ -2943,8 +3100,10 @@ Object* Heap::CopyJSObject(JSObject* source) { // If we're forced to always allocate, we use the general allocation // functions which may leave us with an object in old space. if (always_allocate()) { - clone = AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE); - if (clone->IsFailure()) return clone; + { MaybeObject* maybe_clone = + AllocateRaw(object_size, NEW_SPACE, OLD_POINTER_SPACE); + if (!maybe_clone->ToObject(&clone)) return maybe_clone; + } Address clone_address = HeapObject::cast(clone)->address(); CopyBlock(clone_address, source->address(), @@ -2954,8 +3113,9 @@ Object* Heap::CopyJSObject(JSObject* source) { JSObject::kHeaderSize, (object_size - JSObject::kHeaderSize) / kPointerSize); } else { - clone = new_space_.AllocateRaw(object_size); - if (clone->IsFailure()) return clone; + { MaybeObject* maybe_clone = new_space_.AllocateRaw(object_size); + if (!maybe_clone->ToObject(&clone)) return maybe_clone; + } ASSERT(Heap::InNewSpace(clone)); // Since we know the clone is allocated in new space, we can copy // the contents without worrying about updating the write barrier. @@ -2968,16 +3128,20 @@ Object* Heap::CopyJSObject(JSObject* source) { FixedArray* properties = FixedArray::cast(source->properties()); // Update elements if necessary. if (elements->length() > 0) { - Object* elem = - (elements->map() == fixed_cow_array_map()) ? - elements : CopyFixedArray(elements); - if (elem->IsFailure()) return elem; + Object* elem; + { MaybeObject* maybe_elem = + (elements->map() == fixed_cow_array_map()) ? + elements : CopyFixedArray(elements); + if (!maybe_elem->ToObject(&elem)) return maybe_elem; + } JSObject::cast(clone)->set_elements(FixedArray::cast(elem)); } // Update properties if necessary. if (properties->length() > 0) { - Object* prop = CopyFixedArray(properties); - if (prop->IsFailure()) return prop; + Object* prop; + { MaybeObject* maybe_prop = CopyFixedArray(properties); + if (!maybe_prop->ToObject(&prop)) return maybe_prop; + } JSObject::cast(clone)->set_properties(FixedArray::cast(prop)); } // Return the new clone. @@ -2988,8 +3152,8 @@ Object* Heap::CopyJSObject(JSObject* source) { } -Object* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor, - JSGlobalProxy* object) { +MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor, + JSGlobalProxy* object) { ASSERT(constructor->has_initial_map()); Map* map = constructor->initial_map(); @@ -3000,8 +3164,10 @@ Object* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor, // Allocate the backing storage for the properties. int prop_size = map->unused_property_fields() - map->inobject_properties(); - Object* properties = AllocateFixedArray(prop_size, TENURED); - if (properties->IsFailure()) return properties; + Object* properties; + { MaybeObject* maybe_properties = AllocateFixedArray(prop_size, TENURED); + if (!maybe_properties->ToObject(&properties)) return maybe_properties; + } // Reset the map for the object. object->set_map(constructor->initial_map()); @@ -3012,10 +3178,13 @@ Object* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor, } -Object* Heap::AllocateStringFromAscii(Vector<const char> string, - PretenureFlag pretenure) { - Object* result = AllocateRawAsciiString(string.length(), pretenure); - if (result->IsFailure()) return result; +MaybeObject* Heap::AllocateStringFromAscii(Vector<const char> string, + PretenureFlag pretenure) { + Object* result; + { MaybeObject* maybe_result = + AllocateRawAsciiString(string.length(), pretenure); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Copy the characters into the new object. SeqAsciiString* string_result = SeqAsciiString::cast(result); @@ -3026,8 +3195,8 @@ Object* Heap::AllocateStringFromAscii(Vector<const char> string, } -Object* Heap::AllocateStringFromUtf8(Vector<const char> string, - PretenureFlag pretenure) { +MaybeObject* Heap::AllocateStringFromUtf8(Vector<const char> string, + PretenureFlag pretenure) { // V8 only supports characters in the Basic Multilingual Plane. const uc32 kMaxSupportedChar = 0xFFFF; // Count the number of characters in the UTF-8 string and check if @@ -3046,8 +3215,10 @@ Object* Heap::AllocateStringFromUtf8(Vector<const char> string, // since UTF8 is backwards compatible with ascii. if (is_ascii) return AllocateStringFromAscii(string, pretenure); - Object* result = AllocateRawTwoByteString(chars, pretenure); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateRawTwoByteString(chars, pretenure); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Convert and copy the characters into the new object. String* string_result = String::cast(result); @@ -3061,19 +3232,20 @@ Object* Heap::AllocateStringFromUtf8(Vector<const char> string, } -Object* Heap::AllocateStringFromTwoByte(Vector<const uc16> string, - PretenureFlag pretenure) { +MaybeObject* Heap::AllocateStringFromTwoByte(Vector<const uc16> string, + PretenureFlag pretenure) { // Check if the string is an ASCII string. int i = 0; while (i < string.length() && string[i] <= String::kMaxAsciiCharCode) i++; - Object* result; + MaybeObject* maybe_result; if (i == string.length()) { // It's an ASCII string. - result = AllocateRawAsciiString(string.length(), pretenure); + maybe_result = AllocateRawAsciiString(string.length(), pretenure); } else { // It's not an ASCII string. - result = AllocateRawTwoByteString(string.length(), pretenure); + maybe_result = AllocateRawTwoByteString(string.length(), pretenure); } - if (result->IsFailure()) return result; + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // Copy the characters into the new object, which may be either ASCII or // UTF-16. @@ -3106,9 +3278,9 @@ Map* Heap::SymbolMapForString(String* string) { } -Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, - int chars, - uint32_t hash_field) { +MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, + int chars, + uint32_t hash_field) { ASSERT(chars >= 0); // Ensure the chars matches the number of characters in the buffer. ASSERT(static_cast<unsigned>(chars) == buffer->Length()); @@ -3141,10 +3313,12 @@ Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, } // Allocate string. - Object* result = (size > MaxObjectSizeInPagedSpace()) - ? lo_space_->AllocateRaw(size) - : old_data_space_->AllocateRaw(size); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = (size > MaxObjectSizeInPagedSpace()) + ? lo_space_->AllocateRaw(size) + : old_data_space_->AllocateRaw(size); + if (!maybe_result->ToObject(&result)) return maybe_result; + } reinterpret_cast<HeapObject*>(result)->set_map(map); // Set length and hash fields of the allocated string. @@ -3162,7 +3336,7 @@ Object* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, } -Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { +MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { if (length < 0 || length > SeqAsciiString::kMaxLength) { return Failure::OutOfMemoryException(); } @@ -3184,8 +3358,10 @@ Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { } else if (space == OLD_DATA_SPACE && size > MaxObjectSizeInPagedSpace()) { space = LO_SPACE; } - Object* result = AllocateRaw(size, space, retry_space); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Partially initialize the object. HeapObject::cast(result)->set_map(ascii_string_map()); @@ -3196,7 +3372,8 @@ Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { } -Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) { +MaybeObject* Heap::AllocateRawTwoByteString(int length, + PretenureFlag pretenure) { if (length < 0 || length > SeqTwoByteString::kMaxLength) { return Failure::OutOfMemoryException(); } @@ -3216,8 +3393,10 @@ Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) { } else if (space == OLD_DATA_SPACE && size > MaxObjectSizeInPagedSpace()) { space = LO_SPACE; } - Object* result = AllocateRaw(size, space, retry_space); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = AllocateRaw(size, space, retry_space); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Partially initialize the object. HeapObject::cast(result)->set_map(string_map()); @@ -3228,10 +3407,13 @@ Object* Heap::AllocateRawTwoByteString(int length, PretenureFlag pretenure) { } -Object* Heap::AllocateEmptyFixedArray() { +MaybeObject* Heap::AllocateEmptyFixedArray() { int size = FixedArray::SizeFor(0); - Object* result = AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + AllocateRaw(size, OLD_DATA_SPACE, OLD_DATA_SPACE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Initialize the object. reinterpret_cast<FixedArray*>(result)->set_map(fixed_array_map()); reinterpret_cast<FixedArray*>(result)->set_length(0); @@ -3239,7 +3421,7 @@ Object* Heap::AllocateEmptyFixedArray() { } -Object* Heap::AllocateRawFixedArray(int length) { +MaybeObject* Heap::AllocateRawFixedArray(int length) { if (length < 0 || length > FixedArray::kMaxLength) { return Failure::OutOfMemoryException(); } @@ -3254,10 +3436,12 @@ Object* Heap::AllocateRawFixedArray(int length) { } -Object* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { +MaybeObject* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { int len = src->length(); - Object* obj = AllocateRawFixedArray(len); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = AllocateRawFixedArray(len); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } if (Heap::InNewSpace(obj)) { HeapObject* dst = HeapObject::cast(obj); dst->set_map(map); @@ -3278,24 +3462,25 @@ Object* Heap::CopyFixedArrayWithMap(FixedArray* src, Map* map) { } -Object* Heap::AllocateFixedArray(int length) { +MaybeObject* Heap::AllocateFixedArray(int length) { ASSERT(length >= 0); if (length == 0) return empty_fixed_array(); - Object* result = AllocateRawFixedArray(length); - if (!result->IsFailure()) { - // Initialize header. - FixedArray* array = reinterpret_cast<FixedArray*>(result); - array->set_map(fixed_array_map()); - array->set_length(length); - // Initialize body. - ASSERT(!Heap::InNewSpace(undefined_value())); - MemsetPointer(array->data_start(), undefined_value(), length); + Object* result; + { MaybeObject* maybe_result = AllocateRawFixedArray(length); + if (!maybe_result->ToObject(&result)) return maybe_result; } + // Initialize header. + FixedArray* array = reinterpret_cast<FixedArray*>(result); + array->set_map(fixed_array_map()); + array->set_length(length); + // Initialize body. + ASSERT(!Heap::InNewSpace(undefined_value())); + MemsetPointer(array->data_start(), undefined_value(), length); return result; } -Object* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) { +MaybeObject* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) { if (length < 0 || length > FixedArray::kMaxLength) { return Failure::OutOfMemoryException(); } @@ -3319,16 +3504,19 @@ Object* Heap::AllocateRawFixedArray(int length, PretenureFlag pretenure) { } -static Object* AllocateFixedArrayWithFiller(int length, - PretenureFlag pretenure, - Object* filler) { +MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithFiller( + int length, + PretenureFlag pretenure, + Object* filler) { ASSERT(length >= 0); ASSERT(Heap::empty_fixed_array()->IsFixedArray()); if (length == 0) return Heap::empty_fixed_array(); ASSERT(!Heap::InNewSpace(filler)); - Object* result = Heap::AllocateRawFixedArray(length, pretenure); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::AllocateRawFixedArray(length, pretenure); + if (!maybe_result->ToObject(&result)) return maybe_result; + } HeapObject::cast(result)->set_map(Heap::fixed_array_map()); FixedArray* array = FixedArray::cast(result); @@ -3338,21 +3526,24 @@ static Object* AllocateFixedArrayWithFiller(int length, } -Object* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { +MaybeObject* Heap::AllocateFixedArray(int length, PretenureFlag pretenure) { return AllocateFixedArrayWithFiller(length, pretenure, undefined_value()); } -Object* Heap::AllocateFixedArrayWithHoles(int length, PretenureFlag pretenure) { +MaybeObject* Heap::AllocateFixedArrayWithHoles(int length, + PretenureFlag pretenure) { return AllocateFixedArrayWithFiller(length, pretenure, the_hole_value()); } -Object* Heap::AllocateUninitializedFixedArray(int length) { +MaybeObject* Heap::AllocateUninitializedFixedArray(int length) { if (length == 0) return empty_fixed_array(); - Object* obj = AllocateRawFixedArray(length); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = AllocateRawFixedArray(length); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } reinterpret_cast<FixedArray*>(obj)->set_map(fixed_array_map()); FixedArray::cast(obj)->set_length(length); @@ -3360,18 +3551,23 @@ Object* Heap::AllocateUninitializedFixedArray(int length) { } -Object* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { - Object* result = Heap::AllocateFixedArray(length, pretenure); - if (result->IsFailure()) return result; +MaybeObject* Heap::AllocateHashTable(int length, PretenureFlag pretenure) { + Object* result; + { MaybeObject* maybe_result = Heap::AllocateFixedArray(length, pretenure); + if (!maybe_result->ToObject(&result)) return maybe_result; + } reinterpret_cast<HeapObject*>(result)->set_map(hash_table_map()); ASSERT(result->IsHashTable()); return result; } -Object* Heap::AllocateGlobalContext() { - Object* result = Heap::AllocateFixedArray(Context::GLOBAL_CONTEXT_SLOTS); - if (result->IsFailure()) return result; +MaybeObject* Heap::AllocateGlobalContext() { + Object* result; + { MaybeObject* maybe_result = + Heap::AllocateFixedArray(Context::GLOBAL_CONTEXT_SLOTS); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Context* context = reinterpret_cast<Context*>(result); context->set_map(global_context_map()); ASSERT(context->IsGlobalContext()); @@ -3380,10 +3576,12 @@ Object* Heap::AllocateGlobalContext() { } -Object* Heap::AllocateFunctionContext(int length, JSFunction* function) { +MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) { ASSERT(length >= Context::MIN_CONTEXT_SLOTS); - Object* result = Heap::AllocateFixedArray(length); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::AllocateFixedArray(length); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Context* context = reinterpret_cast<Context*>(result); context->set_map(context_map()); context->set_closure(function); @@ -3398,11 +3596,14 @@ Object* Heap::AllocateFunctionContext(int length, JSFunction* function) { } -Object* Heap::AllocateWithContext(Context* previous, - JSObject* extension, - bool is_catch_context) { - Object* result = Heap::AllocateFixedArray(Context::MIN_CONTEXT_SLOTS); - if (result->IsFailure()) return result; +MaybeObject* Heap::AllocateWithContext(Context* previous, + JSObject* extension, + bool is_catch_context) { + Object* result; + { MaybeObject* maybe_result = + Heap::AllocateFixedArray(Context::MIN_CONTEXT_SLOTS); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Context* context = reinterpret_cast<Context*>(result); context->set_map(is_catch_context ? catch_context_map() : context_map()); context->set_closure(previous->closure()); @@ -3417,7 +3618,7 @@ Object* Heap::AllocateWithContext(Context* previous, } -Object* Heap::AllocateStruct(InstanceType type) { +MaybeObject* Heap::AllocateStruct(InstanceType type) { Map* map; switch (type) { #define MAKE_CASE(NAME, Name, name) case NAME##_TYPE: map = name##_map(); break; @@ -3430,8 +3631,10 @@ STRUCT_LIST(MAKE_CASE) int size = map->instance_size(); AllocationSpace space = (size > MaxObjectSizeInPagedSpace()) ? LO_SPACE : OLD_POINTER_SPACE; - Object* result = Heap::Allocate(map, space); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::Allocate(map, space); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Struct::cast(result)->InitializeBody(size); return result; } @@ -3691,10 +3894,13 @@ void Heap::Verify() { #endif // DEBUG -Object* Heap::LookupSymbol(Vector<const char> string) { +MaybeObject* Heap::LookupSymbol(Vector<const char> string) { Object* symbol = NULL; - Object* new_table = symbol_table()->LookupSymbol(string, &symbol); - if (new_table->IsFailure()) return new_table; + Object* new_table; + { MaybeObject* maybe_new_table = + symbol_table()->LookupSymbol(string, &symbol); + if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; + } // Can't use set_symbol_table because SymbolTable::cast knows that // SymbolTable is a singleton and checks for identity. roots_[kSymbolTableRootIndex] = new_table; @@ -3703,11 +3909,14 @@ Object* Heap::LookupSymbol(Vector<const char> string) { } -Object* Heap::LookupSymbol(String* string) { +MaybeObject* Heap::LookupSymbol(String* string) { if (string->IsSymbol()) return string; Object* symbol = NULL; - Object* new_table = symbol_table()->LookupString(string, &symbol); - if (new_table->IsFailure()) return new_table; + Object* new_table; + { MaybeObject* maybe_new_table = + symbol_table()->LookupString(string, &symbol); + if (!maybe_new_table->ToObject(&new_table)) return maybe_new_table; + } // Can't use set_symbol_table because SymbolTable::cast knows that // SymbolTable is a singleton and checks for identity. roots_[kSymbolTableRootIndex] = new_table; diff --git a/deps/v8/src/heap.h b/deps/v8/src/heap.h index 6d32a4b6f2..8ff2f5f341 100644 --- a/deps/v8/src/heap.h +++ b/deps/v8/src/heap.h @@ -316,32 +316,33 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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); // Allocates and initializes a new global object based on a constructor. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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. // Properties and elements are copied too. // 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. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateFunctionPrototype( + MUST_USE_RESULT static MaybeObject* AllocateFunctionPrototype( JSFunction* function); // Reinitialize an JSGlobalProxy based on a constructor. The object // must have the same size as objects allocated using the // constructor. The object is reinitialized and behaves as an // object that has been freshly allocated using the constructor. - MUST_USE_RESULT static Object* ReinitializeJSGlobalProxy( + MUST_USE_RESULT static MaybeObject* ReinitializeJSGlobalProxy( JSFunction* constructor, JSGlobalProxy* global); @@ -349,31 +350,32 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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); // Allocates a heap object based on the map. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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); // Allocates a partial map for bootstrapping. - MUST_USE_RESULT static Object* AllocatePartialMap(InstanceType instance_type, - int instance_size); + MUST_USE_RESULT static MaybeObject* AllocatePartialMap( + InstanceType instance_type, + int instance_size); // 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. - MUST_USE_RESULT static Object* AllocateCodeCache(); + MUST_USE_RESULT static MaybeObject* AllocateCodeCache(); // Clear the Instanceof cache (used when a prototype changes). static void ClearInstanceofCache() { @@ -398,13 +400,13 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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, PretenureFlag pretenure = NOT_TENURED); - MUST_USE_RESULT static Object* AllocateStringFromUtf8( + MUST_USE_RESULT static MaybeObject* AllocateStringFromUtf8( Vector<const char> str, PretenureFlag pretenure = NOT_TENURED); - MUST_USE_RESULT static Object* AllocateStringFromTwoByte( + MUST_USE_RESULT static MaybeObject* AllocateStringFromTwoByte( Vector<const uc16> str, PretenureFlag pretenure = NOT_TENURED); @@ -412,15 +414,17 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this function does not perform a garbage collection. - MUST_USE_RESULT static inline Object* AllocateSymbol(Vector<const char> str, - int chars, - uint32_t hash_field); + MUST_USE_RESULT static inline MaybeObject* AllocateSymbol( + Vector<const char> str, + 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); - MUST_USE_RESULT static Object* AllocateExternalSymbol(Vector<const char> str, - int chars); + MUST_USE_RESULT static MaybeObject* AllocateExternalSymbol( + Vector<const char> str, + int chars); // 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 // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateRawAsciiString( + MUST_USE_RESULT static MaybeObject* AllocateRawAsciiString( int length, PretenureFlag pretenure = NOT_TENURED); - MUST_USE_RESULT static Object* AllocateRawTwoByteString( + MUST_USE_RESULT static MaybeObject* AllocateRawTwoByteString( int length, PretenureFlag pretenure = NOT_TENURED); @@ -441,27 +445,27 @@ class Heap : public AllStatic { // A cache is used for ascii codes. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // 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); // Allocate a byte array of the specified length // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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); // Allocate a non-tenured byte array of the specified length // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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 // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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, PretenureFlag pretenure); @@ -469,7 +473,7 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateExternalArray( + MUST_USE_RESULT static MaybeObject* AllocateExternalArray( int length, ExternalArrayType array_type, void* external_pointer, @@ -479,66 +483,71 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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 // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateFixedArray(int length, - PretenureFlag pretenure); + MUST_USE_RESULT static MaybeObject* AllocateFixedArray( + int length, + PretenureFlag pretenure); // 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. // // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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 // 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 // Failure::RetryAfterGC(requested_bytes, space) if the allocation failed. - MUST_USE_RESULT static Object* CopyFixedArrayWithMap(FixedArray* src, - Map* map); + MUST_USE_RESULT static MaybeObject* CopyFixedArrayWithMap(FixedArray* src, + Map* map); // Allocates a fixed array initialized with the hole values. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateFixedArrayWithHoles( + MUST_USE_RESULT static MaybeObject* AllocateFixedArrayWithHoles( int length, PretenureFlag pretenure = NOT_TENURED); // AllocateHashTable is identical to AllocateFixedArray except // 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); // Allocate a global (but otherwise uninitialized) context. - MUST_USE_RESULT static Object* AllocateGlobalContext(); + MUST_USE_RESULT static MaybeObject* AllocateGlobalContext(); // Allocate a function context. - MUST_USE_RESULT static Object* AllocateFunctionContext(int length, - JSFunction* closure); + MUST_USE_RESULT static MaybeObject* AllocateFunctionContext( + int length, + JSFunction* closure); // Allocate a 'with' context. - MUST_USE_RESULT static Object* AllocateWithContext(Context* previous, - JSObject* extension, - bool is_catch_context); + MUST_USE_RESULT static MaybeObject* AllocateWithContext( + Context* previous, + JSObject* extension, + bool is_catch_context); // 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. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateFunction( + MUST_USE_RESULT static MaybeObject* AllocateFunction( Map* function_map, SharedFunctionInfo* shared, Object* prototype, @@ -554,37 +563,38 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateArgumentsObject(Object* callee, - int length); + MUST_USE_RESULT static MaybeObject* AllocateArgumentsObject(Object* callee, + int length); // Same as NewNumberFromDouble, but may return a preallocated/immutable // 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); // Allocated a HeapNumber from value. - MUST_USE_RESULT static Object* AllocateHeapNumber(double value, - PretenureFlag pretenure); + MUST_USE_RESULT static MaybeObject* AllocateHeapNumber( + double value, + PretenureFlag pretenure); // 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. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateProxy( + MUST_USE_RESULT static MaybeObject* AllocateProxy( Address proxy, PretenureFlag pretenure = NOT_TENURED); @@ -592,14 +602,14 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // 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. // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateConsString(String* first, - String* second); + MUST_USE_RESULT static MaybeObject* AllocateConsString(String* first, + String* second); // Allocates a new sub string object which is a substring of an underlying // 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 // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateSubString( + MUST_USE_RESULT static MaybeObject* AllocateSubString( String* buffer, int start, int end, @@ -618,9 +628,9 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this does not perform a garbage collection. - MUST_USE_RESULT static Object* AllocateExternalStringFromAscii( + MUST_USE_RESULT static MaybeObject* AllocateExternalStringFromAscii( ExternalAsciiString::Resource* resource); - MUST_USE_RESULT static Object* AllocateExternalStringFromTwoByte( + MUST_USE_RESULT static MaybeObject* AllocateExternalStringFromTwoByte( ExternalTwoByteString::Resource* resource); // 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 // failed. // 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, AllocationSpace space, AllocationSpace retry_space); @@ -647,26 +657,27 @@ class Heap : public AllStatic { // self_reference. This allows generated code to reference its own Code // object by containing this pointer. // Please note this function does not perform a garbage collection. - MUST_USE_RESULT static Object* CreateCode(const CodeDesc& desc, - Code::Flags flags, - Handle<Object> self_reference); + MUST_USE_RESULT static MaybeObject* CreateCode(const CodeDesc& desc, + Code::Flags flags, + 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 // 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. // If not found, a new symbol is added to the table and returned. // Returns Failure::RetryAfterGC(requested_bytes, space) if allocation // failed. // Please note this function does not perform a garbage collection. - MUST_USE_RESULT static Object* LookupSymbol(Vector<const char> str); - MUST_USE_RESULT static Object* LookupAsciiSymbol(const char* str) { + MUST_USE_RESULT static MaybeObject* LookupSymbol(Vector<const char> str); + MUST_USE_RESULT static MaybeObject* LookupAsciiSymbol(const char* 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 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. // // 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. static Object* ToBoolean(bool condition) { @@ -693,20 +704,13 @@ class Heap : public AllStatic { static void GarbageCollectionPrologue(); static void GarbageCollectionEpilogue(); - enum CollectionPolicy { NORMAL, AGGRESSIVE }; - // Performs garbage collection operation. // Returns whether required_space bytes are available after the collection. - static void CollectGarbage(AllocationSpace space, - CollectionPolicy collectionPolicy = NORMAL); + static void CollectGarbage(AllocationSpace space); // Performs a full garbage collection. Force compaction if the // parameter is true. - static void CollectAllGarbage(bool force_compaction, - CollectionPolicy collectionPolicy = NORMAL); - - // Last hope GC, should try to squeeze as much as possible. - static void CollectAllAvailableGarbage(); + static void CollectAllGarbage(bool force_compaction); // Notify the heap that a context has been disposed. static int NotifyContextDisposed() { return ++contexts_disposed_; } @@ -904,10 +908,10 @@ class Heap : public AllStatic { // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // failed. // Please note this function does not perform a garbage collection. - MUST_USE_RESULT static Object* CreateSymbol(const char* str, - int length, - int hash); - MUST_USE_RESULT static Object* CreateSymbol(String* str); + MUST_USE_RESULT static MaybeObject* CreateSymbol(const char* str, + int length, + int hash); + MUST_USE_RESULT static MaybeObject* CreateSymbol(String* str); // Write barrier support for address[offset] = o. static inline void RecordWrite(Address address, int offset); @@ -979,9 +983,10 @@ class Heap : public AllStatic { static inline int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes); // Allocate uninitialized fixed array. - MUST_USE_RESULT static Object* AllocateRawFixedArray(int length); - MUST_USE_RESULT static Object* AllocateRawFixedArray(int length, - PretenureFlag pretenure); + MUST_USE_RESULT static MaybeObject* AllocateRawFixedArray(int length); + MUST_USE_RESULT static MaybeObject* AllocateRawFixedArray( + int length, + PretenureFlag pretenure); // 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. @@ -1024,7 +1029,7 @@ class Heap : public AllStatic { kRootListLength }; - MUST_USE_RESULT static Object* NumberToString( + MUST_USE_RESULT static MaybeObject* NumberToString( Object* number, bool check_number_string_cache = true); @@ -1242,22 +1247,16 @@ class Heap : public AllStatic { // Performs garbage collection static void PerformGarbageCollection(GarbageCollector collector, - GCTracer* tracer, - CollectionPolicy collectionPolicy); - - static const intptr_t kMinimumPromotionLimit = 2 * MB; - static const intptr_t kMinimumAllocationLimit = 8 * MB; - - inline static void UpdateOldSpaceLimits(); + GCTracer* tracer); // 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 // have to test the allocation space argument and (b) can reduce code size // (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. - MUST_USE_RESULT static inline Object* AllocateRawCell(); + MUST_USE_RESULT static inline MaybeObject* AllocateRawCell(); // Initializes a JSObject based on its map. static void InitializeJSObjectFromMap(JSObject* obj, @@ -1276,10 +1275,11 @@ class Heap : public AllStatic { 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. - static Object* AllocateEmptyFixedArray(); + MUST_USE_RESULT static MaybeObject* AllocateEmptyFixedArray(); // Performs a minor collection in new generation. static void Scavenge(); @@ -1318,7 +1318,7 @@ class Heap : public AllStatic { // 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. // 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, SharedFunctionInfo* shared, Object* prototype); @@ -1327,7 +1327,7 @@ class Heap : public AllStatic { // 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. static void FlushNumberStringCache(); @@ -1935,7 +1935,7 @@ class TranscendentalCache { // Returns a heap number with f(input), where f is a math function specified // 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]; if (cache == NULL) { caches_[type] = cache = new TranscendentalCache(type); @@ -1948,7 +1948,7 @@ class TranscendentalCache { static void Clear(); private: - MUST_USE_RESULT inline Object* Get(double input) { + MUST_USE_RESULT inline MaybeObject* Get(double input) { Converter c; c.dbl = input; int hash = Hash(c); @@ -1960,13 +1960,14 @@ class TranscendentalCache { return e.output; } 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(); + 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; } diff --git a/deps/v8/src/ia32/assembler-ia32.cc b/deps/v8/src/ia32/assembler-ia32.cc index e201179cd4..019f478adc 100644 --- a/deps/v8/src/ia32/assembler-ia32.cc +++ b/deps/v8/src/ia32/assembler-ia32.cc @@ -120,10 +120,15 @@ void CpuFeatures::Probe() { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Code>::null()); + + Object* code; + { MaybeObject* maybe_code = Heap::CreateCode(desc, + Code::ComputeFlags(Code::STUB), + Handle<Code>::null()); + if (!maybe_code->ToObject(&code)) return; + } if (!code->IsCode()) return; + PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG, Code::cast(code), "CpuFeatures::Probe")); typedef uint64_t (*F0)(); diff --git a/deps/v8/src/ia32/assembler-ia32.h b/deps/v8/src/ia32/assembler-ia32.h index d8051c8719..5286788fa7 100644 --- a/deps/v8/src/ia32/assembler-ia32.h +++ b/deps/v8/src/ia32/assembler-ia32.h @@ -695,7 +695,6 @@ class Assembler : public Malloced { void call(Label* L); void call(byte* entry, RelocInfo::Mode rmode); void call(const Operand& adr); - void call(const ExternalReference& target); void call(Handle<Code> code, RelocInfo::Mode rmode); // Jumps diff --git a/deps/v8/src/ia32/code-stubs-ia32.cc b/deps/v8/src/ia32/code-stubs-ia32.cc index 348bb1484b..b2b73926b9 100644 --- a/deps/v8/src/ia32/code-stubs-ia32.cc +++ b/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) { - Label empty_handle; - Label prologue; - Label promote_scheduled_exception; - __ EnterApiExitFrame(kStackSpace, kArgc); - STATIC_ASSERT(kArgc == 4); - 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); + __ PrepareCallApiFunction(kStackSpace, kArgc); + STATIC_ASSERT(kArgc == 2); + __ mov(ApiParameterOperand(0), ebx); // name. + __ mov(ApiParameterOperand(1), eax); // arguments pointer. + __ CallApiFunctionAndReturn(fun(), kArgc); } diff --git a/deps/v8/src/ia32/macro-assembler-ia32.cc b/deps/v8/src/ia32/macro-assembler-ia32.cc index a62f74b746..b72f4df0e7 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.cc +++ b/deps/v8/src/ia32/macro-assembler-ia32.cc @@ -584,6 +584,20 @@ void MacroAssembler::AllocateInNewSpace(int object_size, Register scratch, Label* gc_required, 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)); // Load address of new object into result. @@ -627,6 +641,19 @@ void MacroAssembler::AllocateInNewSpace(int header_size, Register scratch, Label* gc_required, 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)); // Load address of new object into result. @@ -655,6 +682,19 @@ void MacroAssembler::AllocateInNewSpace(Register object_size, Register scratch, Label* gc_required, 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)); // 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. - Object* result = stub->TryGetCode(); - if (!result->IsFailure()) { - call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); + Object* result; + { MaybeObject* maybe_result = stub->TryGetCode(); + if (!maybe_result->ToObject(&result)) return maybe_result; } + call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); 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. - Object* result = stub->TryGetCode(); - if (!result->IsFailure()) { - jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); + Object* result; + { MaybeObject* maybe_result = stub->TryGetCode(); + if (!maybe_result->ToObject(&result)) return maybe_result; } + jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); return result; } @@ -1000,8 +1042,8 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { } -Object* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, - int num_arguments) { +MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, + int 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, - int num_arguments) { +MaybeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f, + int num_arguments) { if (f->nargs >= 0 && f->nargs != num_arguments) { IllegalOperation(num_arguments); // 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) { - // Push the number of extensions, smi-tagged so the gc will ignore it. - ExternalReference extensions_address = - ExternalReference::handle_scope_extensions_address(); - mov(scratch, Operand::StaticVariable(extensions_address)); - SmiTag(scratch); - push(scratch); - mov(Operand::StaticVariable(extensions_address), Immediate(0)); - // Push next and limit pointers which will be wordsize aligned and - // hence automatically smi tagged. - ExternalReference next_address = - ExternalReference::handle_scope_next_address(); - push(Operand::StaticVariable(next_address)); - ExternalReference limit_address = - ExternalReference::handle_scope_limit_address(); - push(Operand::StaticVariable(limit_address)); +// 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 + + +Operand ApiParameterOperand(int index) { + return Operand(esp, (index + (kPassHandlesDirectly ? 0 : 1)) * kPointerSize); } -Object* MacroAssembler::PopHandleScopeHelper(Register saved, - Register scratch, - bool gc_allowed) { - Object* result = NULL; - ExternalReference extensions_address = - 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); +void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) { + if (kPassHandlesDirectly) { + EnterApiExitFrame(stack_space, argc); + // When handles as passed directly we don't have to allocate extra + // space for and pass an out parameter. } else { - result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); - if (result->IsFailure()) return result; + // We allocate two additional slots: return value and pointer to it. + 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) { - PopHandleScopeHelper(saved, scratch, true); -} + // Allocate HandleScope in callee-save registers. + 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) { - return PopHandleScopeHelper(saved, scratch, false); + Label empty_handle; + 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); } diff --git a/deps/v8/src/ia32/macro-assembler-ia32.h b/deps/v8/src/ia32/macro-assembler-ia32.h index fe3267c943..7b9b843939 100644 --- a/deps/v8/src/ia32/macro-assembler-ia32.h +++ b/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 // the code if necessary. Do not perform a GC but instead return a retry // 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. 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 // generate the code if necessary. Do not perform a GC but instead return // 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. void StubReturn(int argc); @@ -440,13 +440,15 @@ class MacroAssembler: public Assembler { // Call a runtime function, returning the CodeStub object called. // Try to generate the stub code if necessary. Do not perform a GC // 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. void CallRuntime(Runtime::FunctionId id, int num_arguments); // 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. void CallExternalReference(ExternalReference ref, int num_arguments); @@ -480,15 +482,16 @@ class MacroAssembler: public Assembler { void CallCFunction(ExternalReference 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 - // 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); + // Tail call an API function (jump). Allocates HandleScope, extracts + // returned value from handle and propagates exceptions. + // Clobbers ebx, esi, edi and caller-save registers. + void CallApiFunctionAndReturn(ApiFunction* function, int argc); // Jump to a runtime routine. void JumpToExternalReference(const ExternalReference& ext); @@ -596,9 +599,9 @@ class MacroAssembler: public Assembler { // Helper for PopHandleScope. Allowed to perform a GC and returns // NULL if gc_allowed. Does not perform a GC if !gc_allowed, and // possibly returns a failure object indicating an allocation failure. - Object* PopHandleScopeHelper(Register saved, - Register scratch, - bool gc_allowed); + MUST_USE_RESULT MaybeObject* PopHandleScopeHelper(Register saved, + Register scratch, + bool gc_allowed); }; @@ -639,6 +642,9 @@ static inline Operand FieldOperand(Register object, return Operand(object, index, scale, offset - kHeapObjectTag); } +// Generates an Operand for saving parameters after PrepareCallApiFunction. +Operand ApiParameterOperand(int index); + #ifdef GENERATED_CODE_COVERAGE extern void LogGeneratedCodeCoverage(const char* file_line); diff --git a/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc b/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc index e2853e88c2..d435a70775 100644 --- a/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc +++ b/deps/v8/src/ia32/regexp-macro-assembler-ia32.cc @@ -1067,7 +1067,7 @@ int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address, ASSERT(*return_address <= 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 int delta = *code_handle - re_code; diff --git a/deps/v8/src/ia32/simulator-ia32.h b/deps/v8/src/ia32/simulator-ia32.h index 94ef7bff97..88d0b6187f 100644 --- a/deps/v8/src/ia32/simulator-ia32.h +++ b/deps/v8/src/ia32/simulator-ia32.h @@ -30,10 +30,21 @@ #include "allocation.h" +namespace v8 { +namespace internal { + // Since there is no simulator for the ia32 architecture the only thing we can // do is to call the entry directly. #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 // 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() { } }; -// Call the generated regexp code directly. The entry function pointer should -// 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) +} } // namespace v8::internal #endif // V8_IA32_SIMULATOR_IA32_H_ diff --git a/deps/v8/src/ia32/stub-cache-ia32.cc b/deps/v8/src/ia32/stub-cache-ia32.cc index bb0a46cd8b..90dabed0e5 100644 --- a/deps/v8/src/ia32/stub-cache-ia32.cc +++ b/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 // the property cell at compilation time if no cell exists for the // property. -static Object* GenerateCheckPropertyCell(MacroAssembler* masm, - GlobalObject* global, - String* name, - Register scratch, - Label* miss) { - Object* probe = global->EnsurePropertyCell(name); - if (probe->IsFailure()) return probe; +MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( + MacroAssembler* masm, + GlobalObject* global, + String* name, + Register scratch, + Label* miss) { + Object* probe; + { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); ASSERT(cell->value()->IsTheHole()); __ 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 // from object to (but not including) holder. -static Object* GenerateCheckPropertyCells(MacroAssembler* masm, - JSObject* object, - JSObject* holder, - String* name, - Register scratch, - Label* miss) { +MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCells( + MacroAssembler* masm, + JSObject* object, + JSObject* holder, + String* name, + Register scratch, + Label* miss) { JSObject* current = object; while (current != holder) { if (current->IsGlobalObject()) { - Object* cell = GenerateCheckPropertyCell(masm, - GlobalObject::cast(current), - name, - scratch, - miss); - if (cell->IsFailure()) { - return cell; - } + // Returns a cell or a failure. + MaybeObject* result = GenerateCheckPropertyCell( + masm, + GlobalObject::cast(current), + name, + scratch, + miss); + if (result->IsFailure()) return result; } ASSERT(current->IsJSObject()); current = JSObject::cast(current->GetPrototype()); @@ -892,13 +896,13 @@ Register StubCompiler::CheckPrototypes(JSObject* object, !current->IsJSGlobalObject() && !current->IsJSGlobalProxy()) { if (!name->IsSymbol()) { - Object* lookup_result = Heap::LookupSymbol(name); - if (lookup_result->IsFailure()) { + MaybeObject* maybe_lookup_result = Heap::LookupSymbol(name); + Object* lookup_result = NULL; // Initialization to please compiler. + if (!maybe_lookup_result->ToObject(&lookup_result)) { set_failure(Failure::cast(lookup_result)); return reg; - } else { - name = String::cast(lookup_result); } + name = String::cast(lookup_result); } ASSERT(current->property_dictionary()->FindEntry(name) == StringDictionary::kNotFound); @@ -975,12 +979,12 @@ Register StubCompiler::CheckPrototypes(JSObject* object, // 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 // property cell for the property is still empty. - Object* result = GenerateCheckPropertyCells(masm(), - object, - holder, - name, - scratch1, - miss); + MaybeObject* result = GenerateCheckPropertyCells(masm(), + object, + holder, + name, + scratch1, + miss); if (result->IsFailure()) set_failure(Failure::cast(result)); // Return the register containing the holder. @@ -1035,7 +1039,6 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, Handle<AccessorInfo> callback_handle(callback); __ EnterInternalFrame(); - __ PushHandleScope(scratch2); // Push the stack address where the list of arguments ends. __ mov(scratch2, esp); __ 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 // garbage collection but instead return the allocation failure // object. - Object* result = masm()->TryCallStub(&stub); - if (result->IsFailure()) { - *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; + Object* result = NULL; // Initialization to please compiler. + { MaybeObject* try_call_result = masm()->TryCallStub(&stub); + if (!try_call_result->ToObject(&result)) { + *failure = Failure::cast(result); + return false; + } } __ LeaveInternalFrame(); @@ -1314,18 +1308,22 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, } -Object* CallStubCompiler::GenerateMissBranch() { - Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); - if (obj->IsFailure()) return obj; +MaybeObject* CallStubCompiler::GenerateMissBranch() { + Object* 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); return obj; } -Object* CallStubCompiler::CompileCallField(JSObject* object, - JSObject* holder, - int index, - String* name) { +MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( + JSObject* object, + JSObject* holder, + int index, + String* name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -1369,19 +1367,21 @@ Object* CallStubCompiler::CompileCallField(JSObject* object, // Handle call cache miss. __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(FIELD, name); } -Object* CallStubCompiler::CompileArrayPushCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -1465,6 +1465,10 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, __ ret((argc + 1) * kPointerSize); __ bind(&attempt_to_grow_elements); + if (!FLAG_inline_new) { + __ jmp(&call_builtin); + } + ExternalReference new_space_allocation_top = ExternalReference::new_space_allocation_top_address(); ExternalReference new_space_allocation_limit = @@ -1515,19 +1519,21 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, } __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileArrayPopCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -1596,15 +1602,17 @@ Object* CallStubCompiler::CompileArrayPopCall(Object* object, 1); __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileStringCharCodeAtCall( +MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( Object* object, JSObject* holder, JSGlobalPropertyCell* cell, @@ -1666,19 +1674,22 @@ Object* CallStubCompiler::CompileStringCharCodeAtCall( __ ret((argc + 1) * kPointerSize); __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileStringCharAtCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileStringCharAtCall( + Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- ecx : function name // -- esp[0] : return address @@ -1738,15 +1749,17 @@ Object* CallStubCompiler::CompileStringCharAtCall(Object* object, __ ret((argc + 1) * kPointerSize); __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileStringFromCharCodeCall( +MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( Object* object, JSObject* holder, JSGlobalPropertyCell* cell, @@ -1811,19 +1824,21 @@ Object* CallStubCompiler::CompileStringFromCharCodeCall( __ bind(&miss); // ecx: function name. - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } -Object* CallStubCompiler::CompileMathFloorCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -1936,19 +1951,21 @@ Object* CallStubCompiler::CompileMathFloorCall(Object* object, __ bind(&miss); // ecx: function name. - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } -Object* CallStubCompiler::CompileMathAbsCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -2039,19 +2056,21 @@ Object* CallStubCompiler::CompileMathAbsCall(Object* object, __ bind(&miss); // ecx: function name. - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } -Object* CallStubCompiler::CompileCallConstant(Object* object, - JSObject* holder, - JSFunction* function, - String* name, - CheckType check) { +MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, + JSObject* holder, + JSFunction* function, + String* name, + CheckType check) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -2063,8 +2082,10 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, SharedFunctionInfo* function_info = function->shared(); if (function_info->HasCustomCallGenerator()) { const int id = function_info->custom_call_generator_id(); - Object* result = CompileCustomCall( + MaybeObject* maybe_result = CompileCustomCall( id, object, holder, NULL, function, name); + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // undefined means bail out to regular compiler. if (!result->IsUndefined()) return result; } @@ -2192,17 +2213,19 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, FreeSpaceForFastApiCall(masm(), eax); } __ bind(&miss_in_smi_check); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, - JSObject* holder, - String* name) { +MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, + JSObject* holder, + String* name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -2257,19 +2280,21 @@ Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, // Handle load cache miss. __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(INTERCEPTOR, name); } -Object* CallStubCompiler::CompileCallGlobal(JSObject* object, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- ecx : name // -- esp[0] : return address @@ -2281,8 +2306,10 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, SharedFunctionInfo* function_info = function->shared(); if (function_info->HasCustomCallGenerator()) { const int id = function_info->custom_call_generator_id(); - Object* result = CompileCustomCall( + MaybeObject* maybe_result = CompileCustomCall( id, object, holder, cell, function, name); + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // undefined means bail out to regular compiler. if (!result->IsUndefined()) return result; } @@ -2318,18 +2345,20 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, // Handle call cache miss. __ bind(&miss); __ IncrementCounter(&Counters::call_global_inline_miss, 1); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(NORMAL, name); } -Object* StoreStubCompiler::CompileStoreField(JSObject* object, - int index, - Map* transition, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, + int index, + Map* transition, + String* name) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : name @@ -2357,9 +2386,9 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object, } -Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, - AccessorInfo* callback, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, + AccessorInfo* callback, + String* name) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : name @@ -2408,8 +2437,8 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, } -Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, + String* name) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : name @@ -2457,9 +2486,9 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, } -Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, - JSGlobalPropertyCell* cell, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, + JSGlobalPropertyCell* cell, + String* name) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : name @@ -2492,10 +2521,10 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, } -Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, - int index, - Map* transition, - String* name) { +MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, + int index, + Map* transition, + String* name) { // ----------- S t a t e ------------- // -- eax : value // -- ecx : key @@ -2529,9 +2558,9 @@ Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, } -Object* LoadStubCompiler::CompileLoadNonexistent(String* name, - JSObject* object, - JSObject* last) { +MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, + JSObject* object, + JSObject* last) { // ----------- S t a t e ------------- // -- eax : receiver // -- ecx : name @@ -2553,11 +2582,11 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name, // If the last object in the prototype chain is a global object, // check that the global property cell is empty. if (last->IsGlobalObject()) { - Object* cell = GenerateCheckPropertyCell(masm(), - GlobalObject::cast(last), - name, - edx, - &miss); + MaybeObject* cell = GenerateCheckPropertyCell(masm(), + GlobalObject::cast(last), + name, + edx, + &miss); if (cell->IsFailure()) { miss.Unuse(); return cell; @@ -2577,10 +2606,10 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name, } -Object* LoadStubCompiler::CompileLoadField(JSObject* object, - JSObject* holder, - int index, - String* name) { +MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, + JSObject* holder, + int index, + String* name) { // ----------- S t a t e ------------- // -- eax : receiver // -- ecx : name @@ -2597,10 +2626,10 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object, } -Object* LoadStubCompiler::CompileLoadCallback(String* name, - JSObject* object, - JSObject* holder, - AccessorInfo* callback) { +MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, + JSObject* object, + JSObject* holder, + AccessorInfo* callback) { // ----------- S t a t e ------------- // -- eax : receiver // -- ecx : name @@ -2624,10 +2653,10 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name, } -Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, - JSObject* holder, - Object* value, - String* name) { +MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, + JSObject* holder, + Object* value, + String* name) { // ----------- S t a t e ------------- // -- eax : receiver // -- ecx : name @@ -2644,9 +2673,9 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, } -Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, - JSObject* holder, - String* name) { +MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, + JSObject* holder, + String* name) { // ----------- S t a t e ------------- // -- eax : receiver // -- ecx : name @@ -2678,11 +2707,11 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, } -Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - String* name, - bool is_dont_delete) { +MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + String* name, + bool is_dont_delete) { // ----------- S t a t e ------------- // -- eax : receiver // -- ecx : name @@ -2727,10 +2756,10 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, } -Object* KeyedLoadStubCompiler::CompileLoadField(String* name, - JSObject* receiver, - JSObject* holder, - int index) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, + JSObject* receiver, + JSObject* holder, + int index) { // ----------- S t a t e ------------- // -- eax : key // -- edx : receiver @@ -2755,10 +2784,11 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name, } -Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, - JSObject* receiver, - JSObject* holder, - AccessorInfo* callback) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( + String* name, + JSObject* receiver, + JSObject* holder, + AccessorInfo* callback) { // ----------- S t a t e ------------- // -- eax : key // -- edx : receiver @@ -2790,10 +2820,10 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, } -Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, - JSObject* receiver, - JSObject* holder, - Object* value) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, + JSObject* receiver, + JSObject* holder, + Object* value) { // ----------- S t a t e ------------- // -- eax : key // -- edx : receiver @@ -2818,9 +2848,9 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, } -Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, - JSObject* holder, - String* name) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, + JSObject* holder, + String* name) { // ----------- S t a t e ------------- // -- eax : key // -- edx : receiver @@ -2855,9 +2885,7 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, } - - -Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { // ----------- S t a t e ------------- // -- eax : key // -- 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 ------------- // -- eax : key // -- 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 ------------- // -- eax : key // -- edx : receiver @@ -2931,7 +2959,7 @@ Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { // Specialized stub for constructing objects from functions which only have only // simple assignments of the form this.x = ...; in their body. -Object* ConstructStubCompiler::CompileConstructStub( +MaybeObject* ConstructStubCompiler::CompileConstructStub( SharedFunctionInfo* shared) { // ----------- S t a t e ------------- // -- eax : argc diff --git a/deps/v8/src/ic.cc b/deps/v8/src/ic.cc index adf365af0f..58acebcc5d 100644 --- a/deps/v8/src/ic.cc +++ b/deps/v8/src/ic.cc @@ -476,9 +476,9 @@ void CallICBase::ReceiverToObject(Handle<Object> object) { } -Object* CallICBase::LoadFunction(State state, - Handle<Object> object, - Handle<String> name) { +MaybeObject* CallICBase::LoadFunction(State state, + Handle<Object> object, + Handle<String> name) { // If the object is undefined or null it's illegal to try to get any // of its properties; throw a TypeError in that case. if (object->IsUndefined() || object->IsNull()) { @@ -493,7 +493,11 @@ Object* CallICBase::LoadFunction(State state, // the element if so. uint32_t 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; // Try to find a suitable function delegate for the object at hand. @@ -523,8 +527,11 @@ Object* CallICBase::LoadFunction(State state, // Get the property. PropertyAttributes attr; - Object* result = object->GetProperty(*object, &lookup, *name, &attr); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + object->GetProperty(*object, &lookup, *name, &attr); + if (!maybe_result->ToObject(&result)) return maybe_result; + } if (lookup.type() == INTERCEPTOR) { // If the object does not have the requested property, check which // 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. result = TryCallAsFunction(result); - return result->IsJSFunction() ? - result : TypeError("property_not_function", object, name); + MaybeObject* answer = result; + 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. int argc = target()->arguments_count(); InLoopFlag in_loop = target()->ic_in_loop(); - Object* code = NULL; - + MaybeObject* maybe_code = NULL; + Object* code; if (state == UNINITIALIZED) { // This is the first time we execute this inline cache. // Set the target to the pre monomorphic stub to delay // setting the monomorphic state. - code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); + maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); } else if (state == MONOMORPHIC) { - code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); + maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); } else { // Compute monomorphic stub. switch (lookup->type()) { case FIELD: { int index = lookup->GetFieldIndex(); - code = StubCache::ComputeCallField(argc, - in_loop, - kind_, - *name, - *object, - lookup->holder(), - index); + maybe_code = StubCache::ComputeCallField(argc, + in_loop, + kind_, + *name, + *object, + lookup->holder(), + index); break; } case CONSTANT_FUNCTION: { @@ -606,13 +616,13 @@ void CallICBase::UpdateCaches(LookupResult* lookup, // call; used for rewriting to monomorphic state and making sure // that the code stub is in the stub cache. JSFunction* function = lookup->GetConstantFunction(); - code = StubCache::ComputeCallConstant(argc, - in_loop, - kind_, - *name, - *object, - lookup->holder(), - function); + maybe_code = StubCache::ComputeCallConstant(argc, + in_loop, + kind_, + *name, + *object, + lookup->holder(), + function); break; } case NORMAL: { @@ -625,35 +635,35 @@ void CallICBase::UpdateCaches(LookupResult* lookup, JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); if (!cell->value()->IsJSFunction()) return; JSFunction* function = JSFunction::cast(cell->value()); - code = StubCache::ComputeCallGlobal(argc, - in_loop, - kind_, - *name, - *receiver, - global, - cell, - function); + maybe_code = StubCache::ComputeCallGlobal(argc, + in_loop, + kind_, + *name, + *receiver, + global, + cell, + function); } else { // There is only one shared stub for calling normalized // properties. It does not traverse the prototype chain, so the // property must be found in the receiver for the stub to be // applicable. if (lookup->holder() != *receiver) return; - code = StubCache::ComputeCallNormal(argc, - in_loop, - kind_, - *name, - *receiver); + maybe_code = StubCache::ComputeCallNormal(argc, + in_loop, + kind_, + *name, + *receiver); } break; } case INTERCEPTOR: { ASSERT(HasInterceptorGetter(lookup->holder())); - code = StubCache::ComputeCallInterceptor(argc, - kind_, - *name, - *object, - lookup->holder()); + maybe_code = StubCache::ComputeCallInterceptor(argc, + kind_, + *name, + *object, + lookup->holder()); break; } default: @@ -663,7 +673,7 @@ void CallICBase::UpdateCaches(LookupResult* lookup, // If we're unable to compute the stub (not enough memory left), we // 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. if (state == UNINITIALIZED || @@ -688,9 +698,9 @@ void CallICBase::UpdateCaches(LookupResult* lookup, } -Object* KeyedCallIC::LoadFunction(State state, - Handle<Object> object, - Handle<Object> key) { +MaybeObject* KeyedCallIC::LoadFunction(State state, + Handle<Object> object, + Handle<Object> key) { if (key->IsSymbol()) { 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()) { int argc = target()->arguments_count(); InLoopFlag in_loop = target()->ic_in_loop(); - Object* code = StubCache::ComputeCallMegamorphic( + MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic( argc, in_loop, Code::KEYED_CALL_IC); - if (!code->IsFailure()) { + Object* code; + if (maybe_code->ToObject(&code)) { set_target(Code::cast(code)); #ifdef DEBUG TraceIC( @@ -716,11 +727,17 @@ Object* KeyedCallIC::LoadFunction(State state, #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; result = TryCallAsFunction(result); - return result->IsJSFunction() ? - result : TypeError("property_not_function", object, key); + MaybeObject* answer = result; + if (!result->IsJSFunction()) { + answer = TypeError("property_not_function", object, key); + } + return answer; } @@ -732,7 +749,9 @@ Object* KeyedCallIC::LoadFunction(State state, #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 // of its properties; throw a TypeError in that case. if (object->IsUndefined() || object->IsNull()) { @@ -874,8 +893,11 @@ Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { PropertyAttributes attr; if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { // Get the property. - Object* result = object->GetProperty(*object, &lookup, *name, &attr); - if (result->IsFailure()) return result; + Object* 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 // exception. if (attr == ABSENT && IsContextual(object)) { @@ -904,28 +926,29 @@ void LoadIC::UpdateCaches(LookupResult* lookup, if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; // Compute the code stub for this load. - Object* code = NULL; + MaybeObject* maybe_code = NULL; + Object* code; if (state == UNINITIALIZED) { // This is the first time we execute this inline cache. // Set the target to the pre monomorphic stub to delay // setting the monomorphic state. - code = pre_monomorphic_stub(); + maybe_code = pre_monomorphic_stub(); } else if (!lookup->IsProperty()) { // Nonexistent property. The result is undefined. - code = StubCache::ComputeLoadNonexistent(*name, *receiver); + maybe_code = StubCache::ComputeLoadNonexistent(*name, *receiver); } else { // Compute monomorphic stub. switch (lookup->type()) { case FIELD: { - code = StubCache::ComputeLoadField(*name, *receiver, - lookup->holder(), - lookup->GetFieldIndex()); + maybe_code = StubCache::ComputeLoadField(*name, *receiver, + lookup->holder(), + lookup->GetFieldIndex()); break; } case CONSTANT_FUNCTION: { Object* constant = lookup->GetConstantFunction(); - code = StubCache::ComputeLoadConstant(*name, *receiver, - lookup->holder(), constant); + maybe_code = StubCache::ComputeLoadConstant(*name, *receiver, + lookup->holder(), constant); break; } case NORMAL: { @@ -933,18 +956,18 @@ void LoadIC::UpdateCaches(LookupResult* lookup, GlobalObject* global = GlobalObject::cast(lookup->holder()); JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); - code = StubCache::ComputeLoadGlobal(*name, - *receiver, - global, - cell, - lookup->IsDontDelete()); + maybe_code = StubCache::ComputeLoadGlobal(*name, + *receiver, + global, + cell, + lookup->IsDontDelete()); } else { // There is only one shared stub for loading normalized // properties. It does not traverse the prototype chain, so the // property must be found in the receiver for the stub to be // applicable. if (lookup->holder() != *receiver) return; - code = StubCache::ComputeLoadNormal(); + maybe_code = StubCache::ComputeLoadNormal(); } break; } @@ -953,14 +976,14 @@ void LoadIC::UpdateCaches(LookupResult* lookup, AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); if (v8::ToCData<Address>(callback->getter()) == 0) return; - code = StubCache::ComputeLoadCallback(*name, *receiver, - lookup->holder(), callback); + maybe_code = StubCache::ComputeLoadCallback(*name, *receiver, + lookup->holder(), callback); break; } case INTERCEPTOR: { ASSERT(HasInterceptorGetter(lookup->holder())); - code = StubCache::ComputeLoadInterceptor(*name, *receiver, - lookup->holder()); + maybe_code = StubCache::ComputeLoadInterceptor(*name, *receiver, + lookup->holder()); break; } default: @@ -970,7 +993,7 @@ void LoadIC::UpdateCaches(LookupResult* lookup, // If we're unable to compute the stub (not enough memory left), we // 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. if (state == UNINITIALIZED || state == PREMONOMORPHIC || @@ -993,9 +1016,9 @@ void LoadIC::UpdateCaches(LookupResult* lookup, } -Object* KeyedLoadIC::Load(State state, - Handle<Object> object, - Handle<Object> key) { +MaybeObject* KeyedLoadIC::Load(State state, + Handle<Object> object, + Handle<Object> key) { if (key->IsSymbol()) { Handle<String> name = Handle<String>::cast(key); @@ -1010,8 +1033,10 @@ Object* KeyedLoadIC::Load(State state, if (object->IsString() && name->Equals(Heap::length_symbol())) { Handle<String> string = Handle<String>::cast(object); Object* code = NULL; - code = StubCache::ComputeKeyedLoadStringLength(*name, *string); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + StubCache::ComputeKeyedLoadStringLength(*name, *string); + if (!maybe_code->ToObject(&code)) return maybe_code; + } set_target(Code::cast(code)); #ifdef DEBUG TraceIC("KeyedLoadIC", name, state, target()); @@ -1022,8 +1047,11 @@ Object* KeyedLoadIC::Load(State state, // Use specialized code for getting the length of arrays. if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { Handle<JSArray> array = Handle<JSArray>::cast(object); - Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array); - if (code->IsFailure()) return code; + Object* code; + { MaybeObject* maybe_code = + StubCache::ComputeKeyedLoadArrayLength(*name, *array); + if (!maybe_code->ToObject(&code)) return maybe_code; + } set_target(Code::cast(code)); #ifdef DEBUG TraceIC("KeyedLoadIC", name, state, target()); @@ -1035,9 +1063,11 @@ Object* KeyedLoadIC::Load(State state, if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && JSFunction::cast(*object)->should_have_prototype()) { Handle<JSFunction> function = Handle<JSFunction>::cast(object); - Object* code = - StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); - if (code->IsFailure()) return code; + Object* code; + { MaybeObject* maybe_code = + StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); + if (!maybe_code->ToObject(&code)) return maybe_code; + } set_target(Code::cast(code)); #ifdef DEBUG TraceIC("KeyedLoadIC", name, state, target()); @@ -1074,8 +1104,11 @@ Object* KeyedLoadIC::Load(State state, PropertyAttributes attr; if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { // Get the property. - Object* result = object->GetProperty(*object, &lookup, *name, &attr); - if (result->IsFailure()) return result; + Object* 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 // exception. if (attr == ABSENT && IsContextual(object)) { @@ -1133,26 +1166,29 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; // Compute the code stub for this load. - Object* code = NULL; + MaybeObject* maybe_code = NULL; + Object* code; if (state == UNINITIALIZED) { // This is the first time we execute this inline cache. // Set the target to the pre monomorphic stub to delay // setting the monomorphic state. - code = pre_monomorphic_stub(); + maybe_code = pre_monomorphic_stub(); } else { // Compute a monomorphic stub. switch (lookup->type()) { case FIELD: { - code = StubCache::ComputeKeyedLoadField(*name, *receiver, - lookup->holder(), - lookup->GetFieldIndex()); + maybe_code = StubCache::ComputeKeyedLoadField(*name, *receiver, + lookup->holder(), + lookup->GetFieldIndex()); break; } case CONSTANT_FUNCTION: { Object* constant = lookup->GetConstantFunction(); - code = StubCache::ComputeKeyedLoadConstant(*name, *receiver, - lookup->holder(), constant); + maybe_code = StubCache::ComputeKeyedLoadConstant(*name, + *receiver, + lookup->holder(), + constant); break; } case CALLBACKS: { @@ -1160,20 +1196,22 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); if (v8::ToCData<Address>(callback->getter()) == 0) return; - code = StubCache::ComputeKeyedLoadCallback(*name, *receiver, - lookup->holder(), callback); + maybe_code = StubCache::ComputeKeyedLoadCallback(*name, + *receiver, + lookup->holder(), + callback); break; } case INTERCEPTOR: { ASSERT(HasInterceptorGetter(lookup->holder())); - code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver, - lookup->holder()); + maybe_code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver, + lookup->holder()); break; } default: { // Always rewrite to the generic case so that we do not // repeatedly try to rewrite. - code = generic_stub(); + maybe_code = generic_stub(); 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 // 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 // sure to always rewrite from monomorphic to megamorphic. @@ -1229,10 +1267,10 @@ static bool LookupForWrite(JSObject* object, } -Object* StoreIC::Store(State state, - Handle<Object> object, - Handle<String> name, - Handle<Object> value) { +MaybeObject* StoreIC::Store(State state, + Handle<Object> object, + Handle<String> name, + Handle<Object> value) { // If the object is undefined or null it's illegal to try to set any // properties on it; throw a TypeError in that case. 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 // monomorphic state and making sure that the code stub is in the // stub cache. + MaybeObject* maybe_code = NULL; Object* code = NULL; switch (type) { case FIELD: { - code = StubCache::ComputeStoreField(*name, *receiver, - lookup->GetFieldIndex()); + maybe_code = StubCache::ComputeStoreField(*name, *receiver, + lookup->GetFieldIndex()); break; } case MAP_TRANSITION: { @@ -1358,7 +1397,8 @@ void StoreIC::UpdateCaches(LookupResult* lookup, ASSERT(type == MAP_TRANSITION); Handle<Map> transition(lookup->GetTransitionMap()); int index = transition->PropertyIndexFor(*name); - code = StubCache::ComputeStoreField(*name, *receiver, index, *transition); + maybe_code = StubCache::ComputeStoreField(*name, *receiver, + index, *transition); break; } case NORMAL: { @@ -1369,10 +1409,10 @@ void StoreIC::UpdateCaches(LookupResult* lookup, Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); - code = StubCache::ComputeStoreGlobal(*name, *global, cell); + maybe_code = StubCache::ComputeStoreGlobal(*name, *global, cell); } else { if (lookup->holder() != *receiver) return; - code = StubCache::ComputeStoreNormal(); + maybe_code = StubCache::ComputeStoreNormal(); } break; } @@ -1380,12 +1420,12 @@ void StoreIC::UpdateCaches(LookupResult* lookup, if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); if (v8::ToCData<Address>(callback->setter()) == 0) return; - code = StubCache::ComputeStoreCallback(*name, *receiver, callback); + maybe_code = StubCache::ComputeStoreCallback(*name, *receiver, callback); break; } case INTERCEPTOR: { ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); - code = StubCache::ComputeStoreInterceptor(*name, *receiver); + maybe_code = StubCache::ComputeStoreInterceptor(*name, *receiver); break; } default: @@ -1394,7 +1434,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup, // If we're unable to compute the stub (not enough memory left), we // 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. if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { @@ -1413,10 +1453,10 @@ void StoreIC::UpdateCaches(LookupResult* lookup, } -Object* KeyedStoreIC::Store(State state, - Handle<Object> object, - Handle<Object> key, - Handle<Object> value) { +MaybeObject* KeyedStoreIC::Store(State state, + Handle<Object> object, + Handle<Object> key, + Handle<Object> value) { if (key->IsSymbol()) { 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 // monomorphic state and making sure that the code stub is in the // stub cache. + MaybeObject* maybe_code = NULL; Object* code = NULL; switch (type) { case FIELD: { - code = StubCache::ComputeKeyedStoreField(*name, *receiver, - lookup->GetFieldIndex()); + maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver, + lookup->GetFieldIndex()); break; } case MAP_TRANSITION: { @@ -1510,8 +1551,8 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup, ASSERT(type == MAP_TRANSITION); Handle<Map> transition(lookup->GetTransitionMap()); int index = transition->PropertyIndexFor(*name); - code = StubCache::ComputeKeyedStoreField(*name, *receiver, - index, *transition); + maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver, + index, *transition); break; } // fall through. @@ -1519,14 +1560,14 @@ void KeyedStoreIC::UpdateCaches(LookupResult* lookup, default: { // Always rewrite to the generic case so that we do not // repeatedly try to rewrite. - code = generic_stub(); + maybe_code = generic_stub(); break; } } // If we're unable to compute the stub (not enough memory left), we // 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 // sure to always rewrite from monomorphic to megamorphic. @@ -1562,13 +1603,16 @@ static JSFunction* CompileFunction(JSFunction* function, // Used from ic-<arch>.cc. -Object* CallIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 2); CallIC ic; IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); - Object* result = - ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); + Object* result; + { 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 // 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. -Object* KeyedCallIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 2); KeyedCallIC ic; 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)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { return result; @@ -1601,7 +1648,7 @@ Object* KeyedCallIC_Miss(Arguments args) { // Used from ic-<arch>.cc. -Object* LoadIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* LoadIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 2); LoadIC ic; @@ -1611,7 +1658,7 @@ Object* LoadIC_Miss(Arguments args) { // Used from ic-<arch>.cc -Object* KeyedLoadIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 2); KeyedLoadIC ic; @@ -1621,7 +1668,7 @@ Object* KeyedLoadIC_Miss(Arguments args) { // Used from ic-<arch>.cc. -Object* StoreIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 3); 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; ASSERT(args.length() == 2); JSObject* receiver = JSObject::cast(args[0]); Object* len = args[1]; - Object* result = receiver->SetElementsLength(len); - if (result->IsFailure()) return result; + // The generated code should filter out non-Smis before we get here. + ASSERT(len->IsSmi()); + + Object* result; + { MaybeObject* maybe_result = receiver->SetElementsLength(len); + if (!maybe_result->ToObject(&result)) return maybe_result; + } return len; } @@ -1647,7 +1699,7 @@ Object* StoreIC_ArrayLength(Arguments args) { // Extend storage is called in a store inline cache when // it is necessary to extend the properties array of a // JSObject. -Object* SharedStoreIC_ExtendStorage(Arguments args) { +MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 3); @@ -1664,8 +1716,10 @@ Object* SharedStoreIC_ExtendStorage(Arguments args) { FixedArray* old_storage = object->properties(); int new_unused = transition->unused_property_fields(); int new_size = old_storage->length() + new_unused + 1; - Object* result = old_storage->CopySize(new_size); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = old_storage->CopySize(new_size); + if (!maybe_result->ToObject(&result)) return maybe_result; + } FixedArray* new_storage = FixedArray::cast(result); new_storage->set(old_storage->length(), value); @@ -1679,7 +1733,7 @@ Object* SharedStoreIC_ExtendStorage(Arguments args) { // Used from ic-<arch>.cc. -Object* KeyedStoreIC_Miss(Arguments args) { +MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 3); KeyedStoreIC ic; @@ -1744,7 +1798,7 @@ BinaryOpIC::TypeInfo BinaryOpIC::GetTypeInfo(Object* left, 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); Handle<Object> left = args.at<Object>(0); diff --git a/deps/v8/src/ic.h b/deps/v8/src/ic.h index 437e45a935..7b8b1bf01a 100644 --- a/deps/v8/src/ic.h +++ b/deps/v8/src/ic.h @@ -191,7 +191,9 @@ class CallICBase: public IC { explicit CallICBase(Code::Kind kind) : IC(EXTRA_CALL_FRAME), kind_(kind) {} 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: Code::Kind kind_; @@ -235,7 +237,9 @@ class KeyedCallIC: public CallICBase { 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. static void GenerateInitialize(MacroAssembler* masm, int argc) { @@ -251,7 +255,9 @@ class LoadIC: public IC { public: 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. static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } @@ -311,7 +317,9 @@ class KeyedLoadIC: public IC { public: 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. static void GenerateMiss(MacroAssembler* masm); @@ -384,10 +392,10 @@ class StoreIC: public IC { public: StoreIC() : IC(NO_EXTRA_FRAME) { ASSERT(target()->is_store_stub()); } - Object* Store(State state, - Handle<Object> object, - Handle<String> name, - Handle<Object> value); + MUST_USE_RESULT MaybeObject* Store(State state, + Handle<Object> object, + Handle<String> name, + Handle<Object> value); // Code generators for stub routines. Only called once at startup. static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } @@ -433,10 +441,10 @@ class KeyedStoreIC: public IC { public: KeyedStoreIC() : IC(NO_EXTRA_FRAME) { } - Object* Store(State state, - Handle<Object> object, - Handle<Object> name, - Handle<Object> value); + MUST_USE_RESULT MaybeObject* Store(State state, + Handle<Object> object, + Handle<Object> name, + Handle<Object> value); // Code generators for stub routines. Only called once at startup. static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); } diff --git a/deps/v8/src/liveedit.cc b/deps/v8/src/liveedit.cc index 3cbd244693..49f221a466 100644 --- a/deps/v8/src/liveedit.cc +++ b/deps/v8/src/liveedit.cc @@ -463,7 +463,7 @@ class JSArrayBasedStruct { SetElement(array_, field_position, Handle<Smi>(Smi::FromInt(value))); } Object* GetField(int field_position) { - return array_->GetElement(field_position); + return array_->GetElementNoExceptionThrown(field_position); } int GetSmiValueField(int field_position) { Object* res = GetField(field_position); @@ -550,7 +550,7 @@ class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> { public: static bool IsInstance(Handle<JSArray> array) { return array->length() == Smi::FromInt(kSize_) && - array->GetElement(kSharedInfoOffset_)->IsJSValue(); + array->GetElementNoExceptionThrown(kSharedInfoOffset_)->IsJSValue(); } explicit SharedInfoWrapper(Handle<JSArray> array) @@ -605,16 +605,18 @@ class FunctionInfoListener { void FunctionDone() { HandleScope scope; - FunctionInfoWrapper info = - FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_)); + Object* element = + result_->GetElementNoExceptionThrown(current_parent_index_); + FunctionInfoWrapper info = FunctionInfoWrapper::cast(element); current_parent_index_ = info.GetParentIndex(); } // Saves only function code, because for a script function we // may never create a SharedFunctionInfo object. void FunctionCode(Handle<Code> function_code) { - FunctionInfoWrapper info = - FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_)); + Object* element = + result_->GetElementNoExceptionThrown(current_parent_index_); + FunctionInfoWrapper info = FunctionInfoWrapper::cast(element); info.SetFunctionCode(function_code, Handle<Object>(Heap::null_value())); } @@ -624,8 +626,9 @@ class FunctionInfoListener { if (!shared->IsSharedFunctionInfo()) { return; } - FunctionInfoWrapper info = - FunctionInfoWrapper::cast(result_->GetElement(current_parent_index_)); + Object* element = + result_->GetElementNoExceptionThrown(current_parent_index_); + FunctionInfoWrapper info = FunctionInfoWrapper::cast(element); info.SetFunctionCode(Handle<Code>(shared->code()), Handle<Object>(shared->scope_info())); info.SetSharedFunctionInfo(shared); @@ -721,7 +724,7 @@ void LiveEdit::WrapSharedFunctionInfos(Handle<JSArray> array) { int len = Smi::cast(array->length())->value(); for (int i = 0; i < len; i++) { Handle<SharedFunctionInfo> info( - SharedFunctionInfo::cast(array->GetElement(i))); + SharedFunctionInfo::cast(array->GetElementNoExceptionThrown(i))); SharedInfoWrapper info_wrapper = SharedInfoWrapper::Create(); Handle<String> name_handle(String::cast(info->name())); 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, - Handle<JSArray> shared_info_array) { +MaybeObject* LiveEdit::ReplaceFunctionCode( + Handle<JSArray> new_compile_info_array, + Handle<JSArray> shared_info_array) { HandleScope scope; 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(); // TODO(635): binary search may be used here for (int i = 0; i < array_len; i += 3) { - int chunk_start = - Smi::cast(position_change_array->GetElement(i))->value(); + Object* element = position_change_array->GetElementNoExceptionThrown(i); + int chunk_start = Smi::cast(element)->value(); if (original_position < chunk_start) { break; } - int chunk_end = - Smi::cast(position_change_array->GetElement(i + 1))->value(); + element = position_change_array->GetElementNoExceptionThrown(i + 1); + int chunk_end = Smi::cast(element)->value(); // Position mustn't be inside a chunk. ASSERT(original_position >= chunk_end); - int chunk_changed_end = - Smi::cast(position_change_array->GetElement(i + 2))->value(); + element = position_change_array->GetElementNoExceptionThrown(i + 2); + int chunk_changed_end = Smi::cast(element)->value(); 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) { 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(); 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( SharedFunctionInfo::cast(wrapper->value())); diff --git a/deps/v8/src/liveedit.h b/deps/v8/src/liveedit.h index d8e2a1375b..c9bf96d4d0 100644 --- a/deps/v8/src/liveedit.h +++ b/deps/v8/src/liveedit.h @@ -83,14 +83,15 @@ class LiveEdit : AllStatic { static void WrapSharedFunctionInfos(Handle<JSArray> array); - static Object* ReplaceFunctionCode(Handle<JSArray> new_compile_info_array, - Handle<JSArray> shared_info_array); + MUST_USE_RESULT static MaybeObject* ReplaceFunctionCode( + Handle<JSArray> new_compile_info_array, + Handle<JSArray> shared_info_array); // Updates script field in FunctionSharedInfo. static void SetFunctionScript(Handle<JSValue> function_wrapper, Handle<Object> script_handle); - static Object* PatchFunctionPositions( + MUST_USE_RESULT static MaybeObject* PatchFunctionPositions( Handle<JSArray> shared_info_array, Handle<JSArray> position_change_array); // For a script updates its source field. If old_script_name is provided diff --git a/deps/v8/src/log.cc b/deps/v8/src/log.cc index 1b0fdeb5be..2cc2b8ffa8 100644 --- a/deps/v8/src/log.cc +++ b/deps/v8/src/log.cc @@ -559,7 +559,12 @@ void Logger::LogRuntime(Vector<const char> format, JSArray* args) { if (c == '%' && i <= format.length() - 2) { i++; 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++; switch (format[i]) { case 's': @@ -1378,8 +1383,10 @@ void Logger::LogCodeInfo() { void Logger::LowLevelCodeCreateEvent(Code* code, LogMessageBuilder* msg) { if (!FLAG_ll_prof || Log::output_code_handle_ == NULL) return; int pos = static_cast<int>(ftell(Log::output_code_handle_)); - fwrite(code->instruction_start(), 1, code->instruction_size(), - Log::output_code_handle_); + size_t rv = fwrite(code->instruction_start(), 1, code->instruction_size(), + Log::output_code_handle_); + ASSERT(static_cast<size_t>(code->instruction_size()) == rv); + USE(rv); msg->Append(",%d", pos); } diff --git a/deps/v8/src/mark-compact.cc b/deps/v8/src/mark-compact.cc index ad928ea3ed..484497f087 100644 --- a/deps/v8/src/mark-compact.cc +++ b/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 // strings are promoted to the code space, large objects to large object space, // and all others to the old space. -inline Object* MCAllocateFromNewSpace(HeapObject* object, int object_size) { - Object* forwarded; +inline MaybeObject* MCAllocateFromNewSpace(HeapObject* object, + int object_size) { + MaybeObject* forwarded; if (object_size > Heap::MaxObjectSizeInPagedSpace()) { forwarded = Failure::Exception(); } else { @@ -1274,36 +1275,45 @@ inline Object* MCAllocateFromNewSpace(HeapObject* object, int object_size) { target_space == Heap::old_data_space()); forwarded = target_space->MCAllocateRaw(object_size); } - if (forwarded->IsFailure()) { - forwarded = Heap::new_space()->MCAllocateRaw(object_size); + Object* result; + 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. -inline Object* MCAllocateFromOldPointerSpace(HeapObject* ignore, - int object_size) { +MUST_USE_RESULT inline MaybeObject* MCAllocateFromOldPointerSpace( + HeapObject* ignore, + int 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); } -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); } -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); } -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); } @@ -1380,9 +1390,8 @@ inline void EncodeForwardingAddressesInRange(Address start, MarkCompactCollector::tracer()->decrement_marked_count(); object_size = object->Size(); - Object* forwarded = Alloc(object, object_size); // 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); #ifdef DEBUG @@ -1551,8 +1560,9 @@ static bool TryPromoteObject(HeapObject* object, int object_size) { Object* result; if (object_size > Heap::MaxObjectSizeInPagedSpace()) { - result = Heap::lo_space()->AllocateRawFixedArray(object_size); - if (!result->IsFailure()) { + MaybeObject* maybe_result = + Heap::lo_space()->AllocateRawFixedArray(object_size); + if (maybe_result->ToObject(&result)) { HeapObject* target = HeapObject::cast(result); MigrateObject(target->address(), object->address(), object_size, true); MarkCompactCollector::tracer()-> @@ -1564,8 +1574,8 @@ static bool TryPromoteObject(HeapObject* object, int object_size) { ASSERT(target_space == Heap::old_pointer_space() || target_space == Heap::old_data_space()); - result = target_space->AllocateRaw(object_size); - if (!result->IsFailure()) { + MaybeObject* maybe_result = target_space->AllocateRaw(object_size); + if (maybe_result->ToObject(&result)) { HeapObject* target = HeapObject::cast(result); MigrateObject(target->address(), object->address(), @@ -1613,10 +1623,8 @@ static void SweepNewSpace(NewSpace* space) { } // Promotion failed. Just migrate object to another semispace. - Object* target = space->AllocateRaw(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(), current, diff --git a/deps/v8/src/mark-compact.h b/deps/v8/src/mark-compact.h index 72a6fa3b62..7444c5bf3c 100644 --- a/deps/v8/src/mark-compact.h +++ b/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 // allocation function for each (compactable) space based on the location // 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. // Given the object, its size, and the new (non-failure) object it will be diff --git a/deps/v8/src/messages.cc b/deps/v8/src/messages.cc index ec91cc8779..42fc3c9bd6 100644 --- a/deps/v8/src/messages.cc +++ b/deps/v8/src/messages.cc @@ -152,8 +152,8 @@ void MessageHandler::ReportMessage(MessageLocation* loc, Handle<String> MessageHandler::GetMessage(Handle<Object> data) { Handle<String> fmt_str = Factory::LookupAsciiSymbol("FormatMessage"); Handle<JSFunction> fun = - Handle<JSFunction>( - JSFunction::cast(Top::builtins()->GetProperty(*fmt_str))); + Handle<JSFunction>(JSFunction::cast( + Top::builtins()->GetPropertyNoExceptionThrown(*fmt_str))); Object** argv[1] = { data.location() }; bool caught_exception; diff --git a/deps/v8/src/objects-debug.cc b/deps/v8/src/objects-debug.cc index 5883f8b343..c0e5610aba 100644 --- a/deps/v8/src/objects-debug.cc +++ b/deps/v8/src/objects-debug.cc @@ -40,31 +40,37 @@ namespace internal { static const char* TypeToString(InstanceType type); -void Object::Print() { - if (IsSmi()) { - Smi::cast(this)->SmiPrint(); - } else if (IsFailure()) { - Failure::cast(this)->FailurePrint(); +void MaybeObject::Print() { + Object* this_as_object; + if (ToObject(&this_as_object)) { + if (this_as_object->IsSmi()) { + Smi::cast(this_as_object)->SmiPrint(); + } else { + HeapObject::cast(this_as_object)->HeapObjectPrint(); + } } else { - HeapObject::cast(this)->HeapObjectPrint(); + Failure::cast(this)->FailurePrint(); } Flush(); } -void Object::PrintLn() { +void MaybeObject::PrintLn() { Print(); PrintF("\n"); } -void Object::Verify() { - if (IsSmi()) { - Smi::cast(this)->SmiVerify(); - } else if (IsFailure()) { - Failure::cast(this)->FailureVerify(); +void MaybeObject::Verify() { + Object* this_as_object; + if (ToObject(&this_as_object)) { + if (this_as_object->IsSmi()) { + Smi::cast(this_as_object)->SmiVerify(); + } else { + HeapObject::cast(this_as_object)->HeapObjectVerify(); + } } else { - HeapObject::cast(this)->HeapObjectVerify(); + Failure::cast(this)->FailureVerify(); } } diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index 11f9d34882..4d210172b8 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -396,28 +396,39 @@ bool Object::IsExternalFloatArray() { } -bool Object::IsFailure() { +bool MaybeObject::IsFailure() { return HAS_FAILURE_TAG(this); } -bool Object::IsRetryAfterGC() { +bool MaybeObject::IsRetryAfterGC() { return HAS_FAILURE_TAG(this) && Failure::cast(this)->type() == Failure::RETRY_AFTER_GC; } -bool Object::IsOutOfMemoryFailure() { +bool MaybeObject::IsOutOfMemory() { return HAS_FAILURE_TAG(this) && Failure::cast(this)->IsOutOfMemoryException(); } -bool Object::IsException() { +bool MaybeObject::IsException() { 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() { return IsHeapObject() && 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() { return this == Heap::null_value(); } @@ -706,7 +712,7 @@ double Object::Number() { -Object* Object::ToSmi() { +MaybeObject* Object::ToSmi() { if (IsSmi()) return this; if (IsHeapNumber()) { 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); } -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; return GetPropertyWithReceiver(this, key, &attributes); } -Object* Object::GetProperty(String* key, PropertyAttributes* attributes) { +MaybeObject* Object::GetProperty(String* key, PropertyAttributes* attributes) { return GetPropertyWithReceiver(this, key, attributes); } @@ -1189,9 +1204,11 @@ void JSObject::initialize_elements() { } -Object* JSObject::ResetElements() { - Object* obj = map()->GetFastElementsMap(); - if (obj->IsFailure()) return obj; +MaybeObject* JSObject::ResetElements() { + Object* obj; + { MaybeObject* maybe_obj = map()->GetFastElementsMap(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } set_map(Map::cast(obj)); initialize_elements(); return this; @@ -1681,7 +1698,6 @@ CAST_ACCESSOR(ExternalAsciiString) CAST_ACCESSOR(ExternalTwoByteString) CAST_ACCESSOR(JSObject) CAST_ACCESSOR(Smi) -CAST_ACCESSOR(Failure) CAST_ACCESSOR(HeapObject) CAST_ACCESSOR(HeapNumber) 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; ConsString* cons = ConsString::cast(this); if (cons->second()->length() == 0) return cons->first(); @@ -1763,8 +1779,12 @@ Object* String::TryFlatten(PretenureFlag pretenure) { String* String::TryFlattenGetString(PretenureFlag pretenure) { - Object* flat = TryFlatten(pretenure); - return flat->IsFailure() ? this : String::cast(flat); + MaybeObject* flat = TryFlatten(pretenure); + 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; - Object* obj = CopyDropTransitions(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = CopyDropTransitions(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } Map* new_map = Map::cast(obj); new_map->set_has_fast_elements(true); 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; - Object* obj = CopyDropTransitions(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = CopyDropTransitions(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } Map* new_map = Map::cast(obj); new_map->set_has_fast_elements(false); Counters::map_fast_to_slow_elements.Increment(); @@ -3189,13 +3213,17 @@ bool JSObject::AllowsSetElementsLength() { } -Object* JSObject::EnsureWritableFastElements() { +MaybeObject* JSObject::EnsureWritableFastElements() { ASSERT(HasFastElements()); FixedArray* elems = FixedArray::cast(elements()); if (elems->map() != Heap::fixed_cow_array_map()) return elems; - Object* writable_elems = Heap::CopyFixedArrayWithMap(elems, - Heap::fixed_array_map()); - if (writable_elems->IsFailure()) return writable_elems; + Object* writable_elems; + { MaybeObject* maybe_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)); Counters::cow_arrays_converted.Increment(); return writable_elems; @@ -3340,13 +3368,18 @@ bool JSObject::HasHiddenPropertiesObject() { Object* JSObject::GetHiddenPropertiesObject() { ASSERT(!IsJSGlobalProxy()); PropertyAttributes attributes; - return GetLocalPropertyPostInterceptor(this, - Heap::hidden_symbol(), - &attributes); + // You can't install a getter on a property indexed by the hidden symbol, + // so we can be sure that GetLocalPropertyPostInterceptor returns a real + // 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()); return SetPropertyPostInterceptor(Heap::hidden_symbol(), hidden_obj, @@ -3453,7 +3486,7 @@ void JSArray::SetContent(FixedArray* storage) { } -Object* FixedArray::Copy() { +MaybeObject* FixedArray::Copy() { if (length() == 0) return this; return Heap::CopyFixedArray(this); } diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index ac20b2e6f7..c1cb922de5 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -54,16 +54,18 @@ const int kGetterIndex = 0; const int kSetterIndex = 1; -MUST_USE_RESULT static Object* CreateJSValue(JSFunction* constructor, - Object* value) { - Object* result = Heap::AllocateJSObject(constructor); - if (result->IsFailure()) return result; +MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, + Object* value) { + Object* result; + { MaybeObject* maybe_result = Heap::AllocateJSObject(constructor); + if (!maybe_result->ToObject(&result)) return maybe_result; + } JSValue::cast(result)->set_value(value); return result; } -Object* Object::ToObject(Context* global_context) { +MaybeObject* Object::ToObject(Context* global_context) { if (IsNumber()) { return CreateJSValue(global_context->number_function(), this); } else if (IsBoolean()) { @@ -76,7 +78,7 @@ Object* Object::ToObject(Context* global_context) { } -Object* Object::ToObject() { +MaybeObject* Object::ToObject() { Context* global_context = Top::context()->global_context(); if (IsJSObject()) { return this; @@ -130,28 +132,28 @@ void Object::Lookup(String* name, LookupResult* result) { } -Object* Object::GetPropertyWithReceiver(Object* receiver, - String* name, - PropertyAttributes* attributes) { +MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, + String* name, + PropertyAttributes* attributes) { LookupResult result; Lookup(name, &result); - Object* value = GetProperty(receiver, &result, name, attributes); + MaybeObject* value = GetProperty(receiver, &result, name, attributes); ASSERT(*attributes <= ABSENT); return value; } -Object* Object::GetPropertyWithCallback(Object* receiver, - Object* structure, - String* name, - Object* holder) { +MaybeObject* Object::GetPropertyWithCallback(Object* receiver, + Object* structure, + String* name, + Object* holder) { // To accommodate both the old and the new api we switch on the // data structure used to store the callbacks. Eventually proxy // callbacks should be phased out. if (structure->IsProxy()) { AccessorDescriptor* callback = reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); - Object* value = (callback->getter)(receiver, callback->data); + MaybeObject* value = (callback->getter)(receiver, callback->data); RETURN_IF_SCHEDULED_EXCEPTION(); return value; } @@ -195,8 +197,8 @@ Object* Object::GetPropertyWithCallback(Object* receiver, } -Object* Object::GetPropertyWithDefinedGetter(Object* receiver, - JSFunction* getter) { +MaybeObject* Object::GetPropertyWithDefinedGetter(Object* receiver, + JSFunction* getter) { HandleScope scope; Handle<JSFunction> fun(JSFunction::cast(getter)); Handle<Object> self(receiver); @@ -216,7 +218,7 @@ Object* Object::GetPropertyWithDefinedGetter(Object* receiver, // Only deal with CALLBACKS and INTERCEPTOR -Object* JSObject::GetPropertyWithFailedAccessCheck( +MaybeObject* JSObject::GetPropertyWithFailedAccessCheck( Object* receiver, LookupResult* result, String* name, @@ -365,19 +367,26 @@ Object* JSObject::SetNormalizedProperty(LookupResult* result, Object* value) { } -Object* JSObject::SetNormalizedProperty(String* name, - Object* value, - PropertyDetails details) { +MaybeObject* JSObject::SetNormalizedProperty(String* name, + Object* value, + PropertyDetails details) { ASSERT(!HasFastProperties()); int entry = property_dictionary()->FindEntry(name); if (entry == StringDictionary::kNotFound) { Object* store_value = value; if (IsGlobalObject()) { - store_value = Heap::AllocateJSGlobalPropertyCell(value); - if (store_value->IsFailure()) return store_value; + { MaybeObject* maybe_store_value = + Heap::AllocateJSGlobalPropertyCell(value); + if (!maybe_store_value->ToObject(&store_value)) { + return maybe_store_value; + } + } + } + Object* dict; + { MaybeObject* maybe_dict = + property_dictionary()->Add(name, store_value, details); + if (!maybe_dict->ToObject(&dict)) return maybe_dict; } - Object* dict = property_dictionary()->Add(name, store_value, details); - if (dict->IsFailure()) return dict; set_properties(StringDictionary::cast(dict)); return value; } @@ -398,7 +407,7 @@ Object* JSObject::SetNormalizedProperty(String* name, } -Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { +MaybeObject* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { ASSERT(!HasFastProperties()); StringDictionary* dictionary = property_dictionary(); int entry = dictionary->FindEntry(name); @@ -412,8 +421,10 @@ Object* JSObject::DeleteNormalizedProperty(String* name, DeleteMode mode) { // map change to invalidate any ICs that think they can load // from the DontDelete cell without checking if it contains // the hole value. - Object* new_map = map()->CopyDropDescriptors(); - if (new_map->IsFailure()) return new_map; + Object* new_map; + { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } set_map(Map::cast(new_map)); } JSGlobalPropertyCell* cell = @@ -443,10 +454,10 @@ bool JSObject::IsDirty() { } -Object* Object::GetProperty(Object* receiver, - LookupResult* result, - String* name, - PropertyAttributes* attributes) { +MaybeObject* Object::GetProperty(Object* receiver, + LookupResult* result, + String* name, + PropertyAttributes* attributes) { // Make sure that the top context does not change when doing // callbacks or interceptor calls. AssertNoContextChange ncc; @@ -512,7 +523,7 @@ Object* Object::GetProperty(Object* receiver, } -Object* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { +MaybeObject* Object::GetElementWithReceiver(Object* receiver, uint32_t index) { // Non-JS objects do not have integer indexed properties. if (!IsJSObject()) return Heap::undefined_value(); return JSObject::cast(this)->GetElementWithReceiver(JSObject::cast(receiver), @@ -598,7 +609,7 @@ static bool AnWord(String* str) { } -Object* String::SlowTryFlatten(PretenureFlag pretenure) { +MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) { #ifdef DEBUG // Do not attempt to flatten in debug mode when allocation is not // allowed. This is to avoid an assertion failure when allocating. @@ -621,8 +632,9 @@ Object* String::SlowTryFlatten(PretenureFlag pretenure) { Object* object; String* result; if (IsAsciiRepresentation()) { - object = Heap::AllocateRawAsciiString(len, tenure); - if (object->IsFailure()) return object; + { MaybeObject* maybe_object = Heap::AllocateRawAsciiString(len, tenure); + if (!maybe_object->ToObject(&object)) return maybe_object; + } result = String::cast(object); String* first = cs->first(); int first_length = first->length(); @@ -634,8 +646,10 @@ Object* String::SlowTryFlatten(PretenureFlag pretenure) { 0, len - first_length); } else { - object = Heap::AllocateRawTwoByteString(len, tenure); - if (object->IsFailure()) return object; + { MaybeObject* maybe_object = + Heap::AllocateRawTwoByteString(len, tenure); + if (!maybe_object->ToObject(&object)) return maybe_object; + } result = String::cast(object); uc16* dest = SeqTwoByteString::cast(result)->GetChars(); String* first = cs->first(); @@ -1169,16 +1183,18 @@ String* JSObject::constructor_name() { } -Object* JSObject::AddFastPropertyUsingMap(Map* new_map, - String* name, - Object* value) { +MaybeObject* JSObject::AddFastPropertyUsingMap(Map* new_map, + String* name, + Object* value) { int index = new_map->PropertyIndexFor(name); if (map()->unused_property_fields() == 0) { ASSERT(map()->unused_property_fields() == 0); int new_unused = new_map->unused_property_fields(); - Object* values = - properties()->CopySize(properties()->length() + new_unused + 1); - if (values->IsFailure()) return values; + Object* values; + { MaybeObject* maybe_values = + properties()->CopySize(properties()->length() + new_unused + 1); + if (!maybe_values->ToObject(&values)) return maybe_values; + } set_properties(FixedArray::cast(values)); } set_map(new_map); @@ -1186,15 +1202,18 @@ Object* JSObject::AddFastPropertyUsingMap(Map* new_map, } -Object* JSObject::AddFastProperty(String* name, - Object* value, - PropertyAttributes attributes) { +MaybeObject* JSObject::AddFastProperty(String* name, + Object* value, + PropertyAttributes attributes) { // Normalize the object if the name is an actual string (not the // hidden symbols) and is not a real identifier. StringInputBuffer buffer(name); if (!Scanner::IsIdentifier(&buffer) && name != Heap::hidden_symbol()) { - Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return AddSlowProperty(name, value, attributes); } @@ -1204,9 +1223,13 @@ Object* JSObject::AddFastProperty(String* name, // Allocate new instance descriptors with (name, index) added FieldDescriptor new_field(name, index, attributes); - Object* new_descriptors = - old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); - if (new_descriptors->IsFailure()) return new_descriptors; + Object* new_descriptors; + { MaybeObject* maybe_new_descriptors = + old_descriptors->CopyInsert(&new_field, REMOVE_TRANSITIONS); + if (!maybe_new_descriptors->ToObject(&new_descriptors)) { + return maybe_new_descriptors; + } + } // Only allow map transition if the object's map is NOT equal to the // global object_function's map and there is not a transition for name. @@ -1218,27 +1241,36 @@ Object* JSObject::AddFastProperty(String* name, (index - map()->inobject_properties()) < properties()->length() || map()->unused_property_fields() == 0); // Allocate a new map for the object. - Object* r = map()->CopyDropDescriptors(); - if (r->IsFailure()) return r; + Object* r; + { MaybeObject* maybe_r = map()->CopyDropDescriptors(); + if (!maybe_r->ToObject(&r)) return maybe_r; + } Map* new_map = Map::cast(r); if (allow_map_transition) { // Allocate new instance descriptors for the old map with map transition. MapTransitionDescriptor d(name, Map::cast(new_map), attributes); - Object* r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); - if (r->IsFailure()) return r; + Object* r; + { MaybeObject* maybe_r = old_descriptors->CopyInsert(&d, KEEP_TRANSITIONS); + if (!maybe_r->ToObject(&r)) return maybe_r; + } old_descriptors = DescriptorArray::cast(r); } if (map()->unused_property_fields() == 0) { if (properties()->length() > MaxFastProperties()) { - Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return AddSlowProperty(name, value, attributes); } // Make room for the new value - Object* values = - properties()->CopySize(properties()->length() + kFieldsAdded); - if (values->IsFailure()) return values; + Object* values; + { MaybeObject* maybe_values = + properties()->CopySize(properties()->length() + kFieldsAdded); + if (!maybe_values->ToObject(&values)) return maybe_values; + } set_properties(FixedArray::cast(values)); new_map->set_unused_property_fields(kFieldsAdded - 1); } else { @@ -1253,20 +1285,27 @@ Object* JSObject::AddFastProperty(String* name, } -Object* JSObject::AddConstantFunctionProperty(String* name, - JSFunction* function, - PropertyAttributes attributes) { +MaybeObject* JSObject::AddConstantFunctionProperty( + String* name, + JSFunction* function, + PropertyAttributes attributes) { ASSERT(!Heap::InNewSpace(function)); // Allocate new instance descriptors with (name, function) added ConstantFunctionDescriptor d(name, function, attributes); - Object* new_descriptors = - map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS); - if (new_descriptors->IsFailure()) return new_descriptors; + Object* new_descriptors; + { MaybeObject* maybe_new_descriptors = + map()->instance_descriptors()->CopyInsert(&d, REMOVE_TRANSITIONS); + if (!maybe_new_descriptors->ToObject(&new_descriptors)) { + return maybe_new_descriptors; + } + } // Allocate a new map for the object. - Object* new_map = map()->CopyDropDescriptors(); - if (new_map->IsFailure()) return new_map; + Object* new_map; + { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } DescriptorArray* descriptors = DescriptorArray::cast(new_descriptors); Map::cast(new_map)->set_instance_descriptors(descriptors); @@ -1292,10 +1331,12 @@ Object* JSObject::AddConstantFunctionProperty(String* name, return function; } ConstTransitionDescriptor mark(name, Map::cast(new_map)); - new_descriptors = - old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS); - if (new_descriptors->IsFailure()) { - return function; // We have accomplished the main goal, so return success. + { MaybeObject* maybe_new_descriptors = + old_map->instance_descriptors()->CopyInsert(&mark, KEEP_TRANSITIONS); + if (!maybe_new_descriptors->ToObject(&new_descriptors)) { + // We have accomplished the main goal, so return success. + return function; + } } old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); @@ -1304,9 +1345,9 @@ Object* JSObject::AddConstantFunctionProperty(String* name, // Add property in slow mode -Object* JSObject::AddSlowProperty(String* name, - Object* value, - PropertyAttributes attributes) { +MaybeObject* JSObject::AddSlowProperty(String* name, + Object* value, + PropertyAttributes attributes) { ASSERT(!HasFastProperties()); StringDictionary* dict = property_dictionary(); Object* store_value = value; @@ -1324,21 +1365,25 @@ Object* JSObject::AddSlowProperty(String* name, dict->SetEntry(entry, name, store_value, details); return value; } - store_value = Heap::AllocateJSGlobalPropertyCell(value); - if (store_value->IsFailure()) return store_value; + { MaybeObject* maybe_store_value = + Heap::AllocateJSGlobalPropertyCell(value); + if (!maybe_store_value->ToObject(&store_value)) return maybe_store_value; + } JSGlobalPropertyCell::cast(store_value)->set_value(value); } PropertyDetails details = PropertyDetails(attributes, NORMAL); - Object* result = dict->Add(name, store_value, details); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = dict->Add(name, store_value, details); + if (!maybe_result->ToObject(&result)) return maybe_result; + } if (dict != result) set_properties(StringDictionary::cast(result)); return value; } -Object* JSObject::AddProperty(String* name, - Object* value, - PropertyAttributes attributes) { +MaybeObject* JSObject::AddProperty(String* name, + Object* value, + PropertyAttributes attributes) { ASSERT(!IsJSGlobalProxy()); if (!map()->is_extensible()) { Handle<Object> args[1] = {Handle<String>(name)}; @@ -1359,17 +1404,21 @@ Object* JSObject::AddProperty(String* name, } else { // Normalize the object to prevent very large instance descriptors. // This eliminates unwanted N^2 allocation and lookup behavior. - Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } } } return AddSlowProperty(name, value, attributes); } -Object* JSObject::SetPropertyPostInterceptor(String* name, - Object* value, - PropertyAttributes attributes) { +MaybeObject* JSObject::SetPropertyPostInterceptor( + String* name, + Object* value, + PropertyAttributes attributes) { // Check local property, ignore interceptor. LookupResult result; LocalLookupRealNamedProperty(name, &result); @@ -1383,9 +1432,9 @@ Object* JSObject::SetPropertyPostInterceptor(String* name, } -Object* JSObject::ReplaceSlowProperty(String* name, - Object* value, - PropertyAttributes attributes) { +MaybeObject* JSObject::ReplaceSlowProperty(String* name, + Object* value, + PropertyAttributes attributes) { StringDictionary* dictionary = property_dictionary(); int old_index = dictionary->FindEntry(name); int new_enumeration_index = 0; // 0 means "Use the next available index." @@ -1400,13 +1449,16 @@ Object* JSObject::ReplaceSlowProperty(String* name, } -Object* JSObject::ConvertDescriptorToFieldAndMapTransition( +MaybeObject* JSObject::ConvertDescriptorToFieldAndMapTransition( String* name, Object* new_value, PropertyAttributes attributes) { Map* old_map = map(); - Object* result = ConvertDescriptorToField(name, new_value, attributes); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + ConvertDescriptorToField(name, new_value, attributes); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // If we get to this point we have succeeded - do not return failure // after this point. Later stuff is optional. if (!HasFastProperties()) { @@ -1420,37 +1472,51 @@ Object* JSObject::ConvertDescriptorToFieldAndMapTransition( MapTransitionDescriptor transition(name, map(), attributes); - Object* new_descriptors = - old_map->instance_descriptors()-> - CopyInsert(&transition, KEEP_TRANSITIONS); - if (new_descriptors->IsFailure()) return result; // Yes, return _result_. + Object* new_descriptors; + { MaybeObject* maybe_new_descriptors = old_map->instance_descriptors()-> + CopyInsert(&transition, KEEP_TRANSITIONS); + if (!maybe_new_descriptors->ToObject(&new_descriptors)) { + return result; // Yes, return _result_. + } + } old_map->set_instance_descriptors(DescriptorArray::cast(new_descriptors)); return result; } -Object* JSObject::ConvertDescriptorToField(String* name, - Object* new_value, - PropertyAttributes attributes) { +MaybeObject* JSObject::ConvertDescriptorToField(String* name, + Object* new_value, + PropertyAttributes attributes) { if (map()->unused_property_fields() == 0 && properties()->length() > MaxFastProperties()) { - Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return ReplaceSlowProperty(name, new_value, attributes); } int index = map()->NextFreePropertyIndex(); FieldDescriptor new_field(name, index, attributes); // Make a new DescriptorArray replacing an entry with FieldDescriptor. - Object* descriptors_unchecked = map()->instance_descriptors()-> - CopyInsert(&new_field, REMOVE_TRANSITIONS); - if (descriptors_unchecked->IsFailure()) return descriptors_unchecked; + Object* descriptors_unchecked; + { MaybeObject* maybe_descriptors_unchecked = map()->instance_descriptors()-> + CopyInsert(&new_field, REMOVE_TRANSITIONS); + if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { + return maybe_descriptors_unchecked; + } + } DescriptorArray* new_descriptors = DescriptorArray::cast(descriptors_unchecked); // Make a new map for the object. - Object* new_map_unchecked = map()->CopyDropDescriptors(); - if (new_map_unchecked->IsFailure()) return new_map_unchecked; + Object* new_map_unchecked; + { MaybeObject* maybe_new_map_unchecked = map()->CopyDropDescriptors(); + if (!maybe_new_map_unchecked->ToObject(&new_map_unchecked)) { + return maybe_new_map_unchecked; + } + } Map* new_map = Map::cast(new_map_unchecked); new_map->set_instance_descriptors(new_descriptors); @@ -1459,10 +1525,14 @@ Object* JSObject::ConvertDescriptorToField(String* name, int new_unused_property_fields = map()->unused_property_fields() - 1; if (map()->unused_property_fields() == 0) { new_unused_property_fields = kFieldsAdded - 1; - Object* new_properties_unchecked = - properties()->CopySize(properties()->length() + kFieldsAdded); - if (new_properties_unchecked->IsFailure()) return new_properties_unchecked; - new_properties = FixedArray::cast(new_properties_unchecked); + Object* new_properties_object; + { MaybeObject* maybe_new_properties_object = + properties()->CopySize(properties()->length() + kFieldsAdded); + if (!maybe_new_properties_object->ToObject(&new_properties_object)) { + return maybe_new_properties_object; + } + } + new_properties = FixedArray::cast(new_properties_object); } // Update pointers to commit changes. @@ -1477,9 +1547,10 @@ Object* JSObject::ConvertDescriptorToField(String* name, -Object* JSObject::SetPropertyWithInterceptor(String* name, - Object* value, - PropertyAttributes attributes) { +MaybeObject* JSObject::SetPropertyWithInterceptor( + String* name, + Object* value, + PropertyAttributes attributes) { HandleScope scope; Handle<JSObject> this_handle(this); Handle<String> name_handle(name); @@ -1505,27 +1576,28 @@ Object* JSObject::SetPropertyWithInterceptor(String* name, RETURN_IF_SCHEDULED_EXCEPTION(); if (!result.IsEmpty()) return *value_handle; } - Object* raw_result = this_handle->SetPropertyPostInterceptor(*name_handle, - *value_handle, - attributes); + MaybeObject* raw_result = + this_handle->SetPropertyPostInterceptor(*name_handle, + *value_handle, + attributes); RETURN_IF_SCHEDULED_EXCEPTION(); return raw_result; } -Object* JSObject::SetProperty(String* name, - Object* value, - PropertyAttributes attributes) { +MaybeObject* JSObject::SetProperty(String* name, + Object* value, + PropertyAttributes attributes) { LookupResult result; LocalLookup(name, &result); return SetProperty(&result, name, value, attributes); } -Object* JSObject::SetPropertyWithCallback(Object* structure, - String* name, - Object* value, - JSObject* holder) { +MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, + String* name, + Object* value, + JSObject* holder) { HandleScope scope; // We should never get here to initialize a const with the hole @@ -1539,7 +1611,7 @@ Object* JSObject::SetPropertyWithCallback(Object* structure, if (structure->IsProxy()) { AccessorDescriptor* callback = reinterpret_cast<AccessorDescriptor*>(Proxy::cast(structure)->proxy()); - Object* obj = (callback->setter)(this, value, callback->data); + MaybeObject* obj = (callback->setter)(this, value, callback->data); RETURN_IF_SCHEDULED_EXCEPTION(); if (obj->IsFailure()) return obj; return *value_handle; @@ -1584,8 +1656,8 @@ Object* JSObject::SetPropertyWithCallback(Object* structure, } -Object* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter, - Object* value) { +MaybeObject* JSObject::SetPropertyWithDefinedSetter(JSFunction* setter, + Object* value) { Handle<Object> value_handle(value); Handle<JSFunction> fun(JSFunction::cast(setter)); Handle<JSObject> self(this); @@ -1727,9 +1799,9 @@ void JSObject::LookupRealNamedPropertyInPrototypes(String* name, // We only need to deal with CALLBACKS and INTERCEPTORS -Object* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, - String* name, - Object* value) { +MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, + String* name, + Object* value) { if (!result->IsProperty()) { LookupCallbackSetterInPrototypes(name, result); } @@ -1774,10 +1846,10 @@ Object* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, } -Object* JSObject::SetProperty(LookupResult* result, - String* name, - Object* value, - PropertyAttributes attributes) { +MaybeObject* JSObject::SetProperty(LookupResult* result, + String* name, + Object* value, + PropertyAttributes attributes) { // Make sure that the top context does not change when doing callbacks or // interceptor calls. AssertNoContextChange ncc; @@ -1786,8 +1858,12 @@ Object* JSObject::SetProperty(LookupResult* result, // dictionary. We make these short keys into symbols to avoid constantly // reallocating them. if (!name->IsSymbol() && name->length() <= 2) { - Object* symbol_version = Heap::LookupSymbol(name); - if (!symbol_version->IsFailure()) name = String::cast(symbol_version); + Object* symbol_version; + { MaybeObject* maybe_symbol_version = Heap::LookupSymbol(name); + if (maybe_symbol_version->ToObject(&symbol_version)) { + name = String::cast(symbol_version); + } + } } // Check access rights if needed. @@ -1883,7 +1959,7 @@ Object* JSObject::SetProperty(LookupResult* result, // callback setter removed. The two lines looking up the LookupResult // result are also added. If one of the functions is changed, the other // should be. -Object* JSObject::IgnoreAttributesAndSetLocalProperty( +MaybeObject* JSObject::IgnoreAttributesAndSetLocalProperty( String* name, Object* value, PropertyAttributes attributes) { @@ -2081,7 +2157,8 @@ PropertyAttributes JSObject::GetLocalPropertyAttribute(String* name) { } -Object* NormalizedMapCache::Get(JSObject* obj, PropertyNormalizationMode mode) { +MaybeObject* NormalizedMapCache::Get(JSObject* obj, + PropertyNormalizationMode mode) { Map* fast = obj->map(); int index = Hash(fast) % kEntries; Object* result = get(index); @@ -2089,19 +2166,24 @@ Object* NormalizedMapCache::Get(JSObject* obj, PropertyNormalizationMode mode) { #ifdef DEBUG if (FLAG_enable_slow_asserts) { // The cached map should match newly created normalized map bit-by-bit. - Object* fresh = fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); - if (!fresh->IsFailure()) { - ASSERT(memcmp(Map::cast(fresh)->address(), - Map::cast(result)->address(), - Map::kSize) == 0); + Object* fresh; + { MaybeObject* maybe_fresh = + fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); + if (maybe_fresh->ToObject(&fresh)) { + ASSERT(memcmp(Map::cast(fresh)->address(), + Map::cast(result)->address(), + Map::kSize) == 0); + } } } #endif return result; } - result = fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = + fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); + if (!maybe_result->ToObject(&result)) return maybe_result; + } set(index, result); Counters::normalized_maps.Increment(); @@ -2153,14 +2235,16 @@ bool NormalizedMapCache::CheckHit(Map* slow, } -Object* JSObject::UpdateMapCodeCache(String* name, Code* code) { +MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) { if (map()->is_shared()) { // Fast case maps are never marked as shared. ASSERT(!HasFastProperties()); // Replace the map with an identical copy that can be safely modified. - Object* obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, - UNIQUE_NORMALIZED_MAP); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, + UNIQUE_NORMALIZED_MAP); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } Counters::normalized_maps.Increment(); set_map(Map::cast(obj)); @@ -2169,8 +2253,8 @@ Object* JSObject::UpdateMapCodeCache(String* name, Code* code) { } -Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, - int expected_additional_properties) { +MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode, + int expected_additional_properties) { if (!HasFastProperties()) return this; // The global object is always normalized. @@ -2183,9 +2267,11 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, } else { property_count += 2; // Make space for two more properties. } - Object* obj = - StringDictionary::Allocate(property_count); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + StringDictionary::Allocate(property_count); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } StringDictionary* dictionary = StringDictionary::cast(obj); DescriptorArray* descs = map()->instance_descriptors(); @@ -2196,8 +2282,11 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, PropertyDetails d = PropertyDetails(details.attributes(), NORMAL, details.index()); Object* value = descs->GetConstantFunction(i); - Object* result = dictionary->Add(descs->GetKey(i), value, d); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + dictionary->Add(descs->GetKey(i), value, d); + if (!maybe_result->ToObject(&result)) return maybe_result; + } dictionary = StringDictionary::cast(result); break; } @@ -2205,8 +2294,11 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, PropertyDetails d = PropertyDetails(details.attributes(), NORMAL, details.index()); Object* value = FastPropertyAt(descs->GetFieldIndex(i)); - Object* result = dictionary->Add(descs->GetKey(i), value, d); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + dictionary->Add(descs->GetKey(i), value, d); + if (!maybe_result->ToObject(&result)) return maybe_result; + } dictionary = StringDictionary::cast(result); break; } @@ -2214,8 +2306,11 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, PropertyDetails d = PropertyDetails(details.attributes(), CALLBACKS, details.index()); Object* value = descs->GetCallbacksObject(i); - Object* result = dictionary->Add(descs->GetKey(i), value, d); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + dictionary->Add(descs->GetKey(i), value, d); + if (!maybe_result->ToObject(&result)) return maybe_result; + } dictionary = StringDictionary::cast(result); break; } @@ -2233,9 +2328,10 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, int index = map()->instance_descriptors()->NextEnumerationIndex(); dictionary->SetNextEnumerationIndex(index); - obj = Top::context()->global_context()-> - normalized_map_cache()->Get(this, mode); - if (obj->IsFailure()) return obj; + { MaybeObject* maybe_obj = Top::context()->global_context()-> + normalized_map_cache()->Get(this, mode); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } Map* new_map = Map::cast(obj); // We have now successfully allocated all the necessary objects. @@ -2264,7 +2360,7 @@ Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, } -Object* JSObject::TransformToFastProperties(int unused_property_fields) { +MaybeObject* JSObject::TransformToFastProperties(int unused_property_fields) { if (HasFastProperties()) return this; ASSERT(!IsGlobalObject()); return property_dictionary()-> @@ -2272,13 +2368,15 @@ Object* JSObject::TransformToFastProperties(int unused_property_fields) { } -Object* JSObject::NormalizeElements() { +MaybeObject* JSObject::NormalizeElements() { ASSERT(!HasPixelElements() && !HasExternalArrayElements()); if (HasDictionaryElements()) return this; ASSERT(map()->has_fast_elements()); - Object* obj = map()->GetSlowElementsMap(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = map()->GetSlowElementsMap(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } Map* new_map = Map::cast(obj); // Get number of entries. @@ -2288,16 +2386,20 @@ Object* JSObject::NormalizeElements() { int length = IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value() : array->length(); - obj = NumberDictionary::Allocate(length); - if (obj->IsFailure()) return obj; + { MaybeObject* maybe_obj = NumberDictionary::Allocate(length); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } NumberDictionary* dictionary = NumberDictionary::cast(obj); // Copy entries. for (int i = 0; i < length; i++) { Object* value = array->get(i); if (!value->IsTheHole()) { PropertyDetails details = PropertyDetails(NONE, NORMAL); - Object* result = dictionary->AddNumberEntry(i, array->get(i), details); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + dictionary->AddNumberEntry(i, array->get(i), details); + if (!maybe_result->ToObject(&result)) return maybe_result; + } dictionary = NumberDictionary::cast(result); } } @@ -2320,21 +2422,24 @@ Object* JSObject::NormalizeElements() { } -Object* JSObject::DeletePropertyPostInterceptor(String* name, DeleteMode mode) { +MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, + DeleteMode mode) { // Check local property, ignore interceptor. LookupResult result; LocalLookupRealNamedProperty(name, &result); if (!result.IsProperty()) return Heap::true_value(); // Normalize object if needed. - Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return DeleteNormalizedProperty(name, mode); } -Object* JSObject::DeletePropertyWithInterceptor(String* name) { +MaybeObject* JSObject::DeletePropertyWithInterceptor(String* name) { HandleScope scope; Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); Handle<String> name_handle(name); @@ -2357,20 +2462,22 @@ Object* JSObject::DeletePropertyWithInterceptor(String* name) { return *v8::Utils::OpenHandle(*result); } } - Object* raw_result = + MaybeObject* raw_result = this_handle->DeletePropertyPostInterceptor(*name_handle, NORMAL_DELETION); RETURN_IF_SCHEDULED_EXCEPTION(); return raw_result; } -Object* JSObject::DeleteElementPostInterceptor(uint32_t index, - DeleteMode mode) { +MaybeObject* JSObject::DeleteElementPostInterceptor(uint32_t index, + DeleteMode mode) { ASSERT(!HasPixelElements() && !HasExternalArrayElements()); switch (GetElementsKind()) { case FAST_ELEMENTS: { - Object* obj = EnsureWritableFastElements(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureWritableFastElements(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } uint32_t length = IsJSArray() ? static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : static_cast<uint32_t>(FixedArray::cast(elements())->length()); @@ -2395,7 +2502,7 @@ Object* JSObject::DeleteElementPostInterceptor(uint32_t index, } -Object* JSObject::DeleteElementWithInterceptor(uint32_t index) { +MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { // Make sure that the top context does not change when doing // callbacks or interceptor calls. AssertNoContextChange ncc; @@ -2419,14 +2526,14 @@ Object* JSObject::DeleteElementWithInterceptor(uint32_t index) { ASSERT(result->IsBoolean()); return *v8::Utils::OpenHandle(*result); } - Object* raw_result = + MaybeObject* raw_result = this_handle->DeleteElementPostInterceptor(index, NORMAL_DELETION); RETURN_IF_SCHEDULED_EXCEPTION(); return raw_result; } -Object* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { +MaybeObject* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { // Check access rights if needed. if (IsAccessCheckNeeded() && !Top::MayIndexedAccess(this, index, v8::ACCESS_DELETE)) { @@ -2451,8 +2558,10 @@ Object* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { switch (GetElementsKind()) { case FAST_ELEMENTS: { - Object* obj = EnsureWritableFastElements(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureWritableFastElements(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } uint32_t length = IsJSArray() ? static_cast<uint32_t>(Smi::cast(JSArray::cast(this)->length())->value()) : static_cast<uint32_t>(FixedArray::cast(elements())->length()); @@ -2488,7 +2597,7 @@ Object* JSObject::DeleteElement(uint32_t index, DeleteMode mode) { } -Object* JSObject::DeleteProperty(String* name, DeleteMode mode) { +MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { // ECMA-262, 3rd, 8.6.2.5 ASSERT(name->IsString()); @@ -2526,8 +2635,11 @@ Object* JSObject::DeleteProperty(String* name, DeleteMode mode) { return DeletePropertyWithInterceptor(name); } // Normalize object if needed. - Object* obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Make sure the properties are normalized before removing the entry. return DeleteNormalizedProperty(name, mode); } @@ -2633,19 +2745,23 @@ bool JSObject::ReferencesObject(Object* obj) { } -Object* JSObject::PreventExtensions() { +MaybeObject* JSObject::PreventExtensions() { // If there are fast elements we normalize. if (HasFastElements()) { - Object* ok = NormalizeElements(); - if (ok->IsFailure()) return ok; + Object* ok; + { MaybeObject* maybe_ok = NormalizeElements(); + if (!maybe_ok->ToObject(&ok)) return maybe_ok; + } } // Make sure that we never go back to fast case. element_dictionary()->set_requires_slow_elements(); // Do a map transition, other objects with this map may still // be extensible. - Object* new_map = map()->CopyDropTransitions(); - if (new_map->IsFailure()) return new_map; + Object* new_map; + { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } Map::cast(new_map)->set_is_extensible(false); set_map(Map::cast(new_map)); ASSERT(!map()->is_extensible()); @@ -2779,8 +2895,8 @@ void JSObject::LookupCallback(String* name, LookupResult* result) { } -Object* JSObject::DefineGetterSetter(String* name, - PropertyAttributes attributes) { +MaybeObject* JSObject::DefineGetterSetter(String* name, + PropertyAttributes attributes) { // Make sure that the top context does not change when doing callbacks or // interceptor calls. AssertNoContextChange ncc; @@ -2850,8 +2966,10 @@ Object* JSObject::DefineGetterSetter(String* name, } // Allocate the fixed array to hold getter and setter. - Object* structure = Heap::AllocateFixedArray(2, TENURED); - if (structure->IsFailure()) return structure; + Object* structure; + { MaybeObject* maybe_structure = Heap::AllocateFixedArray(2, TENURED); + if (!maybe_structure->ToObject(&structure)) return maybe_structure; + } if (is_element) { return SetElementCallback(index, structure, attributes); @@ -2885,19 +3003,23 @@ bool JSObject::CanSetCallback(String* name) { } -Object* JSObject::SetElementCallback(uint32_t index, - Object* structure, - PropertyAttributes attributes) { +MaybeObject* JSObject::SetElementCallback(uint32_t index, + Object* structure, + PropertyAttributes attributes) { PropertyDetails details = PropertyDetails(attributes, CALLBACKS); // Normalize elements to make this operation simple. - Object* ok = NormalizeElements(); - if (ok->IsFailure()) return ok; + Object* ok; + { MaybeObject* maybe_ok = NormalizeElements(); + if (!maybe_ok->ToObject(&ok)) return maybe_ok; + } // Update the dictionary with the new CALLBACKS property. - Object* dict = - element_dictionary()->Set(index, structure, details); - if (dict->IsFailure()) return dict; + Object* dict; + { MaybeObject* maybe_dict = + element_dictionary()->Set(index, structure, details); + if (!maybe_dict->ToObject(&dict)) return maybe_dict; + } NumberDictionary* elements = NumberDictionary::cast(dict); elements->set_requires_slow_elements(); @@ -2908,9 +3030,9 @@ Object* JSObject::SetElementCallback(uint32_t index, } -Object* JSObject::SetPropertyCallback(String* name, - Object* structure, - PropertyAttributes attributes) { +MaybeObject* JSObject::SetPropertyCallback(String* name, + Object* structure, + PropertyAttributes attributes) { PropertyDetails details = PropertyDetails(attributes, CALLBACKS); bool convert_back_to_fast = HasFastProperties() && @@ -2918,30 +3040,39 @@ Object* JSObject::SetPropertyCallback(String* name, < DescriptorArray::kMaxNumberOfDescriptors); // Normalize object to make this operation simple. - Object* ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); - if (ok->IsFailure()) return ok; + Object* ok; + { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); + if (!maybe_ok->ToObject(&ok)) return maybe_ok; + } // For the global object allocate a new map to invalidate the global inline // caches which have a global property cell reference directly in the code. if (IsGlobalObject()) { - Object* new_map = map()->CopyDropDescriptors(); - if (new_map->IsFailure()) return new_map; + Object* new_map; + { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } set_map(Map::cast(new_map)); } // Update the dictionary with the new CALLBACKS property. - Object* result = SetNormalizedProperty(name, structure, details); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = SetNormalizedProperty(name, structure, details); + if (!maybe_result->ToObject(&result)) return maybe_result; + } if (convert_back_to_fast) { - ok = TransformToFastProperties(0); - if (ok->IsFailure()) return ok; + { MaybeObject* maybe_ok = TransformToFastProperties(0); + if (!maybe_ok->ToObject(&ok)) return maybe_ok; + } } return result; } -Object* JSObject::DefineAccessor(String* name, bool is_getter, JSFunction* fun, - PropertyAttributes attributes) { +MaybeObject* JSObject::DefineAccessor(String* name, + bool is_getter, + JSFunction* fun, + PropertyAttributes attributes) { // Check access rights if needed. if (IsAccessCheckNeeded() && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { @@ -2957,14 +3088,17 @@ Object* JSObject::DefineAccessor(String* name, bool is_getter, JSFunction* fun, fun, attributes); } - Object* array = DefineGetterSetter(name, attributes); - if (array->IsFailure() || array->IsUndefined()) return array; + Object* array; + { MaybeObject* maybe_array = DefineGetterSetter(name, attributes); + if (!maybe_array->ToObject(&array)) return maybe_array; + } + if (array->IsUndefined()) return array; FixedArray::cast(array)->set(is_getter ? 0 : 1, fun); return this; } -Object* JSObject::DefineAccessor(AccessorInfo* info) { +MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { String* name = String::cast(info->name()); // Check access rights if needed. if (IsAccessCheckNeeded() && @@ -3019,8 +3153,11 @@ Object* JSObject::DefineAccessor(AccessorInfo* info) { break; } - Object* ok = SetElementCallback(index, info, info->property_attributes()); - if (ok->IsFailure()) return ok; + Object* ok; + { MaybeObject* maybe_ok = + SetElementCallback(index, info, info->property_attributes()); + if (!maybe_ok->ToObject(&ok)) return maybe_ok; + } } else { // Lookup the name. LookupResult result; @@ -3030,8 +3167,11 @@ Object* JSObject::DefineAccessor(AccessorInfo* info) { if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) { return Heap::undefined_value(); } - Object* ok = SetPropertyCallback(name, info, info->property_attributes()); - if (ok->IsFailure()) return ok; + Object* ok; + { MaybeObject* maybe_ok = + SetPropertyCallback(name, info, info->property_attributes()); + if (!maybe_ok->ToObject(&ok)) return maybe_ok; + } } return this; @@ -3114,9 +3254,12 @@ Object* JSObject::SlowReverseLookup(Object* value) { } -Object* Map::CopyDropDescriptors() { - Object* result = Heap::AllocateMap(instance_type(), instance_size()); - if (result->IsFailure()) return result; +MaybeObject* Map::CopyDropDescriptors() { + Object* result; + { MaybeObject* maybe_result = + Heap::AllocateMap(instance_type(), instance_size()); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Map::cast(result)->set_prototype(prototype()); Map::cast(result)->set_constructor(constructor()); // Don't copy descriptors, so map transitions always remain a forest. @@ -3134,9 +3277,11 @@ Object* Map::CopyDropDescriptors() { if (pre_allocated_property_fields() > 0) { ASSERT(constructor()->IsJSFunction()); JSFunction* ctor = JSFunction::cast(constructor()); - Object* descriptors = - ctor->initial_map()->instance_descriptors()->RemoveTransitions(); - if (descriptors->IsFailure()) return descriptors; + Object* descriptors; + { MaybeObject* maybe_descriptors = + ctor->initial_map()->instance_descriptors()->RemoveTransitions(); + if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; + } Map::cast(result)->set_instance_descriptors( DescriptorArray::cast(descriptors)); Map::cast(result)->set_pre_allocated_property_fields( @@ -3150,15 +3295,18 @@ Object* Map::CopyDropDescriptors() { } -Object* Map::CopyNormalized(PropertyNormalizationMode mode, - NormalizedMapSharingMode sharing) { +MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, + NormalizedMapSharingMode sharing) { int new_instance_size = instance_size(); if (mode == CLEAR_INOBJECT_PROPERTIES) { new_instance_size -= inobject_properties() * kPointerSize; } - Object* result = Heap::AllocateMap(instance_type(), new_instance_size); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + Heap::AllocateMap(instance_type(), new_instance_size); + if (!maybe_result->ToObject(&result)) return maybe_result; + } if (mode != CLEAR_INOBJECT_PROPERTIES) { Map::cast(result)->set_inobject_properties(inobject_properties()); @@ -3182,21 +3330,28 @@ Object* Map::CopyNormalized(PropertyNormalizationMode mode, } -Object* Map::CopyDropTransitions() { - Object* new_map = CopyDropDescriptors(); - if (new_map->IsFailure()) return new_map; - Object* descriptors = instance_descriptors()->RemoveTransitions(); - if (descriptors->IsFailure()) return descriptors; +MaybeObject* Map::CopyDropTransitions() { + Object* new_map; + { MaybeObject* maybe_new_map = CopyDropDescriptors(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } + Object* descriptors; + { MaybeObject* maybe_descriptors = + instance_descriptors()->RemoveTransitions(); + if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; + } cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); return new_map; } -Object* Map::UpdateCodeCache(String* name, Code* code) { +MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { // Allocate the code cache if not present. if (code_cache()->IsFixedArray()) { - Object* result = Heap::AllocateCodeCache(); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::AllocateCodeCache(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } set_code_cache(result); } @@ -3273,7 +3428,7 @@ void Map::TraverseTransitionTree(TraverseCallback callback, void* data) { } -Object* CodeCache::Update(String* name, Code* code) { +MaybeObject* CodeCache::Update(String* name, Code* code) { ASSERT(code->ic_state() == MONOMORPHIC); // The number of monomorphic stubs for normal load/store/call IC's can grow to @@ -3282,9 +3437,11 @@ Object* CodeCache::Update(String* name, Code* code) { if (code->type() == NORMAL) { // Make sure that a hash table is allocated for the normal load code cache. if (normal_type_cache()->IsUndefined()) { - Object* result = - CodeCacheHashTable::Allocate(CodeCacheHashTable::kInitialSize); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + CodeCacheHashTable::Allocate(CodeCacheHashTable::kInitialSize); + if (!maybe_result->ToObject(&result)) return maybe_result; + } set_normal_type_cache(result); } return UpdateNormalTypeCache(name, code); @@ -3295,7 +3452,7 @@ Object* CodeCache::Update(String* name, Code* code) { } -Object* CodeCache::UpdateDefaultCache(String* name, Code* code) { +MaybeObject* CodeCache::UpdateDefaultCache(String* name, Code* code) { // When updating the default code cache we disregard the type encoded in the // flags. This allows call constant stubs to overwrite call field // stubs, etc. @@ -3341,8 +3498,10 @@ Object* CodeCache::UpdateDefaultCache(String* name, Code* code) { int new_length = length + ((length >> 1)) + kCodeCacheEntrySize; new_length = new_length - new_length % kCodeCacheEntrySize; ASSERT((new_length % kCodeCacheEntrySize) == 0); - Object* result = cache->CopySize(new_length); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = cache->CopySize(new_length); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Add the (name, code) pair to the new cache. cache = FixedArray::cast(result); @@ -3353,11 +3512,13 @@ Object* CodeCache::UpdateDefaultCache(String* name, Code* code) { } -Object* CodeCache::UpdateNormalTypeCache(String* name, Code* code) { +MaybeObject* CodeCache::UpdateNormalTypeCache(String* name, Code* code) { // Adding a new entry can cause a new cache to be allocated. CodeCacheHashTable* cache = CodeCacheHashTable::cast(normal_type_cache()); - Object* new_cache = cache->Put(name, code); - if (new_cache->IsFailure()) return new_cache; + Object* new_cache; + { MaybeObject* maybe_new_cache = cache->Put(name, code); + if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache; + } set_normal_type_cache(new_cache); return this; } @@ -3475,10 +3636,12 @@ class CodeCacheHashTableKey : public HashTableKey { return NameFlagsHashHelper(name, code->flags()); } - Object* AsObject() { + MUST_USE_RESULT MaybeObject* AsObject() { ASSERT(code_ != NULL); - Object* obj = Heap::AllocateFixedArray(2); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArray(2); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray* pair = FixedArray::cast(obj); pair->set(0, name_); pair->set(1, code_); @@ -3500,17 +3663,21 @@ Object* CodeCacheHashTable::Lookup(String* name, Code::Flags flags) { } -Object* CodeCacheHashTable::Put(String* name, Code* code) { +MaybeObject* CodeCacheHashTable::Put(String* name, Code* code) { CodeCacheHashTableKey key(name, code); - Object* obj = EnsureCapacity(1, &key); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureCapacity(1, &key); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Don't use this, as the table might have grown. CodeCacheHashTable* cache = reinterpret_cast<CodeCacheHashTable*>(obj); int entry = cache->FindInsertionEntry(key.Hash()); - Object* k = key.AsObject(); - if (k->IsFailure()) return k; + Object* k; + { MaybeObject* maybe_k = key.AsObject(); + if (!maybe_k->ToObject(&k)) return maybe_k; + } cache->set(EntryToIndex(entry), k); cache->set(EntryToIndex(entry) + 1, code); @@ -3548,7 +3715,7 @@ static bool HasKey(FixedArray* array, Object* key) { } -Object* FixedArray::AddKeysFromJSArray(JSArray* array) { +MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { ASSERT(!array->HasPixelElements() && !array->HasExternalArrayElements()); switch (array->GetElementsKind()) { case JSObject::FAST_ELEMENTS: @@ -3558,8 +3725,10 @@ Object* FixedArray::AddKeysFromJSArray(JSArray* array) { int size = dict->NumberOfElements(); // Allocate a temporary fixed array. - Object* object = Heap::AllocateFixedArray(size); - if (object->IsFailure()) return object; + Object* object; + { MaybeObject* maybe_object = Heap::AllocateFixedArray(size); + if (!maybe_object->ToObject(&object)) return maybe_object; + } FixedArray* key_array = FixedArray::cast(object); int capacity = dict->Capacity(); @@ -3581,7 +3750,7 @@ Object* FixedArray::AddKeysFromJSArray(JSArray* array) { } -Object* FixedArray::UnionOfKeys(FixedArray* other) { +MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { int len0 = length(); #ifdef DEBUG if (FLAG_enable_slow_asserts) { @@ -3606,8 +3775,10 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) { if (extra == 0) return this; // Allocate the result - Object* obj = Heap::AllocateFixedArray(len0 + extra); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArray(len0 + extra); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Fill in the content AssertNoAllocation no_gc; FixedArray* result = FixedArray::cast(obj); @@ -3633,10 +3804,12 @@ Object* FixedArray::UnionOfKeys(FixedArray* other) { } -Object* FixedArray::CopySize(int new_length) { +MaybeObject* FixedArray::CopySize(int new_length) { if (new_length == 0) return Heap::empty_fixed_array(); - Object* obj = Heap::AllocateFixedArray(new_length); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArray(new_length); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray* result = FixedArray::cast(obj); // Copy the content AssertNoAllocation no_gc; @@ -3671,20 +3844,24 @@ bool FixedArray::IsEqualTo(FixedArray* other) { #endif -Object* DescriptorArray::Allocate(int number_of_descriptors) { +MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { if (number_of_descriptors == 0) { return Heap::empty_descriptor_array(); } // Allocate the array of keys. - Object* array = - Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors)); - if (array->IsFailure()) return array; + Object* array; + { MaybeObject* maybe_array = + Heap::AllocateFixedArray(ToKeyIndex(number_of_descriptors)); + if (!maybe_array->ToObject(&array)) return maybe_array; + } // Do not use DescriptorArray::cast on incomplete object. FixedArray* result = FixedArray::cast(array); // Allocate the content array and set it in the descriptor array. - array = Heap::AllocateFixedArray(number_of_descriptors << 1); - if (array->IsFailure()) return array; + { MaybeObject* maybe_array = + Heap::AllocateFixedArray(number_of_descriptors << 1); + if (!maybe_array->ToObject(&array)) return maybe_array; + } result->set(kContentArrayIndex, array); result->set(kEnumerationIndexIndex, Smi::FromInt(PropertyDetails::kInitialIndex)); @@ -3710,8 +3887,8 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, } -Object* DescriptorArray::CopyInsert(Descriptor* descriptor, - TransitionFlag transition_flag) { +MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor, + TransitionFlag transition_flag) { // Transitions are only kept when inserting another transition. // This precondition is not required by this function's implementation, but // is currently required by the semantics of maps, so we check it. @@ -3722,8 +3899,10 @@ Object* DescriptorArray::CopyInsert(Descriptor* descriptor, ASSERT(descriptor->GetDetails().type() != NULL_DESCRIPTOR); // Ensure the key is a symbol. - Object* result = descriptor->KeyToSymbol(); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = descriptor->KeyToSymbol(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } int transitions = 0; int null_descriptors = 0; @@ -3763,8 +3942,9 @@ Object* DescriptorArray::CopyInsert(Descriptor* descriptor, ++new_size; } } - result = Allocate(new_size); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = Allocate(new_size); + if (!maybe_result->ToObject(&result)) return maybe_result; + } DescriptorArray* new_descriptors = DescriptorArray::cast(result); // Set the enumeration index in the descriptors and set the enumeration index // in the result. @@ -3812,7 +3992,7 @@ Object* DescriptorArray::CopyInsert(Descriptor* descriptor, } -Object* DescriptorArray::RemoveTransitions() { +MaybeObject* DescriptorArray::RemoveTransitions() { // Remove all transitions and null descriptors. Return a copy of the array // with all transitions removed, or a Failure object if the new array could // not be allocated. @@ -3824,8 +4004,10 @@ Object* DescriptorArray::RemoveTransitions() { } // Allocate the new descriptor array. - Object* result = Allocate(number_of_descriptors() - num_removed); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Allocate(number_of_descriptors() - num_removed); + if (!maybe_result->ToObject(&result)) return maybe_result; + } DescriptorArray* new_descriptors = DescriptorArray::cast(result); // Copy the content. @@ -5063,9 +5245,9 @@ uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer, } -Object* String::SubString(int start, int end, PretenureFlag pretenure) { +MaybeObject* String::SubString(int start, int end, PretenureFlag pretenure) { if (start == 0 && end == length()) return this; - Object* result = Heap::AllocateSubString(this, start, end, pretenure); + MaybeObject* result = Heap::AllocateSubString(this, start, end, pretenure); return result; } @@ -5166,7 +5348,7 @@ Object* JSFunction::SetInstancePrototype(Object* value) { } -Object* JSFunction::SetPrototype(Object* value) { +MaybeObject* JSFunction::SetPrototype(Object* value) { ASSERT(should_have_prototype()); Object* construct_prototype = value; @@ -5178,8 +5360,10 @@ Object* JSFunction::SetPrototype(Object* value) { // Copy the map so this does not affect unrelated functions. // Remove map transitions because they point to maps with a // different prototype. - Object* new_map = map()->CopyDropTransitions(); - if (new_map->IsFailure()) return new_map; + Object* new_map; + { MaybeObject* maybe_new_map = map()->CopyDropTransitions(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } set_map(Map::cast(new_map)); map()->set_constructor(value); map()->set_non_instance_prototype(true); @@ -5212,9 +5396,11 @@ Context* JSFunction::GlobalContextFromLiterals(FixedArray* literals) { } -Object* Oddball::Initialize(const char* to_string, Object* to_number) { - Object* symbol = Heap::LookupAsciiSymbol(to_string); - if (symbol->IsFailure()) return symbol; +MaybeObject* Oddball::Initialize(const char* to_string, Object* to_number) { + Object* symbol; + { MaybeObject* maybe_symbol = Heap::LookupAsciiSymbol(to_string); + if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol; + } set_to_string(String::cast(symbol)); set_to_number(to_number); return this; @@ -5703,16 +5889,20 @@ void Code::Disassemble(const char* name) { #endif // ENABLE_DISASSEMBLER -Object* JSObject::SetFastElementsCapacityAndLength(int capacity, int length) { +MaybeObject* JSObject::SetFastElementsCapacityAndLength(int capacity, + int length) { // We should never end in here with a pixel or external array. ASSERT(!HasPixelElements() && !HasExternalArrayElements()); - Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(capacity); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray* elems = FixedArray::cast(obj); - obj = map()->GetFastElementsMap(); - if (obj->IsFailure()) return obj; + { MaybeObject* maybe_obj = map()->GetFastElementsMap(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } Map* new_map = Map::cast(obj); AssertNoAllocation no_gc; @@ -5754,7 +5944,7 @@ Object* JSObject::SetFastElementsCapacityAndLength(int capacity, int length) { } -Object* JSObject::SetSlowElements(Object* len) { +MaybeObject* JSObject::SetSlowElements(Object* len) { // We should never end in here with a pixel or external array. ASSERT(!HasPixelElements() && !HasExternalArrayElements()); @@ -5765,8 +5955,10 @@ Object* JSObject::SetSlowElements(Object* len) { // Make sure we never try to shrink dense arrays into sparse arrays. ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= new_length); - Object* obj = NormalizeElements(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = NormalizeElements(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Update length for JSArrays. if (IsJSArray()) JSArray::cast(this)->set_length(len); @@ -5789,15 +5981,17 @@ Object* JSObject::SetSlowElements(Object* len) { } -Object* JSArray::Initialize(int capacity) { +MaybeObject* JSArray::Initialize(int capacity) { ASSERT(capacity >= 0); set_length(Smi::FromInt(0)); FixedArray* new_elements; if (capacity == 0) { new_elements = Heap::empty_fixed_array(); } else { - Object* obj = Heap::AllocateFixedArrayWithHoles(capacity); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArrayWithHoles(capacity); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } new_elements = FixedArray::cast(obj); } set_elements(new_elements); @@ -5824,19 +6018,20 @@ static int NewElementsCapacity(int old_capacity) { } -static Object* ArrayLengthRangeError() { +static Failure* ArrayLengthRangeError() { HandleScope scope; return Top::Throw(*Factory::NewRangeError("invalid_array_length", HandleVector<Object>(NULL, 0))); } -Object* JSObject::SetElementsLength(Object* len) { +MaybeObject* JSObject::SetElementsLength(Object* len) { // We should never end in here with a pixel or external array. ASSERT(AllowsSetElementsLength()); - Object* smi_length = len->ToSmi(); - if (smi_length->IsSmi()) { + MaybeObject* maybe_smi_length = len->ToSmi(); + Object* smi_length = Smi::FromInt(0); + if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { const int value = Smi::cast(smi_length)->value(); if (value < 0) return ArrayLengthRangeError(); switch (GetElementsKind()) { @@ -5844,8 +6039,10 @@ Object* JSObject::SetElementsLength(Object* len) { int old_capacity = FixedArray::cast(elements())->length(); if (value <= old_capacity) { if (IsJSArray()) { - Object* obj = EnsureWritableFastElements(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureWritableFastElements(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } int old_length = FastD2I(JSArray::cast(this)->length()->Number()); // NOTE: We may be able to optimize this by removing the // last part of the elements backing storage array and @@ -5861,8 +6058,11 @@ Object* JSObject::SetElementsLength(Object* len) { int new_capacity = value > min ? value : min; if (new_capacity <= kMaxFastElementsLength || !ShouldConvertToSlowElements(new_capacity)) { - Object* obj = SetFastElementsCapacityAndLength(new_capacity, value); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + SetFastElementsCapacityAndLength(new_capacity, value); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return this; } break; @@ -5873,8 +6073,10 @@ Object* JSObject::SetElementsLength(Object* len) { // If the length of a slow array is reset to zero, we clear // the array and flush backing storage. This has the added // benefit that the array returns to fast mode. - Object* obj = ResetElements(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = ResetElements(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } } else { // Remove deleted elements. uint32_t old_length = @@ -5903,8 +6105,10 @@ Object* JSObject::SetElementsLength(Object* len) { // len is not a number so make the array size one and // set only element to len. - Object* obj = Heap::AllocateFixedArray(1); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArray(1); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray::cast(obj)->set(0, len); if (IsJSArray()) JSArray::cast(this)->set_length(Smi::FromInt(1)); set_elements(FixedArray::cast(obj)); @@ -5912,8 +6116,8 @@ Object* JSObject::SetElementsLength(Object* len) { } -Object* JSObject::SetPrototype(Object* value, - bool skip_hidden_prototypes) { +MaybeObject* JSObject::SetPrototype(Object* value, + bool skip_hidden_prototypes) { // Silently ignore the change if value is not a JSObject or null. // SpiderMonkey behaves this way. if (!value->IsJSObject() && !value->IsNull()) return value; @@ -5945,8 +6149,10 @@ Object* JSObject::SetPrototype(Object* value, } // Set the new prototype of the object. - Object* new_map = real_receiver->map()->CopyDropTransitions(); - if (new_map->IsFailure()) return new_map; + Object* new_map; + { MaybeObject* maybe_new_map = real_receiver->map()->CopyDropTransitions(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } Map::cast(new_map)->set_prototype(value); real_receiver->set_map(Map::cast(new_map)); @@ -6179,7 +6385,8 @@ bool JSObject::HasElementWithReceiver(JSObject* receiver, uint32_t index) { } -Object* JSObject::SetElementWithInterceptor(uint32_t index, Object* value) { +MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, + Object* value) { // Make sure that the top context does not change when doing // callbacks or interceptor calls. AssertNoContextChange ncc; @@ -6202,17 +6409,17 @@ Object* JSObject::SetElementWithInterceptor(uint32_t index, Object* value) { RETURN_IF_SCHEDULED_EXCEPTION(); if (!result.IsEmpty()) return *value_handle; } - Object* raw_result = + MaybeObject* raw_result = this_handle->SetElementWithoutInterceptor(index, *value_handle); RETURN_IF_SCHEDULED_EXCEPTION(); return raw_result; } -Object* JSObject::GetElementWithCallback(Object* receiver, - Object* structure, - uint32_t index, - Object* holder) { +MaybeObject* JSObject::GetElementWithCallback(Object* receiver, + Object* structure, + uint32_t index, + Object* holder) { ASSERT(!structure->IsProxy()); // api style callbacks. @@ -6255,10 +6462,10 @@ Object* JSObject::GetElementWithCallback(Object* receiver, } -Object* JSObject::SetElementWithCallback(Object* structure, - uint32_t index, - Object* value, - JSObject* holder) { +MaybeObject* JSObject::SetElementWithCallback(Object* structure, + uint32_t index, + Object* value, + JSObject* holder) { HandleScope scope; // We should never get here to initialize a const with the hole @@ -6314,11 +6521,13 @@ Object* JSObject::SetElementWithCallback(Object* structure, // Adding n elements in fast case is O(n*n). // Note: revisit design to have dual undefined values to capture absent // elements. -Object* JSObject::SetFastElement(uint32_t index, Object* value) { +MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) { ASSERT(HasFastElements()); - Object* elms_obj = EnsureWritableFastElements(); - if (elms_obj->IsFailure()) return elms_obj; + Object* elms_obj; + { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); + if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; + } FixedArray* elms = FixedArray::cast(elms_obj); uint32_t elms_length = static_cast<uint32_t>(elms->length()); @@ -6349,22 +6558,27 @@ Object* JSObject::SetFastElement(uint32_t index, Object* value) { if (new_capacity <= kMaxFastElementsLength || !ShouldConvertToSlowElements(new_capacity)) { ASSERT(static_cast<uint32_t>(new_capacity) > index); - Object* obj = SetFastElementsCapacityAndLength(new_capacity, index + 1); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + SetFastElementsCapacityAndLength(new_capacity, index + 1); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray::cast(elements())->set(index, value); return value; } } // Otherwise default to slow case. - Object* obj = NormalizeElements(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = NormalizeElements(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } ASSERT(HasDictionaryElements()); return SetElement(index, value); } -Object* JSObject::SetElement(uint32_t index, Object* value) { +MaybeObject* JSObject::SetElement(uint32_t index, Object* value) { // Check access rights if needed. if (IsAccessCheckNeeded() && !Top::MayIndexedAccess(this, index, v8::ACCESS_SET)) { @@ -6390,7 +6604,8 @@ Object* JSObject::SetElement(uint32_t index, Object* value) { } -Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { +MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, + Object* value) { switch (GetElementsKind()) { case FAST_ELEMENTS: // Fast case. @@ -6461,8 +6676,10 @@ Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { return Top::Throw(*Factory::NewTypeError("object_not_extensible", HandleVector(args, 1))); } - Object* result = dictionary->AtNumberPut(index, value); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = dictionary->AtNumberPut(index, value); + if (!maybe_result->ToObject(&result)) return maybe_result; + } if (elms != FixedArray::cast(result)) { set_elements(FixedArray::cast(result)); } @@ -6471,9 +6688,13 @@ Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { // Update the array length if this JSObject is an array. if (IsJSArray()) { JSArray* array = JSArray::cast(this); - Object* return_value = array->JSArrayUpdateLengthFromIndex(index, - value); - if (return_value->IsFailure()) return return_value; + Object* return_value; + { MaybeObject* maybe_return_value = + array->JSArrayUpdateLengthFromIndex(index, value); + if (!maybe_return_value->ToObject(&return_value)) { + return maybe_return_value; + } + } } // Attempt to put this object back in fast case. @@ -6484,8 +6705,11 @@ Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { } else { new_length = NumberDictionary::cast(elements())->max_number_key() + 1; } - Object* obj = SetFastElementsCapacityAndLength(new_length, new_length); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + SetFastElementsCapacityAndLength(new_length, new_length); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } #ifdef DEBUG if (FLAG_trace_normalization) { PrintF("Object elements are fast case again:\n"); @@ -6507,23 +6731,26 @@ Object* JSObject::SetElementWithoutInterceptor(uint32_t index, Object* value) { } -Object* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, Object* value) { +MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, + Object* value) { uint32_t old_len = 0; CHECK(length()->ToArrayIndex(&old_len)); // Check to see if we need to update the length. For now, we make // sure that the length stays within 32-bits (unsigned). if (index >= old_len && index != 0xffffffff) { - Object* len = - Heap::NumberFromDouble(static_cast<double>(index) + 1); - if (len->IsFailure()) return len; + Object* len; + { MaybeObject* maybe_len = + Heap::NumberFromDouble(static_cast<double>(index) + 1); + if (!maybe_len->ToObject(&len)) return maybe_len; + } set_length(len); } return value; } -Object* JSObject::GetElementPostInterceptor(JSObject* receiver, - uint32_t index) { +MaybeObject* JSObject::GetElementPostInterceptor(JSObject* receiver, + uint32_t index) { // Get element works for both JSObject and JSArray since // JSArray::length cannot change. switch (GetElementsKind()) { @@ -6579,8 +6806,8 @@ Object* JSObject::GetElementPostInterceptor(JSObject* receiver, } -Object* JSObject::GetElementWithInterceptor(JSObject* receiver, - uint32_t index) { +MaybeObject* JSObject::GetElementWithInterceptor(JSObject* receiver, + uint32_t index) { // Make sure that the top context does not change when doing // callbacks or interceptor calls. AssertNoContextChange ncc; @@ -6605,14 +6832,15 @@ Object* JSObject::GetElementWithInterceptor(JSObject* receiver, if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result); } - Object* raw_result = + MaybeObject* raw_result = holder_handle->GetElementPostInterceptor(*this_handle, index); RETURN_IF_SCHEDULED_EXCEPTION(); return raw_result; } -Object* JSObject::GetElementWithReceiver(JSObject* receiver, uint32_t index) { +MaybeObject* JSObject::GetElementWithReceiver(JSObject* receiver, + uint32_t index) { // Check access rights if needed. if (IsAccessCheckNeeded() && !Top::MayIndexedAccess(this, index, v8::ACCESS_GET)) { @@ -6863,9 +7091,10 @@ InterceptorInfo* JSObject::GetIndexedInterceptor() { } -Object* JSObject::GetPropertyPostInterceptor(JSObject* receiver, - String* name, - PropertyAttributes* attributes) { +MaybeObject* JSObject::GetPropertyPostInterceptor( + JSObject* receiver, + String* name, + PropertyAttributes* attributes) { // Check local property in holder, ignore interceptor. LookupResult result; LocalLookupRealNamedProperty(name, &result); @@ -6880,7 +7109,7 @@ Object* JSObject::GetPropertyPostInterceptor(JSObject* receiver, } -Object* JSObject::GetLocalPropertyPostInterceptor( +MaybeObject* JSObject::GetLocalPropertyPostInterceptor( JSObject* receiver, String* name, PropertyAttributes* attributes) { @@ -6894,7 +7123,7 @@ Object* JSObject::GetLocalPropertyPostInterceptor( } -Object* JSObject::GetPropertyWithInterceptor( +MaybeObject* JSObject::GetPropertyWithInterceptor( JSObject* receiver, String* name, PropertyAttributes* attributes) { @@ -6923,7 +7152,7 @@ Object* JSObject::GetPropertyWithInterceptor( } } - Object* result = holder_handle->GetPropertyPostInterceptor( + MaybeObject* result = holder_handle->GetPropertyPostInterceptor( *receiver_handle, *name_handle, attributes); @@ -7278,7 +7507,7 @@ uint32_t NumberDictionaryShape::HashForObject(uint32_t key, Object* other) { } -Object* NumberDictionaryShape::AsObject(uint32_t key) { +MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) { return Heap::NumberFromUint32(key); } @@ -7301,7 +7530,7 @@ uint32_t StringDictionaryShape::HashForObject(String* key, Object* other) { } -Object* StringDictionaryShape::AsObject(String* key) { +MaybeObject* StringDictionaryShape::AsObject(String* key) { return key; } @@ -7375,9 +7604,11 @@ class StringSharedKey : public HashTableKey { return StringSharedHashHelper(source, shared); } - Object* AsObject() { - Object* obj = Heap::AllocateFixedArray(2); - if (obj->IsFailure()) return obj; + MUST_USE_RESULT MaybeObject* AsObject() { + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArray(2); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray* pair = FixedArray::cast(obj); pair->set(0, shared_); pair->set(1, source_); @@ -7455,7 +7686,7 @@ class Utf8SymbolKey : public HashTableKey { return String::cast(other)->Hash(); } - Object* AsObject() { + MaybeObject* AsObject() { if (hash_field_ == 0) Hash(); return Heap::AllocateSymbol(string_, chars_, hash_field_); } @@ -7481,7 +7712,7 @@ class SymbolKey : public HashTableKey { return String::cast(other)->Hash(); } - Object* AsObject() { + MaybeObject* AsObject() { // Attempt to flatten the string, so that symbols will most often // be flat strings. string_ = string_->TryFlattenGetString(); @@ -7522,8 +7753,8 @@ void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) { template<typename Shape, typename Key> -Object* HashTable<Shape, Key>::Allocate(int at_least_space_for, - PretenureFlag pretenure) { +MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for, + PretenureFlag pretenure) { const int kMinCapacity = 32; int capacity = RoundUpToPowerOf2(at_least_space_for * 2); if (capacity < kMinCapacity) { @@ -7532,12 +7763,14 @@ Object* HashTable<Shape, Key>::Allocate(int at_least_space_for, return Failure::OutOfMemoryException(); } - Object* obj = Heap::AllocateHashTable(EntryToIndex(capacity), pretenure); - if (!obj->IsFailure()) { - HashTable::cast(obj)->SetNumberOfElements(0); - HashTable::cast(obj)->SetNumberOfDeletedElements(0); - HashTable::cast(obj)->SetCapacity(capacity); + Object* obj; + { MaybeObject* maybe_obj = + Heap::AllocateHashTable(EntryToIndex(capacity), pretenure); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; } + HashTable::cast(obj)->SetNumberOfElements(0); + HashTable::cast(obj)->SetNumberOfDeletedElements(0); + HashTable::cast(obj)->SetCapacity(capacity); return obj; } @@ -7600,7 +7833,7 @@ int StringDictionary::FindEntry(String* key) { template<typename Shape, typename Key> -Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { +MaybeObject* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { int capacity = Capacity(); int nof = NumberOfElements() + n; int nod = NumberOfDeletedElements(); @@ -7615,8 +7848,11 @@ Object* HashTable<Shape, Key>::EnsureCapacity(int n, Key key) { const int kMinCapacityForPretenure = 256; bool pretenure = (capacity > kMinCapacityForPretenure) && !Heap::InNewSpace(this); - Object* obj = Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + Allocate(nof * 2, pretenure ? TENURED : NOT_TENURED); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } AssertNoAllocation no_gc; HashTable* table = HashTable::cast(obj); @@ -7674,13 +7910,13 @@ template class Dictionary<StringDictionaryShape, String*>; template class Dictionary<NumberDictionaryShape, uint32_t>; -template Object* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( +template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( int); -template Object* Dictionary<StringDictionaryShape, String*>::Allocate( +template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate( int); -template Object* Dictionary<NumberDictionaryShape, uint32_t>::AtPut( +template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AtPut( uint32_t, Object*); template Object* Dictionary<NumberDictionaryShape, uint32_t>::SlowReverseLookup( @@ -7705,29 +7941,29 @@ template int Dictionary<StringDictionaryShape, String*>::NumberOfElementsFilterAttributes( PropertyAttributes); -template Object* Dictionary<StringDictionaryShape, String*>::Add( +template MaybeObject* Dictionary<StringDictionaryShape, String*>::Add( String*, Object*, PropertyDetails); -template Object* +template MaybeObject* Dictionary<StringDictionaryShape, String*>::GenerateNewEnumerationIndices(); template int Dictionary<NumberDictionaryShape, uint32_t>::NumberOfElementsFilterAttributes( PropertyAttributes); -template Object* Dictionary<NumberDictionaryShape, uint32_t>::Add( +template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Add( uint32_t, Object*, PropertyDetails); -template Object* Dictionary<NumberDictionaryShape, uint32_t>::EnsureCapacity( - int, uint32_t); +template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>:: + EnsureCapacity(int, uint32_t); -template Object* Dictionary<StringDictionaryShape, String*>::EnsureCapacity( - int, String*); +template MaybeObject* Dictionary<StringDictionaryShape, String*>:: + EnsureCapacity(int, String*); -template Object* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry( +template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::AddEntry( uint32_t, Object*, PropertyDetails, uint32_t); -template Object* Dictionary<StringDictionaryShape, String*>::AddEntry( +template MaybeObject* Dictionary<StringDictionaryShape, String*>::AddEntry( String*, Object*, PropertyDetails, uint32_t); template @@ -7742,7 +7978,7 @@ int HashTable<NumberDictionaryShape, uint32_t>::FindEntry(uint32_t); // Collates undefined and unexisting elements below limit from position // zero of the elements. The object stays in Dictionary mode. -Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { +MaybeObject* JSObject::PrepareSlowElementsForSort(uint32_t limit) { ASSERT(HasDictionaryElements()); // Must stay in dictionary mode, either because of requires_slow_elements, // or because we are not going to sort (and therefore compact) all of the @@ -7751,13 +7987,18 @@ Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { HeapNumber* result_double = NULL; if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { // Allocate space for result before we start mutating the object. - Object* new_double = Heap::AllocateHeapNumber(0.0); - if (new_double->IsFailure()) return new_double; + Object* new_double; + { MaybeObject* maybe_new_double = Heap::AllocateHeapNumber(0.0); + if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; + } result_double = HeapNumber::cast(new_double); } - Object* obj = NumberDictionary::Allocate(dict->NumberOfElements()); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + NumberDictionary::Allocate(dict->NumberOfElements()); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } NumberDictionary* new_dict = NumberDictionary::cast(obj); AssertNoAllocation no_alloc; @@ -7779,15 +8020,18 @@ Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { return Smi::FromInt(-1); } uint32_t key = NumberToUint32(k); + // In the following we assert that adding the entry to the new dictionary + // does not cause GC. This is the case because we made sure to allocate + // the dictionary big enough above, so it need not grow. if (key < limit) { if (value->IsUndefined()) { undefs++; } else { - new_dict->AddNumberEntry(pos, value, details); + new_dict->AddNumberEntry(pos, value, details)->ToObjectUnchecked(); pos++; } } else { - new_dict->AddNumberEntry(key, value, details); + new_dict->AddNumberEntry(key, value, details)->ToObjectUnchecked(); } } } @@ -7795,7 +8039,8 @@ Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { uint32_t result = pos; PropertyDetails no_details = PropertyDetails(NONE, NORMAL); while (undefs > 0) { - new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details); + new_dict->AddNumberEntry(pos, Heap::undefined_value(), no_details)-> + ToObjectUnchecked(); pos++; undefs--; } @@ -7816,7 +8061,7 @@ Object* JSObject::PrepareSlowElementsForSort(uint32_t limit) { // the start of the elements array. // If the object is in dictionary mode, it is converted to fast elements // mode. -Object* JSObject::PrepareElementsForSort(uint32_t limit) { +MaybeObject* JSObject::PrepareElementsForSort(uint32_t limit) { ASSERT(!HasPixelElements() && !HasExternalArrayElements()); if (HasDictionaryElements()) { @@ -7829,22 +8074,28 @@ Object* JSObject::PrepareElementsForSort(uint32_t limit) { } // Convert to fast elements. - Object* obj = map()->GetFastElementsMap(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = map()->GetFastElementsMap(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } Map* new_map = Map::cast(obj); PretenureFlag tenure = Heap::InNewSpace(this) ? NOT_TENURED: TENURED; - Object* new_array = - Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); - if (new_array->IsFailure()) return new_array; + Object* new_array; + { MaybeObject* maybe_new_array = + Heap::AllocateFixedArray(dict->NumberOfElements(), tenure); + if (!maybe_new_array->ToObject(&new_array)) return maybe_new_array; + } FixedArray* fast_elements = FixedArray::cast(new_array); dict->CopyValuesTo(fast_elements); set_map(new_map); set_elements(fast_elements); } else { - Object* obj = EnsureWritableFastElements(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureWritableFastElements(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } } ASSERT(HasFastElements()); @@ -7864,8 +8115,10 @@ Object* JSObject::PrepareElementsForSort(uint32_t limit) { if (limit > static_cast<uint32_t>(Smi::kMaxValue)) { // Pessimistically allocate space for return value before // we start mutating the array. - Object* new_double = Heap::AllocateHeapNumber(0.0); - if (new_double->IsFailure()) return new_double; + Object* new_double; + { MaybeObject* maybe_new_double = Heap::AllocateHeapNumber(0.0); + if (!maybe_new_double->ToObject(&new_double)) return maybe_new_double; + } result_double = HeapNumber::cast(new_double); } @@ -7957,9 +8210,9 @@ Object* PixelArray::SetValue(uint32_t index, Object* value) { template<typename ExternalArrayClass, typename ValueType> -static Object* ExternalArrayIntSetter(ExternalArrayClass* receiver, - uint32_t index, - Object* value) { +static MaybeObject* ExternalArrayIntSetter(ExternalArrayClass* receiver, + uint32_t index, + Object* value) { ValueType cast_value = 0; if (index < static_cast<uint32_t>(receiver->length())) { if (value->IsSmi()) { @@ -7979,37 +8232,40 @@ static Object* ExternalArrayIntSetter(ExternalArrayClass* receiver, } -Object* ExternalByteArray::SetValue(uint32_t index, Object* value) { +MaybeObject* ExternalByteArray::SetValue(uint32_t index, Object* value) { return ExternalArrayIntSetter<ExternalByteArray, int8_t> (this, index, value); } -Object* ExternalUnsignedByteArray::SetValue(uint32_t index, Object* value) { +MaybeObject* ExternalUnsignedByteArray::SetValue(uint32_t index, + Object* value) { return ExternalArrayIntSetter<ExternalUnsignedByteArray, uint8_t> (this, index, value); } -Object* ExternalShortArray::SetValue(uint32_t index, Object* value) { +MaybeObject* ExternalShortArray::SetValue(uint32_t index, + Object* value) { return ExternalArrayIntSetter<ExternalShortArray, int16_t> (this, index, value); } -Object* ExternalUnsignedShortArray::SetValue(uint32_t index, Object* value) { +MaybeObject* ExternalUnsignedShortArray::SetValue(uint32_t index, + Object* value) { return ExternalArrayIntSetter<ExternalUnsignedShortArray, uint16_t> (this, index, value); } -Object* ExternalIntArray::SetValue(uint32_t index, Object* value) { +MaybeObject* ExternalIntArray::SetValue(uint32_t index, Object* value) { return ExternalArrayIntSetter<ExternalIntArray, int32_t> (this, index, value); } -Object* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { +MaybeObject* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { uint32_t cast_value = 0; if (index < static_cast<uint32_t>(length())) { if (value->IsSmi()) { @@ -8029,7 +8285,7 @@ Object* ExternalUnsignedIntArray::SetValue(uint32_t index, Object* value) { } -Object* ExternalFloatArray::SetValue(uint32_t index, Object* value) { +MaybeObject* ExternalFloatArray::SetValue(uint32_t index, Object* value) { float cast_value = 0; if (index < static_cast<uint32_t>(length())) { if (value->IsSmi()) { @@ -8057,16 +8313,22 @@ Object* GlobalObject::GetPropertyCell(LookupResult* result) { } -Object* GlobalObject::EnsurePropertyCell(String* name) { +MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { ASSERT(!HasFastProperties()); int entry = property_dictionary()->FindEntry(name); if (entry == StringDictionary::kNotFound) { - Object* cell = Heap::AllocateJSGlobalPropertyCell(Heap::the_hole_value()); - if (cell->IsFailure()) return cell; + Object* cell; + { MaybeObject* maybe_cell = + Heap::AllocateJSGlobalPropertyCell(Heap::the_hole_value()); + if (!maybe_cell->ToObject(&cell)) return maybe_cell; + } PropertyDetails details(NONE, NORMAL); details = details.AsDeleted(); - Object* dictionary = property_dictionary()->Add(name, cell, details); - if (dictionary->IsFailure()) return dictionary; + Object* dictionary; + { MaybeObject* maybe_dictionary = + property_dictionary()->Add(name, cell, details); + if (!maybe_dictionary->ToObject(&dictionary)) return maybe_dictionary; + } set_properties(StringDictionary::cast(dictionary)); return cell; } else { @@ -8077,7 +8339,7 @@ Object* GlobalObject::EnsurePropertyCell(String* name) { } -Object* SymbolTable::LookupString(String* string, Object** s) { +MaybeObject* SymbolTable::LookupString(String* string, Object** s) { SymbolKey key(string); return LookupKey(&key, s); } @@ -8174,13 +8436,13 @@ bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1, } -Object* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { +MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { Utf8SymbolKey key(str); return LookupKey(&key, s); } -Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) { +MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) { int entry = FindEntry(key); // Symbol already in table. @@ -8190,12 +8452,16 @@ Object* SymbolTable::LookupKey(HashTableKey* key, Object** s) { } // Adding new symbol. Grow table if needed. - Object* obj = EnsureCapacity(1, key); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureCapacity(1, key); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Create symbol object. - Object* symbol = key->AsObject(); - if (symbol->IsFailure()) return symbol; + Object* symbol; + { MaybeObject* maybe_symbol = key->AsObject(); + if (!maybe_symbol->ToObject(&symbol)) return maybe_symbol; + } // If the symbol table grew as part of EnsureCapacity, obj is not // the current symbol table and therefore we cannot use @@ -8236,10 +8502,12 @@ Object* CompilationCacheTable::LookupRegExp(String* src, } -Object* CompilationCacheTable::Put(String* src, Object* value) { +MaybeObject* CompilationCacheTable::Put(String* src, Object* value) { StringKey key(src); - Object* obj = EnsureCapacity(1, &key); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureCapacity(1, &key); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } CompilationCacheTable* cache = reinterpret_cast<CompilationCacheTable*>(obj); @@ -8251,19 +8519,23 @@ Object* CompilationCacheTable::Put(String* src, Object* value) { } -Object* CompilationCacheTable::PutEval(String* src, - Context* context, - Object* value) { +MaybeObject* CompilationCacheTable::PutEval(String* src, + Context* context, + Object* value) { StringSharedKey key(src, context->closure()->shared()); - Object* obj = EnsureCapacity(1, &key); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureCapacity(1, &key); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } CompilationCacheTable* cache = reinterpret_cast<CompilationCacheTable*>(obj); int entry = cache->FindInsertionEntry(key.Hash()); - Object* k = key.AsObject(); - if (k->IsFailure()) return k; + Object* k; + { MaybeObject* maybe_k = key.AsObject(); + if (!maybe_k->ToObject(&k)) return maybe_k; + } cache->set(EntryToIndex(entry), k); cache->set(EntryToIndex(entry) + 1, value); @@ -8272,12 +8544,14 @@ Object* CompilationCacheTable::PutEval(String* src, } -Object* CompilationCacheTable::PutRegExp(String* src, - JSRegExp::Flags flags, - FixedArray* value) { +MaybeObject* CompilationCacheTable::PutRegExp(String* src, + JSRegExp::Flags flags, + FixedArray* value) { RegExpKey key(src, flags); - Object* obj = EnsureCapacity(1, &key); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureCapacity(1, &key); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } CompilationCacheTable* cache = reinterpret_cast<CompilationCacheTable*>(obj); @@ -8333,10 +8607,12 @@ Object* MapCache::Lookup(FixedArray* array) { } -Object* MapCache::Put(FixedArray* array, Map* value) { +MaybeObject* MapCache::Put(FixedArray* array, Map* value) { SymbolsKey key(array); - Object* obj = EnsureCapacity(1, &key); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureCapacity(1, &key); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } MapCache* cache = reinterpret_cast<MapCache*>(obj); int entry = cache->FindInsertionEntry(key.Hash()); @@ -8348,32 +8624,37 @@ Object* MapCache::Put(FixedArray* array, Map* value) { template<typename Shape, typename Key> -Object* Dictionary<Shape, Key>::Allocate(int at_least_space_for) { - Object* obj = HashTable<Shape, Key>::Allocate(at_least_space_for); - // Initialize the next enumeration index. - if (!obj->IsFailure()) { - Dictionary<Shape, Key>::cast(obj)-> - SetNextEnumerationIndex(PropertyDetails::kInitialIndex); +MaybeObject* Dictionary<Shape, Key>::Allocate(int at_least_space_for) { + Object* obj; + { MaybeObject* maybe_obj = + HashTable<Shape, Key>::Allocate(at_least_space_for); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; } + // Initialize the next enumeration index. + Dictionary<Shape, Key>::cast(obj)-> + SetNextEnumerationIndex(PropertyDetails::kInitialIndex); return obj; } template<typename Shape, typename Key> -Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { +MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { int length = HashTable<Shape, Key>::NumberOfElements(); // Allocate and initialize iteration order array. - Object* obj = Heap::AllocateFixedArray(length); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArray(length); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray* iteration_order = FixedArray::cast(obj); for (int i = 0; i < length; i++) { iteration_order->set(i, Smi::FromInt(i)); } // Allocate array with enumeration order. - obj = Heap::AllocateFixedArray(length); - if (obj->IsFailure()) return obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArray(length); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } FixedArray* enumeration_order = FixedArray::cast(obj); // Fill the enumeration order array with property details. @@ -8414,13 +8695,15 @@ Object* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() { } template<typename Shape, typename Key> -Object* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) { +MaybeObject* Dictionary<Shape, Key>::EnsureCapacity(int n, Key key) { // Check whether there are enough enumeration indices to add n elements. if (Shape::kIsEnumerable && !PropertyDetails::IsValidIndex(NextEnumerationIndex() + n)) { // If not, we generate new indices for the properties. - Object* result = GenerateNewEnumerationIndices(); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = GenerateNewEnumerationIndices(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return HashTable<Shape, Key>::EnsureCapacity(n, key); } @@ -8464,7 +8747,7 @@ Object* Dictionary<Shape, Key>::DeleteProperty(int entry, template<typename Shape, typename Key> -Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { +MaybeObject* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { int entry = this->FindEntry(key); // If the entry is present set the value; @@ -8474,11 +8757,15 @@ Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { } // Check whether the dictionary should be extended. - Object* obj = EnsureCapacity(1, key); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureCapacity(1, key); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } - Object* k = Shape::AsObject(key); - if (k->IsFailure()) return k; + Object* k; + { MaybeObject* maybe_k = Shape::AsObject(key); + if (!maybe_k->ToObject(&k)) return maybe_k; + } PropertyDetails details = PropertyDetails(NONE, NORMAL); return Dictionary<Shape, Key>::cast(obj)-> AddEntry(key, value, details, Shape::Hash(key)); @@ -8486,14 +8773,16 @@ Object* Dictionary<Shape, Key>::AtPut(Key key, Object* value) { template<typename Shape, typename Key> -Object* Dictionary<Shape, Key>::Add(Key key, - Object* value, - PropertyDetails details) { +MaybeObject* Dictionary<Shape, Key>::Add(Key key, + Object* value, + PropertyDetails details) { // Valdate key is absent. SLOW_ASSERT((this->FindEntry(key) == Dictionary<Shape, Key>::kNotFound)); // Check whether the dictionary should be extended. - Object* obj = EnsureCapacity(1, key); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = EnsureCapacity(1, key); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return Dictionary<Shape, Key>::cast(obj)-> AddEntry(key, value, details, Shape::Hash(key)); } @@ -8501,13 +8790,15 @@ Object* Dictionary<Shape, Key>::Add(Key key, // Add a key, value pair to the dictionary. template<typename Shape, typename Key> -Object* Dictionary<Shape, Key>::AddEntry(Key key, - Object* value, - PropertyDetails details, - uint32_t hash) { +MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key, + Object* value, + PropertyDetails details, + uint32_t hash) { // Compute the key object. - Object* k = Shape::AsObject(key); - if (k->IsFailure()) return k; + Object* k; + { MaybeObject* maybe_k = Shape::AsObject(key); + if (!maybe_k->ToObject(&k)) return maybe_k; + } uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); // Insert element at empty or deleted entry @@ -8545,32 +8836,33 @@ void NumberDictionary::UpdateMaxNumberKey(uint32_t key) { } -Object* NumberDictionary::AddNumberEntry(uint32_t key, - Object* value, - PropertyDetails details) { +MaybeObject* NumberDictionary::AddNumberEntry(uint32_t key, + Object* value, + PropertyDetails details) { UpdateMaxNumberKey(key); SLOW_ASSERT(this->FindEntry(key) == kNotFound); return Add(key, value, details); } -Object* NumberDictionary::AtNumberPut(uint32_t key, Object* value) { +MaybeObject* NumberDictionary::AtNumberPut(uint32_t key, Object* value) { UpdateMaxNumberKey(key); return AtPut(key, value); } -Object* NumberDictionary::Set(uint32_t key, - Object* value, - PropertyDetails details) { +MaybeObject* NumberDictionary::Set(uint32_t key, + Object* value, + PropertyDetails details) { int entry = FindEntry(key); if (entry == kNotFound) return AddNumberEntry(key, value, details); // Preserve enumeration index. details = PropertyDetails(details.attributes(), details.type(), DetailsAt(entry).index()); - Object* object_key = NumberDictionaryShape::AsObject(key); - if (object_key->IsFailure()) return object_key; + MaybeObject* maybe_object_key = NumberDictionaryShape::AsObject(key); + Object* object_key; + if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key; SetEntry(entry, object_key, value, details); return this; } @@ -8678,7 +8970,7 @@ Object* Dictionary<Shape, Key>::SlowReverseLookup(Object* value) { } -Object* StringDictionary::TransformPropertiesToFastFor( +MaybeObject* StringDictionary::TransformPropertiesToFastFor( JSObject* obj, int unused_property_fields) { // Make sure we preserve dictionary representation if there are too many // descriptors. @@ -8690,8 +8982,10 @@ Object* StringDictionary::TransformPropertiesToFastFor( (DescriptorArray::kMaxNumberOfDescriptors - NumberOfElements()); if (!PropertyDetails::IsValidIndex(max_enumeration_index)) { - Object* result = GenerateNewEnumerationIndices(); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = GenerateNewEnumerationIndices(); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } int instance_descriptor_length = 0; @@ -8714,9 +9008,13 @@ Object* StringDictionary::TransformPropertiesToFastFor( } // Allocate the instance descriptor. - Object* descriptors_unchecked = - DescriptorArray::Allocate(instance_descriptor_length); - if (descriptors_unchecked->IsFailure()) return descriptors_unchecked; + Object* descriptors_unchecked; + { MaybeObject* maybe_descriptors_unchecked = + DescriptorArray::Allocate(instance_descriptor_length); + if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { + return maybe_descriptors_unchecked; + } + } DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked); int inobject_props = obj->map()->inobject_properties(); @@ -8729,8 +9027,11 @@ Object* StringDictionary::TransformPropertiesToFastFor( } // Allocate the fixed array for the fields. - Object* fields = Heap::AllocateFixedArray(number_of_allocated_fields); - if (fields->IsFailure()) return fields; + Object* fields; + { MaybeObject* maybe_fields = + Heap::AllocateFixedArray(number_of_allocated_fields); + if (!maybe_fields->ToObject(&fields)) return maybe_fields; + } // Fill in the instance descriptor and the fields. int next_descriptor = 0; @@ -8740,8 +9041,10 @@ Object* StringDictionary::TransformPropertiesToFastFor( if (IsKey(k)) { Object* value = ValueAt(i); // Ensure the key is a symbol before writing into the instance descriptor. - Object* key = Heap::LookupSymbol(String::cast(k)); - if (key->IsFailure()) return key; + Object* key; + { MaybeObject* maybe_key = Heap::LookupSymbol(String::cast(k)); + if (!maybe_key->ToObject(&key)) return maybe_key; + } PropertyDetails details = DetailsAt(i); PropertyType type = details.type(); @@ -8780,8 +9083,10 @@ Object* StringDictionary::TransformPropertiesToFastFor( descriptors->Sort(); // Allocate new map. - Object* new_map = obj->map()->CopyDropDescriptors(); - if (new_map->IsFailure()) return new_map; + Object* new_map; + { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } // Transform the object. obj->set_map(Map::cast(new_map)); diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index d917a5751a..87234ea2cb 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -41,9 +41,10 @@ // Most object types in the V8 JavaScript are described in this file. // // Inheritance hierarchy: +// - MaybeObject (an object or a failure) +// - Failure (immediate for marking failed operation) // - Object // - Smi (immediate small integer) -// - Failure (immediate for marking failed operation) // - HeapObject (superclass for everything allocated in the heap) // - JSObject // - JSArray @@ -584,6 +585,35 @@ struct ValueInfo : public Malloced { // A template-ized version of the IsXXX functions. 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 hierarchy. @@ -591,7 +621,7 @@ template <class C> static inline bool Is(Object* obj); // allocation of the C++ vtable. // Since Smi and Failure are subclasses of Object no // data members can be present in Object. -class Object BASE_EMBEDDED { +class Object : public MaybeObject { public: // Type testing. inline bool IsSmi(); @@ -619,10 +649,6 @@ class Object BASE_EMBEDDED { inline bool IsExternalIntArray(); inline bool IsExternalUnsignedIntArray(); inline bool IsExternalFloatArray(); - inline bool IsFailure(); - inline bool IsRetryAfterGC(); - inline bool IsOutOfMemoryFailure(); - inline bool IsException(); inline bool IsJSObject(); inline bool IsJSContextExtensionObject(); inline bool IsMap(); @@ -669,7 +695,6 @@ class Object BASE_EMBEDDED { // Oddball testing. INLINE(bool IsUndefined()); - INLINE(bool IsTheHole()); INLINE(bool IsNull()); INLINE(bool IsTrue()); INLINE(bool IsFalse()); @@ -679,38 +704,43 @@ class Object BASE_EMBEDDED { inline bool HasSpecificClassOf(String* name); - Object* ToObject(); // ECMA-262 9.9. - Object* ToBoolean(); // ECMA-262 9.2. + MUST_USE_RESULT MaybeObject* ToObject(); // ECMA-262 9.9. + Object* ToBoolean(); // ECMA-262 9.2. // Convert to a JSObject if needed. // 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. // Failure is returned otherwise. - inline Object* ToSmi(); + MUST_USE_RESULT inline MaybeObject* ToSmi(); void Lookup(String* name, LookupResult* result); // Property access. - inline Object* GetProperty(String* key); - inline Object* GetProperty(String* key, PropertyAttributes* attributes); - Object* GetPropertyWithReceiver(Object* receiver, - String* key, - PropertyAttributes* attributes); - Object* GetProperty(Object* receiver, - LookupResult* result, - String* key, - PropertyAttributes* attributes); - Object* GetPropertyWithCallback(Object* receiver, - Object* structure, - String* name, - Object* holder); - Object* GetPropertyWithDefinedGetter(Object* receiver, - JSFunction* getter); - - inline Object* GetElement(uint32_t index); - Object* GetElementWithReceiver(Object* receiver, uint32_t index); + MUST_USE_RESULT inline MaybeObject* GetProperty(String* key); + MUST_USE_RESULT inline MaybeObject* GetProperty( + String* key, + PropertyAttributes* attributes); + MUST_USE_RESULT MaybeObject* GetPropertyWithReceiver( + Object* receiver, + String* key, + PropertyAttributes* attributes); + MUST_USE_RESULT MaybeObject* GetProperty(Object* receiver, + LookupResult* result, + String* key, + PropertyAttributes* attributes); + MUST_USE_RESULT MaybeObject* GetPropertyWithCallback(Object* receiver, + Object* structure, + String* name, + Object* holder); + MUST_USE_RESULT MaybeObject* GetPropertyWithDefinedGetter(Object* receiver, + 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()). Object* GetPrototype(); @@ -724,12 +754,6 @@ class Object BASE_EMBEDDED { inline bool IsStringObjectWithCharacterAt(uint32_t index); #ifdef DEBUG - // Prints this object with details. - void Print(); - void PrintLn(); - // Verifies the object. - void Verify(); - // Verify a pointer is a valid object pointer. static void VerifyPointer(Object* p); #endif @@ -815,7 +839,7 @@ class Smi: public Object { const int kFailureTypeTagSize = 2; const int kFailureTypeTagMask = (1 << kFailureTypeTagSize) - 1; -class Failure: public Object { +class Failure: public MaybeObject { public: // RuntimeStubs assumes EXCEPTION = 1 in the compiler-generated code. enum Type { @@ -840,7 +864,7 @@ class Failure: public Object { static inline Failure* InternalError(); static inline Failure* OutOfMemoryException(); // Casting. - static inline Failure* cast(Object* object); + static inline Failure* cast(MaybeObject* object); // Dispatched behavior. void FailurePrint(); @@ -1249,7 +1273,7 @@ class JSObject: public HeapObject { // PixelArray or an ExternalArray. DECL_ACCESSORS(elements, HeapObject) inline void initialize_elements(); - inline Object* ResetElements(); + MUST_USE_RESULT inline MaybeObject* ResetElements(); inline ElementsKind GetElementsKind(); inline bool HasFastElements(); inline bool HasDictionaryElements(); @@ -1265,41 +1289,45 @@ class JSObject: public HeapObject { inline bool AllowsSetElementsLength(); inline NumberDictionary* element_dictionary(); // Gets slow elements. // Requires: this->HasFastElements(). - inline Object* EnsureWritableFastElements(); + MUST_USE_RESULT inline MaybeObject* EnsureWritableFastElements(); // Collects elements starting at index 0. // Undefined values are placed after 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 // a dictionary, and it will stay a dictionary. - MUST_USE_RESULT Object* PrepareSlowElementsForSort(uint32_t limit); - - Object* SetProperty(String* key, - Object* value, - PropertyAttributes attributes); - Object* SetProperty(LookupResult* result, - String* key, - Object* value, - PropertyAttributes attributes); - Object* SetPropertyWithFailedAccessCheck(LookupResult* result, - String* name, - Object* value); - Object* SetPropertyWithCallback(Object* structure, - String* name, - Object* value, - JSObject* holder); - Object* SetPropertyWithDefinedSetter(JSFunction* setter, - Object* value); - Object* SetPropertyWithInterceptor(String* name, - Object* value, - PropertyAttributes attributes); - Object* SetPropertyPostInterceptor(String* name, - Object* value, - PropertyAttributes attributes); - Object* IgnoreAttributesAndSetLocalProperty(String* key, - Object* value, - PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* PrepareSlowElementsForSort(uint32_t limit); + + MUST_USE_RESULT MaybeObject* SetProperty(String* key, + Object* value, + PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result, + String* key, + Object* value, + PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* SetPropertyWithFailedAccessCheck( + LookupResult* result, + String* name, + Object* value); + MUST_USE_RESULT MaybeObject* SetPropertyWithCallback(Object* structure, + String* name, + Object* value, + JSObject* holder); + MUST_USE_RESULT MaybeObject* SetPropertyWithDefinedSetter(JSFunction* setter, + Object* value); + MUST_USE_RESULT MaybeObject* SetPropertyWithInterceptor( + String* name, + Object* value, + PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* SetPropertyPostInterceptor( + String* name, + Object* value, + PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* IgnoreAttributesAndSetLocalProperty( + String* key, + Object* value, + PropertyAttributes attributes); // Retrieve a value in a normalized object given a lookup result. // 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). // Handles the special representation of JS global objects. - MUST_USE_RESULT Object* SetNormalizedProperty(String* name, - Object* value, - PropertyDetails details); + MUST_USE_RESULT MaybeObject* SetNormalizedProperty(String* name, + Object* value, + PropertyDetails details); // Deletes the named property in a normalized object. - MUST_USE_RESULT Object* DeleteNormalizedProperty(String* name, - DeleteMode mode); + MUST_USE_RESULT MaybeObject* DeleteNormalizedProperty(String* name, + DeleteMode mode); // Returns the class name ([[Class]] property in the specification). String* class_name(); @@ -1335,28 +1363,31 @@ class JSObject: public HeapObject { String* name); PropertyAttributes GetLocalPropertyAttribute(String* name); - MUST_USE_RESULT Object* DefineAccessor(String* name, - bool is_getter, - JSFunction* fun, - PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* DefineAccessor(String* name, + bool is_getter, + JSFunction* fun, + PropertyAttributes attributes); 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(). - Object* GetPropertyWithFailedAccessCheck(Object* receiver, - LookupResult* result, - String* name, - PropertyAttributes* attributes); - Object* GetPropertyWithInterceptor(JSObject* receiver, - String* name, - PropertyAttributes* attributes); - Object* GetPropertyPostInterceptor(JSObject* receiver, - String* name, - PropertyAttributes* attributes); - Object* GetLocalPropertyPostInterceptor(JSObject* receiver, - String* name, - PropertyAttributes* attributes); + MaybeObject* GetPropertyWithFailedAccessCheck( + Object* receiver, + LookupResult* result, + String* name, + PropertyAttributes* attributes); + MaybeObject* GetPropertyWithInterceptor( + JSObject* receiver, + String* name, + PropertyAttributes* attributes); + MaybeObject* GetPropertyPostInterceptor( + JSObject* receiver, + String* name, + PropertyAttributes* attributes); + MaybeObject* GetLocalPropertyPostInterceptor(JSObject* receiver, + String* name, + PropertyAttributes* attributes); // Returns true if this is an instance of an api function and has // 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. inline bool HasHiddenPropertiesObject(); 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 Object* DeleteElement(uint32_t index, DeleteMode mode); + MUST_USE_RESULT MaybeObject* DeleteProperty(String* name, DeleteMode mode); + MUST_USE_RESULT MaybeObject* DeleteElement(uint32_t index, DeleteMode mode); // Tests for the fast common case for property enumeration. bool IsSimpleEnum(); @@ -1411,7 +1443,8 @@ class JSObject: public HeapObject { inline Object* GetPrototype(); // 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. inline bool HasElement(uint32_t index); @@ -1440,20 +1473,20 @@ class JSObject: public HeapObject { bool HasElementWithInterceptor(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. // 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. // The undefined object if index is out of bounds. - Object* GetElementWithReceiver(JSObject* receiver, uint32_t index); - Object* GetElementWithInterceptor(JSObject* receiver, uint32_t index); + MaybeObject* GetElementWithReceiver(JSObject* receiver, uint32_t index); + MaybeObject* GetElementWithInterceptor(JSObject* receiver, uint32_t index); - MUST_USE_RESULT Object* SetFastElementsCapacityAndLength(int capacity, - int length); - MUST_USE_RESULT Object* SetSlowElements(Object* length); + MUST_USE_RESULT MaybeObject* SetFastElementsCapacityAndLength(int capacity, + int length); + MUST_USE_RESULT MaybeObject* SetSlowElements(Object* length); // Lookup interceptors are used for handling properties controlled by host // objects. @@ -1466,7 +1499,7 @@ class JSObject: public HeapObject { bool HasRealNamedCallbackProperty(String* key); // 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 // 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 // new_map. - Object* AddFastPropertyUsingMap(Map* new_map, - String* name, - Object* value); + MUST_USE_RESULT MaybeObject* AddFastPropertyUsingMap(Map* new_map, + String* name, + Object* value); // Add a constant function property to a fast-case object. // 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. // This avoids the creation of many maps with the same constant // function, all orphaned. - Object* AddConstantFunctionProperty(String* name, - JSFunction* function, - PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* AddConstantFunctionProperty( + String* name, + JSFunction* function, + PropertyAttributes attributes); - Object* ReplaceSlowProperty(String* name, - Object* value, - PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* ReplaceSlowProperty( + String* name, + Object* value, + PropertyAttributes attributes); // Converts a descriptor of any other type to a real field, // backed by the properties array. Descriptors of visible // types, such as CONSTANT_FUNCTION, keep their enumeration order. // 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. - Object* ConvertDescriptorToFieldAndMapTransition( + MUST_USE_RESULT MaybeObject* ConvertDescriptorToFieldAndMapTransition( String* name, Object* new_value, PropertyAttributes attributes); @@ -1546,38 +1581,41 @@ class JSObject: public HeapObject { // Converts a descriptor of any other type to a real field, // backed by the properties array. Descriptors of visible // types, such as CONSTANT_FUNCTION, keep their enumeration order. - Object* ConvertDescriptorToField(String* name, - Object* new_value, - PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* ConvertDescriptorToField( + String* name, + Object* new_value, + PropertyAttributes attributes); // Add a property to a fast-case object. - Object* AddFastProperty(String* name, - Object* value, - PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* AddFastProperty(String* name, + Object* value, + PropertyAttributes attributes); // Add a property to a slow-case object. - Object* AddSlowProperty(String* name, - Object* value, - PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* AddSlowProperty(String* name, + Object* value, + PropertyAttributes attributes); // Add a property to an object. - Object* AddProperty(String* name, - Object* value, - PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* AddProperty(String* name, + Object* value, + PropertyAttributes attributes); // Convert the object to use the canonical dictionary // representation. If the object is expected to have additional properties // added this number can be indicated to have the backing store allocated to // an initial capacity for holding these properties. - Object* NormalizeProperties(PropertyNormalizationMode mode, - int expected_additional_properties); - Object* NormalizeElements(); + MUST_USE_RESULT MaybeObject* NormalizeProperties( + PropertyNormalizationMode mode, + 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. // 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. inline Object* FastPropertyAt(int index); @@ -1603,7 +1641,7 @@ class JSObject: public HeapObject { static inline JSObject* cast(Object* obj); // Disalow further properties to be added to the object. - MUST_USE_RESULT Object* PreventExtensions(); + MUST_USE_RESULT MaybeObject* PreventExtensions(); // Dispatched behavior. @@ -1668,28 +1706,28 @@ class JSObject: public HeapObject { }; private: - Object* GetElementWithCallback(Object* receiver, - Object* structure, - uint32_t index, - Object* holder); - Object* SetElementWithCallback(Object* structure, - uint32_t index, - Object* value, - JSObject* holder); - MUST_USE_RESULT Object* SetElementWithInterceptor(uint32_t index, - Object* value); - MUST_USE_RESULT Object* SetElementWithoutInterceptor(uint32_t index, - Object* value); - - Object* GetElementPostInterceptor(JSObject* receiver, uint32_t index); - - MUST_USE_RESULT Object* DeletePropertyPostInterceptor(String* name, - DeleteMode mode); - MUST_USE_RESULT Object* DeletePropertyWithInterceptor(String* name); - - MUST_USE_RESULT Object* DeleteElementPostInterceptor(uint32_t index, - DeleteMode mode); - MUST_USE_RESULT Object* DeleteElementWithInterceptor(uint32_t index); + MUST_USE_RESULT MaybeObject* GetElementWithCallback(Object* receiver, + Object* structure, + uint32_t index, + Object* holder); + MaybeObject* SetElementWithCallback(Object* structure, + uint32_t index, + Object* value, + JSObject* holder); + MUST_USE_RESULT MaybeObject* SetElementWithInterceptor(uint32_t index, + Object* value); + MUST_USE_RESULT MaybeObject* SetElementWithoutInterceptor(uint32_t index, + Object* value); + + MaybeObject* GetElementPostInterceptor(JSObject* receiver, uint32_t index); + + MUST_USE_RESULT MaybeObject* DeletePropertyPostInterceptor(String* name, + DeleteMode mode); + MUST_USE_RESULT MaybeObject* DeletePropertyWithInterceptor(String* name); + + MUST_USE_RESULT MaybeObject* DeleteElementPostInterceptor(uint32_t index, + DeleteMode mode); + MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index); PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver, String* name, @@ -1711,14 +1749,17 @@ class JSObject: public HeapObject { bool HasDenseElements(); bool CanSetCallback(String* name); - MUST_USE_RESULT Object* SetElementCallback(uint32_t index, - Object* structure, - PropertyAttributes attributes); - MUST_USE_RESULT Object* SetPropertyCallback(String* name, - Object* structure, - PropertyAttributes attributes); - MUST_USE_RESULT Object* DefineGetterSetter(String* name, - PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* SetElementCallback( + uint32_t index, + Object* structure, + PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* SetPropertyCallback( + String* name, + Object* structure, + PropertyAttributes attributes); + MUST_USE_RESULT MaybeObject* DefineGetterSetter( + String* name, + PropertyAttributes attributes); void LookupInDescriptor(String* name, LookupResult* result); @@ -1757,14 +1798,14 @@ class FixedArray: public HeapObject { inline Object** data_start(); // Copy operations. - inline Object* Copy(); - MUST_USE_RESULT Object* CopySize(int new_length); + MUST_USE_RESULT inline MaybeObject* Copy(); + MUST_USE_RESULT MaybeObject* CopySize(int new_length); // 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. - MUST_USE_RESULT Object* UnionOfKeys(FixedArray* other); + MUST_USE_RESULT MaybeObject* UnionOfKeys(FixedArray* other); // Copy a sub array from the receiver to dest. 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. // If adding a real property, map transitions must be removed. If adding // a transition, they must not be removed. All null descriptors are removed. - MUST_USE_RESULT Object* CopyInsert(Descriptor* descriptor, - TransitionFlag transition_flag); + MUST_USE_RESULT MaybeObject* CopyInsert(Descriptor* descriptor, + TransitionFlag transition_flag); // 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. - MUST_USE_RESULT Object* RemoveTransitions(); + MUST_USE_RESULT MaybeObject* RemoveTransitions(); // Sort the instance descriptors by the hash codes of their keys. // Does not check for duplicates. @@ -1941,7 +1982,7 @@ class DescriptorArray: public FixedArray { // Allocates a DescriptorArray, but returns the singleton // 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. static inline DescriptorArray* cast(Object* obj); @@ -2081,7 +2122,7 @@ class HashTable: public FixedArray { } // 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, PretenureFlag pretenure = NOT_TENURED); @@ -2177,7 +2218,7 @@ class HashTable: public FixedArray { } // 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; // Returns the key object for storing into the hash table. // If allocations fails a failure object is returned. - MUST_USE_RESULT virtual Object* AsObject() = 0; + MUST_USE_RESULT virtual MaybeObject* AsObject() = 0; // Required. virtual ~HashTableKey() {} }; @@ -2209,7 +2250,7 @@ class SymbolTableShape { static uint32_t HashForObject(HashTableKey* key, Object* object) { return key->HashForObject(object); } - MUST_USE_RESULT static Object* AsObject(HashTableKey* key) { + MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) { return key->AsObject(); } @@ -2227,8 +2268,8 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> { // added. The return value is the symbol table which might have // been enlarged. If the return value is not a failure, the symbol // pointer *s is set to the symbol found. - Object* LookupSymbol(Vector<const char> str, Object** s); - Object* LookupString(String* key, Object** s); + MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str, Object** s); + MUST_USE_RESULT MaybeObject* LookupString(String* key, Object** s); // 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 @@ -2240,7 +2281,7 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> { static inline SymbolTable* cast(Object* obj); private: - Object* LookupKey(HashTableKey* key, Object** s); + MUST_USE_RESULT MaybeObject* LookupKey(HashTableKey* key, Object** s); DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolTable); }; @@ -2259,7 +2300,7 @@ class MapCacheShape { return key->HashForObject(object); } - MUST_USE_RESULT static Object* AsObject(HashTableKey* key) { + MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) { return key->AsObject(); } @@ -2276,7 +2317,7 @@ class MapCache: public HashTable<MapCacheShape, HashTableKey*> { public: // Find cached value for a string key, otherwise return null. 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); private: @@ -2347,10 +2388,10 @@ class Dictionary: public HashTable<Shape, Key> { } // 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. - Object* EnsureCapacity(int n, Key key); + MUST_USE_RESULT MaybeObject* EnsureCapacity(int n, Key key); #ifdef DEBUG void Print(); @@ -2364,20 +2405,22 @@ class Dictionary: public HashTable<Shape, Key> { Object* value, PropertyDetails details); - Object* Add(Key key, Object* value, PropertyDetails details); + MUST_USE_RESULT MaybeObject* Add(Key key, + Object* value, + PropertyDetails details); protected: // Generic at put operation. - Object* AtPut(Key key, Object* value); + MUST_USE_RESULT MaybeObject* AtPut(Key key, Object* value); // Add entry to dictionary. - Object* AddEntry(Key key, - Object* value, - PropertyDetails details, - uint32_t hash); + MUST_USE_RESULT MaybeObject* AddEntry(Key key, + Object* value, + PropertyDetails details, + uint32_t hash); // Generate new enumeration indices to avoid enumeration index overflow. - Object* GenerateNewEnumerationIndices(); + MUST_USE_RESULT MaybeObject* GenerateNewEnumerationIndices(); static const int kMaxNumberKeyIndex = HashTable<Shape, Key>::kPrefixStartIndex; static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1; @@ -2389,7 +2432,7 @@ class StringDictionaryShape { static inline bool IsMatch(String* key, Object* other); static inline uint32_t Hash(String* key); 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 kEntrySize = 3; static const bool kIsEnumerable = true; @@ -2407,8 +2450,9 @@ class StringDictionary: public Dictionary<StringDictionaryShape, String*> { void CopyEnumKeysTo(FixedArray* storage, FixedArray* sort_array); // For transforming properties of a JSObject. - Object* TransformPropertiesToFastFor(JSObject* obj, - int unused_property_fields); + MUST_USE_RESULT MaybeObject* TransformPropertiesToFastFor( + JSObject* obj, + int unused_property_fields); // Find entry for key otherwise return kNotFound. Optimzed version of // HashTable::FindEntry. @@ -2421,7 +2465,7 @@ class NumberDictionaryShape { static inline bool IsMatch(uint32_t key, Object* other); static inline uint32_t Hash(uint32_t key); 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 kEntrySize = 3; 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). - Object* AtNumberPut(uint32_t key, Object* value); - Object* AddNumberEntry(uint32_t key, - Object* value, - PropertyDetails details); + MUST_USE_RESULT MaybeObject* AtNumberPut(uint32_t key, Object* value); + MUST_USE_RESULT MaybeObject* AddNumberEntry(uint32_t key, + Object* value, + PropertyDetails details); // 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); @@ -2509,7 +2555,8 @@ class NormalizedMapCache: public FixedArray { public: static const int kEntries = 64; - Object* Get(JSObject* object, PropertyNormalizationMode mode); + MUST_USE_RESULT MaybeObject* Get(JSObject* object, + PropertyNormalizationMode mode); void Clear(); @@ -2686,7 +2733,7 @@ class ExternalByteArray: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - Object* SetValue(uint32_t index, Object* value); + MaybeObject* SetValue(uint32_t index, Object* value); // Casting. static inline ExternalByteArray* cast(Object* obj); @@ -2709,7 +2756,7 @@ class ExternalUnsignedByteArray: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - Object* SetValue(uint32_t index, Object* value); + MaybeObject* SetValue(uint32_t index, Object* value); // Casting. static inline ExternalUnsignedByteArray* cast(Object* obj); @@ -2732,7 +2779,7 @@ class ExternalShortArray: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - Object* SetValue(uint32_t index, Object* value); + MaybeObject* SetValue(uint32_t index, Object* value); // Casting. static inline ExternalShortArray* cast(Object* obj); @@ -2755,7 +2802,7 @@ class ExternalUnsignedShortArray: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - Object* SetValue(uint32_t index, Object* value); + MaybeObject* SetValue(uint32_t index, Object* value); // Casting. static inline ExternalUnsignedShortArray* cast(Object* obj); @@ -2778,7 +2825,7 @@ class ExternalIntArray: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - Object* SetValue(uint32_t index, Object* value); + MaybeObject* SetValue(uint32_t index, Object* value); // Casting. static inline ExternalIntArray* cast(Object* obj); @@ -2801,7 +2848,7 @@ class ExternalUnsignedIntArray: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - Object* SetValue(uint32_t index, Object* value); + MaybeObject* SetValue(uint32_t index, Object* value); // Casting. static inline ExternalUnsignedIntArray* cast(Object* obj); @@ -2824,7 +2871,7 @@ class ExternalFloatArray: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - Object* SetValue(uint32_t index, Object* value); + MaybeObject* SetValue(uint32_t index, Object* value); // Casting. static inline ExternalFloatArray* cast(Object* obj); @@ -3192,24 +3239,24 @@ class Map: public HeapObject { // [stub cache]: contains stubs compiled for this map. DECL_ACCESSORS(code_cache, Object) - MUST_USE_RESULT Object* CopyDropDescriptors(); + MUST_USE_RESULT MaybeObject* CopyDropDescriptors(); - MUST_USE_RESULT Object* CopyNormalized(PropertyNormalizationMode mode, - NormalizedMapSharingMode sharing); + MUST_USE_RESULT MaybeObject* CopyNormalized(PropertyNormalizationMode mode, + NormalizedMapSharingMode sharing); // Returns a copy of the map, with all transitions dropped from the // 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 a copy of the map, with all transitions dropped from the // 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, // otherwise returns a copy of the map, with all transitions dropped // 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). int PropertyIndexFor(String* name); @@ -3232,7 +3279,7 @@ class Map: public HeapObject { inline void ClearCodeCache(); // 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. Object* FindInCodeCache(String* name, Code::Flags flags); @@ -3881,7 +3928,7 @@ class JSFunction: public JSObject { inline Object* prototype(); inline Object* instance_prototype(); 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 // [[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. 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. - Object* EnsurePropertyCell(String* name); + MUST_USE_RESULT MaybeObject* EnsurePropertyCell(String* name); // Casting. static inline GlobalObject* cast(Object* obj); @@ -4222,7 +4278,7 @@ class CompilationCacheShape { return key->HashForObject(object); } - MUST_USE_RESULT static Object* AsObject(HashTableKey* key) { + MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) { return key->AsObject(); } @@ -4238,9 +4294,9 @@ class CompilationCacheTable: public HashTable<CompilationCacheShape, Object* Lookup(String* src); Object* LookupEval(String* src, Context* context); Object* LookupRegExp(String* source, JSRegExp::Flags flags); - Object* Put(String* src, Object* value); - Object* PutEval(String* src, Context* context, Object* value); - Object* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value); + MaybeObject* Put(String* src, Object* value); + MaybeObject* PutEval(String* src, Context* context, Object* value); + MaybeObject* PutRegExp(String* src, JSRegExp::Flags flags, FixedArray* value); static inline CompilationCacheTable* cast(Object* obj); @@ -4255,7 +4311,7 @@ class CodeCache: public Struct { DECL_ACCESSORS(normal_type_cache, Object) // 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 // if not. @@ -4283,8 +4339,8 @@ class CodeCache: public Struct { static const int kSize = kNormalTypeCacheOffset + kPointerSize; private: - MUST_USE_RESULT Object* UpdateDefaultCache(String* name, Code* code); - MUST_USE_RESULT Object* UpdateNormalTypeCache(String* name, Code* code); + MUST_USE_RESULT MaybeObject* UpdateDefaultCache(String* name, Code* code); + MUST_USE_RESULT MaybeObject* UpdateNormalTypeCache(String* name, Code* code); Object* LookupDefaultCache(String* name, Code::Flags flags); Object* LookupNormalTypeCache(String* name, Code::Flags flags); @@ -4312,7 +4368,7 @@ class CodeCacheHashTableShape { return key->HashForObject(object); } - MUST_USE_RESULT static Object* AsObject(HashTableKey* key) { + MUST_USE_RESULT static MaybeObject* AsObject(HashTableKey* key) { return key->AsObject(); } @@ -4325,7 +4381,7 @@ class CodeCacheHashTable: public HashTable<CodeCacheHashTableShape, HashTableKey*> { public: 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); void RemoveByIndex(int index); @@ -4492,7 +4548,7 @@ class String: public HeapObject { // // Use FlattenString from Handles.cc to flatten even in case an // 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 // TryFlatten(), except in the case of failure returns the original @@ -4507,7 +4563,9 @@ class String: public HeapObject { bool MarkAsUndetectable(); // 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. 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 // string. This is a no-op unless the string is a ConsString. Flatten // 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); @@ -5101,7 +5159,8 @@ class Oddball: public HeapObject { #endif // 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. 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. inline void set_length(Smi* length); - MUST_USE_RESULT Object* JSArrayUpdateLengthFromIndex(uint32_t index, - Object* value); + MUST_USE_RESULT MaybeObject* JSArrayUpdateLengthFromIndex(uint32_t index, + Object* value); // Initialize the array with the given capacity. The function may // fail due to out-of-memory situations, but only if the requested // 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. inline void SetContent(FixedArray* storage); diff --git a/deps/v8/src/parser.cc b/deps/v8/src/parser.cc index 7690e92d52..180d0d2456 100644 --- a/deps/v8/src/parser.cc +++ b/deps/v8/src/parser.cc @@ -4266,11 +4266,9 @@ Expression* Parser::NewThrowError(Handle<String> constructor, for (int i = 0; i < argc; i++) { Handle<Object> element = arguments[i]; 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 // large enough. - ASSERT(!ok->IsFailure()); + array->SetFastElement(i, *element)->ToObjectUnchecked(); } } ZoneList<Expression*>* args = new ZoneList<Expression*>(2); diff --git a/deps/v8/src/platform-freebsd.cc b/deps/v8/src/platform-freebsd.cc index 1003de15cd..6b8f2c048a 100644 --- a/deps/v8/src/platform-freebsd.cc +++ b/deps/v8/src/platform-freebsd.cc @@ -617,7 +617,10 @@ class Sampler::PlatformData : public Malloced { Sampler::Sampler(int interval, bool profiling) - : interval_(interval), profiling_(profiling), active_(false) { + : interval_(interval), + profiling_(profiling), + synchronous_(profiling), + active_(false) { data_ = new PlatformData(); } diff --git a/deps/v8/src/platform-linux.cc b/deps/v8/src/platform-linux.cc index c01c0d24b5..eefaec9042 100644 --- a/deps/v8/src/platform-linux.cc +++ b/deps/v8/src/platform-linux.cc @@ -33,6 +33,7 @@ #include <signal.h> #include <sys/time.h> #include <sys/resource.h> +#include <sys/syscall.h> #include <sys/types.h> #include <stdlib.h> @@ -714,7 +715,6 @@ Semaphore* OS::CreateSemaphore(int count) { #ifdef ENABLE_LOGGING_AND_PROFILING static Sampler* active_sampler_ = NULL; -static pthread_t vm_thread_ = 0; #if !defined(__GLIBC__) && (defined(__arm__) || defined(__thumb__)) @@ -743,36 +743,11 @@ enum ArmRegisters {R15 = 15, R13 = 13, R11 = 11}; #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) { #ifndef V8_HOST_ARCH_MIPS USE(info); if (signal != SIGPROF) return; if (active_sampler_ == NULL) return; - if (!IsVmThread()) return; TickSample sample_obj; TickSample* sample = CpuProfiler::TickSampleEvent(); @@ -819,22 +794,51 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { class Sampler::PlatformData : public Malloced { public: - PlatformData() { - signal_handler_installed_ = false; + explicit PlatformData(Sampler* sampler) + : 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_; 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) : interval_(interval), profiling_(profiling), synchronous_(profiling), active_(false) { - data_ = new PlatformData(); + data_ = new PlatformData(this); } @@ -848,8 +852,6 @@ void Sampler::Start() { // platforms. if (active_sampler_ != NULL) return; - vm_thread_ = pthread_self(); - // Request profiling signals. struct sigaction sa; sa.sa_sigaction = ProfilerSignalHandler; @@ -858,31 +860,38 @@ void Sampler::Start() { if (sigaction(SIGPROF, &sa, &data_->old_signal_handler_) != 0) return; data_->signal_handler_installed_ = true; - // Set the itimer to generate a tick for each interval. - itimerval itimer; - itimer.it_interval.tv_sec = interval_ / 1000; - itimer.it_interval.tv_usec = (interval_ % 1000) * 1000; - itimer.it_value.tv_sec = itimer.it_interval.tv_sec; - itimer.it_value.tv_usec = itimer.it_interval.tv_usec; - setitimer(ITIMER_PROF, &itimer, &data_->old_timer_value_); + // Start a thread that sends SIGPROF signal to VM thread. + // Sending the signal ourselves instead of relying on itimer provides + // much better accuracy. + active_ = true; + if (pthread_create( + &data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) { + data_->signal_sender_launched_ = true; + } // Set this sampler as the active sampler. active_sampler_ = this; - active_ = true; } 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 if (data_->signal_handler_installed_) { - setitimer(ITIMER_PROF, &data_->old_timer_value_, NULL); sigaction(SIGPROF, &data_->old_signal_handler_, 0); data_->signal_handler_installed_ = false; } // This sampler is no longer the active sampler. active_sampler_ = NULL; - active_ = false; } diff --git a/deps/v8/src/platform-macos.cc b/deps/v8/src/platform-macos.cc index 3e4daf3bbb..5e0e78dbf8 100644 --- a/deps/v8/src/platform-macos.cc +++ b/deps/v8/src/platform-macos.cc @@ -206,7 +206,11 @@ OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, void* initial) { FILE* file = fopen(name, "w+"); 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 = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0); return new PosixMemoryMappedFile(file, memory, size); diff --git a/deps/v8/src/profile-generator.cc b/deps/v8/src/profile-generator.cc index 977c67c8cc..a4d9a828dd 100644 --- a/deps/v8/src/profile-generator.cc +++ b/deps/v8/src/profile-generator.cc @@ -1319,11 +1319,9 @@ HeapEntry* HeapSnapshot::AddEntry(HeapObject* object, retainers_count); } else if (object->IsSharedFunctionInfo()) { SharedFunctionInfo* shared = SharedFunctionInfo::cast(object); - String* name = String::cast(shared->name())->length() > 0 ? - String::cast(shared->name()) : shared->inferred_name(); return AddEntry(object, HeapEntry::kCode, - collection_->GetFunctionName(name), + collection_->GetName(String::cast(shared->name())), children_count, retainers_count); } else if (object->IsScript()) { diff --git a/deps/v8/src/property.h b/deps/v8/src/property.h index 01c58def3e..4715a725f1 100644 --- a/deps/v8/src/property.h +++ b/deps/v8/src/property.h @@ -45,10 +45,12 @@ class Descriptor BASE_EMBEDDED { return Smi::cast(value)->value(); } - Object* KeyToSymbol() { + MUST_USE_RESULT MaybeObject* KeyToSymbol() { if (!StringShape(key_).IsSymbol()) { - Object* result = Heap::LookupSymbol(key_); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::LookupSymbol(key_); + if (!maybe_result->ToObject(&result)) return maybe_result; + } key_ = String::cast(result); } return key_; diff --git a/deps/v8/src/runtime.cc b/deps/v8/src/runtime.cc index 9a604a035d..f701c03113 100644 --- a/deps/v8/src/runtime.cc +++ b/deps/v8/src/runtime.cc @@ -99,12 +99,14 @@ namespace internal { static StaticResource<StringInputBuffer> runtime_string_input_buffer; -MUST_USE_RESULT static Object* DeepCopyBoilerplate(JSObject* boilerplate) { +MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(JSObject* boilerplate) { StackLimitCheck check; if (check.HasOverflowed()) return Top::StackOverflow(); - Object* result = Heap::CopyJSObject(boilerplate); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::CopyJSObject(boilerplate); + if (!maybe_result->ToObject(&result)) return maybe_result; + } JSObject* copy = JSObject::cast(result); // Deep copy local properties. @@ -114,8 +116,9 @@ MUST_USE_RESULT static Object* DeepCopyBoilerplate(JSObject* boilerplate) { Object* value = properties->get(i); if (value->IsJSObject()) { JSObject* js_object = JSObject::cast(value); - result = DeepCopyBoilerplate(js_object); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object); + if (!maybe_result->ToObject(&result)) return maybe_result; + } properties->set(i, result); } } @@ -124,14 +127,17 @@ MUST_USE_RESULT static Object* DeepCopyBoilerplate(JSObject* boilerplate) { Object* value = copy->InObjectPropertyAt(i); if (value->IsJSObject()) { JSObject* js_object = JSObject::cast(value); - result = DeepCopyBoilerplate(js_object); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object); + if (!maybe_result->ToObject(&result)) return maybe_result; + } copy->InObjectPropertyAtPut(i, result); } } } else { - result = Heap::AllocateFixedArray(copy->NumberOfLocalProperties(NONE)); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = + Heap::AllocateFixedArray(copy->NumberOfLocalProperties(NONE)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } FixedArray* names = FixedArray::cast(result); copy->GetLocalPropertyNames(names, 0); for (int i = 0; i < names->length(); i++) { @@ -143,14 +149,17 @@ MUST_USE_RESULT static Object* DeepCopyBoilerplate(JSObject* boilerplate) { // In particular, don't try to copy the length attribute of // an array. if (attributes != NONE) continue; - Object* value = copy->GetProperty(key_string, &attributes); - ASSERT(!value->IsFailure()); + Object* value = + copy->GetProperty(key_string, &attributes)->ToObjectUnchecked(); if (value->IsJSObject()) { JSObject* js_object = JSObject::cast(value); - result = DeepCopyBoilerplate(js_object); - if (result->IsFailure()) return result; - result = copy->SetProperty(key_string, result, NONE); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object); + if (!maybe_result->ToObject(&result)) return maybe_result; + } + { MaybeObject* maybe_result = + copy->SetProperty(key_string, result, NONE); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } } } @@ -173,8 +182,9 @@ MUST_USE_RESULT static Object* DeepCopyBoilerplate(JSObject* boilerplate) { Object* value = elements->get(i); if (value->IsJSObject()) { JSObject* js_object = JSObject::cast(value); - result = DeepCopyBoilerplate(js_object); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object); + if (!maybe_result->ToObject(&result)) return maybe_result; + } elements->set(i, result); } } @@ -190,8 +200,9 @@ MUST_USE_RESULT static Object* DeepCopyBoilerplate(JSObject* boilerplate) { Object* value = element_dictionary->ValueAt(i); if (value->IsJSObject()) { JSObject* js_object = JSObject::cast(value); - result = DeepCopyBoilerplate(js_object); - if (result->IsFailure()) return result; + { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object); + if (!maybe_result->ToObject(&result)) return maybe_result; + } element_dictionary->ValueAtPut(i, result); } } @@ -206,13 +217,13 @@ MUST_USE_RESULT static Object* DeepCopyBoilerplate(JSObject* boilerplate) { } -static Object* Runtime_CloneLiteralBoilerplate(Arguments args) { +static MaybeObject* Runtime_CloneLiteralBoilerplate(Arguments args) { CONVERT_CHECKED(JSObject, boilerplate, args[0]); return DeepCopyBoilerplate(boilerplate); } -static Object* Runtime_CloneShallowLiteralBoilerplate(Arguments args) { +static MaybeObject* Runtime_CloneShallowLiteralBoilerplate(Arguments args) { CONVERT_CHECKED(JSObject, boilerplate, args[0]); return Heap::CopyJSObject(boilerplate); } @@ -403,7 +414,7 @@ static Handle<Object> CreateLiteralBoilerplate( } -static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) { +static MaybeObject* Runtime_CreateArrayLiteralBoilerplate(Arguments args) { // Takes a FixedArray of elements containing the literal elements of // the array literal and produces JSArray with those elements. // Additionally takes the literals array of the surrounding function @@ -424,7 +435,7 @@ static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) { } -static Object* Runtime_CreateObjectLiteral(Arguments args) { +static MaybeObject* Runtime_CreateObjectLiteral(Arguments args) { HandleScope scope; ASSERT(args.length() == 4); CONVERT_ARG_CHECKED(FixedArray, literals, 0); @@ -447,7 +458,7 @@ static Object* Runtime_CreateObjectLiteral(Arguments args) { } -static Object* Runtime_CreateObjectLiteralShallow(Arguments args) { +static MaybeObject* Runtime_CreateObjectLiteralShallow(Arguments args) { HandleScope scope; ASSERT(args.length() == 4); CONVERT_ARG_CHECKED(FixedArray, literals, 0); @@ -470,7 +481,7 @@ static Object* Runtime_CreateObjectLiteralShallow(Arguments args) { } -static Object* Runtime_CreateArrayLiteral(Arguments args) { +static MaybeObject* Runtime_CreateArrayLiteral(Arguments args) { HandleScope scope; ASSERT(args.length() == 3); CONVERT_ARG_CHECKED(FixedArray, literals, 0); @@ -489,7 +500,7 @@ static Object* Runtime_CreateArrayLiteral(Arguments args) { } -static Object* Runtime_CreateArrayLiteralShallow(Arguments args) { +static MaybeObject* Runtime_CreateArrayLiteralShallow(Arguments args) { HandleScope scope; ASSERT(args.length() == 3); CONVERT_ARG_CHECKED(FixedArray, literals, 0); @@ -512,24 +523,28 @@ static Object* Runtime_CreateArrayLiteralShallow(Arguments args) { } -static Object* Runtime_CreateCatchExtensionObject(Arguments args) { +static MaybeObject* Runtime_CreateCatchExtensionObject(Arguments args) { ASSERT(args.length() == 2); CONVERT_CHECKED(String, key, args[0]); Object* value = args[1]; // Create a catch context extension object. JSFunction* constructor = Top::context()->global_context()->context_extension_function(); - Object* object = Heap::AllocateJSObject(constructor); - if (object->IsFailure()) return object; + Object* object; + { MaybeObject* maybe_object = Heap::AllocateJSObject(constructor); + if (!maybe_object->ToObject(&object)) return maybe_object; + } // Assign the exception value to the catch variable and make sure // that the catch variable is DontDelete. - value = JSObject::cast(object)->SetProperty(key, value, DONT_DELETE); - if (value->IsFailure()) return value; + { MaybeObject* maybe_value = + JSObject::cast(object)->SetProperty(key, value, DONT_DELETE); + if (!maybe_value->ToObject(&value)) return maybe_value; + } return object; } -static Object* Runtime_ClassOf(Arguments args) { +static MaybeObject* Runtime_ClassOf(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Object* obj = args[0]; @@ -538,7 +553,7 @@ static Object* Runtime_ClassOf(Arguments args) { } -static Object* Runtime_IsInPrototypeChain(Arguments args) { +static MaybeObject* Runtime_IsInPrototypeChain(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). @@ -554,7 +569,7 @@ static Object* Runtime_IsInPrototypeChain(Arguments args) { // Inserts an object as the hidden prototype of another object. -static Object* Runtime_SetHiddenPrototype(Arguments args) { +static MaybeObject* Runtime_SetHiddenPrototype(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); CONVERT_CHECKED(JSObject, jsobject, args[0]); @@ -568,12 +583,19 @@ static Object* Runtime_SetHiddenPrototype(Arguments args) { RUNTIME_ASSERT(!proto->map()->is_hidden_prototype()); // Allocate up front before we start altering state in case we get a GC. - Object* map_or_failure = proto->map()->CopyDropTransitions(); - if (map_or_failure->IsFailure()) return map_or_failure; + Object* map_or_failure; + { MaybeObject* maybe_map_or_failure = proto->map()->CopyDropTransitions(); + if (!maybe_map_or_failure->ToObject(&map_or_failure)) { + return maybe_map_or_failure; + } + } Map* new_proto_map = Map::cast(map_or_failure); - map_or_failure = jsobject->map()->CopyDropTransitions(); - if (map_or_failure->IsFailure()) return map_or_failure; + { MaybeObject* maybe_map_or_failure = jsobject->map()->CopyDropTransitions(); + if (!maybe_map_or_failure->ToObject(&map_or_failure)) { + return maybe_map_or_failure; + } + } Map* new_map = Map::cast(map_or_failure); // Set proto's prototype to be the old prototype of the object. @@ -589,7 +611,7 @@ static Object* Runtime_SetHiddenPrototype(Arguments args) { } -static Object* Runtime_IsConstructCall(Arguments args) { +static MaybeObject* Runtime_IsConstructCall(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 0); JavaScriptFrameIterator it; @@ -632,7 +654,7 @@ enum PropertyDescriptorIndices { // [false, value, Writeable, Enumerable, Configurable] // if args[1] is an accessor on args[0] // [true, GetFunction, SetFunction, Enumerable, Configurable] -static Object* Runtime_GetOwnProperty(Arguments args) { +static MaybeObject* Runtime_GetOwnProperty(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; Handle<FixedArray> elms = Factory::NewFixedArray(DESCRIPTOR_SIZE); @@ -719,9 +741,11 @@ static Object* Runtime_GetOwnProperty(Arguments args) { if (structure->IsProxy() || structure->IsAccessorInfo()) { // Property that is internally implemented as a callback or // an API defined callback. - Object* value = obj->GetPropertyWithCallback( - *obj, structure, *name, result.holder()); - if (value->IsFailure()) return value; + Object* value; + { MaybeObject* maybe_value = obj->GetPropertyWithCallback( + *obj, structure, *name, result.holder()); + if (!maybe_value->ToObject(&value)) return maybe_value; + } elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); elms->set(VALUE_INDEX, value); elms->set(WRITABLE_INDEX, Heap::ToBoolean(!result.IsReadOnly())); @@ -745,13 +769,13 @@ static Object* Runtime_GetOwnProperty(Arguments args) { } -static Object* Runtime_PreventExtensions(Arguments args) { +static MaybeObject* Runtime_PreventExtensions(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(JSObject, obj, args[0]); return obj->PreventExtensions(); } -static Object* Runtime_IsExtensible(Arguments args) { +static MaybeObject* Runtime_IsExtensible(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(JSObject, obj, args[0]); return obj->map()->is_extensible() ? Heap::true_value() @@ -759,7 +783,7 @@ static Object* Runtime_IsExtensible(Arguments args) { } -static Object* Runtime_RegExpCompile(Arguments args) { +static MaybeObject* Runtime_RegExpCompile(Arguments args) { HandleScope scope; ASSERT(args.length() == 3); CONVERT_ARG_CHECKED(JSRegExp, re, 0); @@ -771,7 +795,7 @@ static Object* Runtime_RegExpCompile(Arguments args) { } -static Object* Runtime_CreateApiFunction(Arguments args) { +static MaybeObject* Runtime_CreateApiFunction(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); CONVERT_ARG_CHECKED(FunctionTemplateInfo, data, 0); @@ -779,7 +803,7 @@ static Object* Runtime_CreateApiFunction(Arguments args) { } -static Object* Runtime_IsTemplate(Arguments args) { +static MaybeObject* Runtime_IsTemplate(Arguments args) { ASSERT(args.length() == 1); Object* arg = args[0]; bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo(); @@ -787,7 +811,7 @@ static Object* Runtime_IsTemplate(Arguments args) { } -static Object* Runtime_GetTemplateField(Arguments args) { +static MaybeObject* Runtime_GetTemplateField(Arguments args) { ASSERT(args.length() == 2); CONVERT_CHECKED(HeapObject, templ, args[0]); CONVERT_CHECKED(Smi, field, args[1]); @@ -806,15 +830,17 @@ static Object* Runtime_GetTemplateField(Arguments args) { } -static Object* Runtime_DisableAccessChecks(Arguments args) { +static MaybeObject* Runtime_DisableAccessChecks(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(HeapObject, object, args[0]); Map* old_map = object->map(); bool needs_access_checks = old_map->is_access_check_needed(); if (needs_access_checks) { // Copy map so it won't interfere constructor's initial map. - Object* new_map = old_map->CopyDropTransitions(); - if (new_map->IsFailure()) return new_map; + Object* new_map; + { MaybeObject* maybe_new_map = old_map->CopyDropTransitions(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } Map::cast(new_map)->set_is_access_check_needed(false); object->set_map(Map::cast(new_map)); @@ -823,14 +849,16 @@ static Object* Runtime_DisableAccessChecks(Arguments args) { } -static Object* Runtime_EnableAccessChecks(Arguments args) { +static MaybeObject* Runtime_EnableAccessChecks(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(HeapObject, object, args[0]); Map* old_map = object->map(); if (!old_map->is_access_check_needed()) { // Copy map so it won't interfere constructor's initial map. - Object* new_map = old_map->CopyDropTransitions(); - if (new_map->IsFailure()) return new_map; + Object* new_map; + { MaybeObject* maybe_new_map = old_map->CopyDropTransitions(); + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; + } Map::cast(new_map)->set_is_access_check_needed(true); object->set_map(Map::cast(new_map)); @@ -839,7 +867,7 @@ static Object* Runtime_EnableAccessChecks(Arguments args) { } -static Object* ThrowRedeclarationError(const char* type, Handle<String> name) { +static Failure* ThrowRedeclarationError(const char* type, Handle<String> name) { HandleScope scope; Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type)); Handle<Object> args[2] = { type_handle, name }; @@ -849,7 +877,7 @@ static Object* ThrowRedeclarationError(const char* type, Handle<String> name) { } -static Object* Runtime_DeclareGlobals(Arguments args) { +static MaybeObject* Runtime_DeclareGlobals(Arguments args) { HandleScope scope; Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global()); @@ -961,7 +989,7 @@ static Object* Runtime_DeclareGlobals(Arguments args) { } -static Object* Runtime_DeclareContextSlot(Arguments args) { +static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { HandleScope scope; ASSERT(args.length() == 4); @@ -1046,7 +1074,7 @@ static Object* Runtime_DeclareContextSlot(Arguments args) { } -static Object* Runtime_InitializeVarGlobal(Arguments args) { +static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { NoHandleAllocation nha; // Determine if we need to assign to the variable if it already @@ -1139,7 +1167,7 @@ static Object* Runtime_InitializeVarGlobal(Arguments args) { } -static Object* Runtime_InitializeConstGlobal(Arguments args) { +static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) { // All constants are declared with an initial value. The name // of the constant is the first argument and the initial value // is the second. @@ -1187,12 +1215,13 @@ static Object* Runtime_InitializeConstGlobal(Arguments args) { // Restore global object from context (in case of GC) and continue // with setting the value because the property is either absent or // read-only. We also have to do redo the lookup. - global = Top::context()->global(); + HandleScope handle_scope; + Handle<GlobalObject>global(Top::context()->global()); // BUG 1213579: Handle the case where we have to set a read-only // property through an interceptor and only do it if it's // uninitialized, e.g. the hole. Nirk... - global->SetProperty(*name, *value, attributes); + SetProperty(global, name, value, attributes); return *value; } @@ -1221,7 +1250,7 @@ static Object* Runtime_InitializeConstGlobal(Arguments args) { } -static Object* Runtime_InitializeConstContextSlot(Arguments args) { +static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) { HandleScope scope; ASSERT(args.length() == 3); @@ -1326,7 +1355,7 @@ static Object* Runtime_InitializeConstContextSlot(Arguments args) { } -static Object* Runtime_OptimizeObjectForAddingMultipleProperties( +static MaybeObject* Runtime_OptimizeObjectForAddingMultipleProperties( Arguments args) { HandleScope scope; ASSERT(args.length() == 2); @@ -1339,7 +1368,7 @@ static Object* Runtime_OptimizeObjectForAddingMultipleProperties( } -static Object* Runtime_RegExpExec(Arguments args) { +static MaybeObject* Runtime_RegExpExec(Arguments args) { HandleScope scope; ASSERT(args.length() == 4); CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); @@ -1361,19 +1390,23 @@ static Object* Runtime_RegExpExec(Arguments args) { } -static Object* Runtime_RegExpConstructResult(Arguments args) { +static MaybeObject* Runtime_RegExpConstructResult(Arguments args) { ASSERT(args.length() == 3); CONVERT_SMI_CHECKED(elements_count, args[0]); if (elements_count > JSArray::kMaxFastElementsLength) { return Top::ThrowIllegalOperation(); } - Object* new_object = Heap::AllocateFixedArrayWithHoles(elements_count); - if (new_object->IsFailure()) return new_object; + Object* new_object; + { MaybeObject* maybe_new_object = + Heap::AllocateFixedArrayWithHoles(elements_count); + if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object; + } FixedArray* elements = FixedArray::cast(new_object); - new_object = Heap::AllocateRaw(JSRegExpResult::kSize, - NEW_SPACE, - OLD_POINTER_SPACE); - if (new_object->IsFailure()) return new_object; + { MaybeObject* maybe_new_object = Heap::AllocateRaw(JSRegExpResult::kSize, + NEW_SPACE, + OLD_POINTER_SPACE); + if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object; + } { AssertNoAllocation no_gc; HandleScope scope; @@ -1391,7 +1424,7 @@ static Object* Runtime_RegExpConstructResult(Arguments args) { } -static Object* Runtime_RegExpCloneResult(Arguments args) { +static MaybeObject* Runtime_RegExpCloneResult(Arguments args) { ASSERT(args.length() == 1); Map* regexp_result_map; { @@ -1414,10 +1447,13 @@ static Object* Runtime_RegExpCloneResult(Arguments args) { ASSERT(result->properties() == Heap::empty_fixed_array()); ASSERT_EQ(2, regexp_result_map->inobject_properties()); - Object* new_array_alloc = Heap::AllocateRaw(JSRegExpResult::kSize, - NEW_SPACE, - OLD_POINTER_SPACE); - if (new_array_alloc->IsFailure()) return new_array_alloc; + Object* new_array_alloc; + { MaybeObject* maybe_new_array_alloc = + Heap::AllocateRaw(JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE); + if (!maybe_new_array_alloc->ToObject(&new_array_alloc)) { + return maybe_new_array_alloc; + } + } // Set HeapObject map to JSRegExpResult map. reinterpret_cast<HeapObject*>(new_array_alloc)->set_map(regexp_result_map); @@ -1448,7 +1484,7 @@ static Object* Runtime_RegExpCloneResult(Arguments args) { } -static Object* Runtime_RegExpInitializeObject(Arguments args) { +static MaybeObject* Runtime_RegExpInitializeObject(Arguments args) { AssertNoAllocation no_alloc; ASSERT(args.length() == 5); CONVERT_CHECKED(JSRegExp, regexp, args[0]); @@ -1480,31 +1516,42 @@ static Object* Runtime_RegExpInitializeObject(Arguments args) { return regexp; } - // Map has changed, so use generic, but slower, method. + // Map has changed, so use generic, but slower, method. Since these + // properties were all added as DONT_DELETE they must be present and + // normal so no failures can be expected. PropertyAttributes final = static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE); PropertyAttributes writable = static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); - regexp->IgnoreAttributesAndSetLocalProperty(Heap::source_symbol(), - source, - final); - regexp->IgnoreAttributesAndSetLocalProperty(Heap::global_symbol(), - global, - final); - regexp->IgnoreAttributesAndSetLocalProperty(Heap::ignore_case_symbol(), - ignoreCase, - final); - regexp->IgnoreAttributesAndSetLocalProperty(Heap::multiline_symbol(), - multiline, - final); - regexp->IgnoreAttributesAndSetLocalProperty(Heap::last_index_symbol(), - Smi::FromInt(0), - writable); + MaybeObject* result; + result = regexp->IgnoreAttributesAndSetLocalProperty(Heap::source_symbol(), + source, + final); + ASSERT(!result->IsFailure()); + result = regexp->IgnoreAttributesAndSetLocalProperty(Heap::global_symbol(), + global, + final); + ASSERT(!result->IsFailure()); + result = + regexp->IgnoreAttributesAndSetLocalProperty(Heap::ignore_case_symbol(), + ignoreCase, + final); + ASSERT(!result->IsFailure()); + result = regexp->IgnoreAttributesAndSetLocalProperty(Heap::multiline_symbol(), + multiline, + final); + ASSERT(!result->IsFailure()); + result = + regexp->IgnoreAttributesAndSetLocalProperty(Heap::last_index_symbol(), + Smi::FromInt(0), + writable); + ASSERT(!result->IsFailure()); + USE(result); return regexp; } -static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) { +static MaybeObject* Runtime_FinishArrayPrototypeSetup(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); CONVERT_ARG_CHECKED(JSArray, prototype, 0); @@ -1531,7 +1578,7 @@ static Handle<JSFunction> InstallBuiltin(Handle<JSObject> holder, } -static Object* Runtime_SpecialArrayFunctions(Arguments args) { +static MaybeObject* Runtime_SpecialArrayFunctions(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); CONVERT_ARG_CHECKED(JSObject, holder, 0); @@ -1548,14 +1595,14 @@ static Object* Runtime_SpecialArrayFunctions(Arguments args) { } -static Object* Runtime_GetGlobalReceiver(Arguments args) { +static MaybeObject* Runtime_GetGlobalReceiver(Arguments args) { // Returns a real global receiver, not one of builtins object. Context* global_context = Top::context()->global()->global_context(); return global_context->global()->global_receiver(); } -static Object* Runtime_MaterializeRegExpLiteral(Arguments args) { +static MaybeObject* Runtime_MaterializeRegExpLiteral(Arguments args) { HandleScope scope; ASSERT(args.length() == 4); CONVERT_ARG_CHECKED(FixedArray, literals, 0); @@ -1585,7 +1632,7 @@ static Object* Runtime_MaterializeRegExpLiteral(Arguments args) { } -static Object* Runtime_FunctionGetName(Arguments args) { +static MaybeObject* Runtime_FunctionGetName(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -1594,7 +1641,7 @@ static Object* Runtime_FunctionGetName(Arguments args) { } -static Object* Runtime_FunctionSetName(Arguments args) { +static MaybeObject* Runtime_FunctionSetName(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -1605,19 +1652,21 @@ static Object* Runtime_FunctionSetName(Arguments args) { } -static Object* Runtime_FunctionRemovePrototype(Arguments args) { +static MaybeObject* Runtime_FunctionRemovePrototype(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); CONVERT_CHECKED(JSFunction, f, args[0]); - Object* obj = f->RemovePrototype(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = f->RemovePrototype(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return Heap::undefined_value(); } -static Object* Runtime_FunctionGetScript(Arguments args) { +static MaybeObject* Runtime_FunctionGetScript(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -1629,7 +1678,7 @@ static Object* Runtime_FunctionGetScript(Arguments args) { } -static Object* Runtime_FunctionGetSourceCode(Arguments args) { +static MaybeObject* Runtime_FunctionGetSourceCode(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -1638,7 +1687,7 @@ static Object* Runtime_FunctionGetSourceCode(Arguments args) { } -static Object* Runtime_FunctionGetScriptSourcePosition(Arguments args) { +static MaybeObject* Runtime_FunctionGetScriptSourcePosition(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -1648,7 +1697,7 @@ static Object* Runtime_FunctionGetScriptSourcePosition(Arguments args) { } -static Object* Runtime_FunctionGetPositionForOffset(Arguments args) { +static MaybeObject* Runtime_FunctionGetPositionForOffset(Arguments args) { ASSERT(args.length() == 2); CONVERT_CHECKED(JSFunction, fun, args[0]); @@ -1663,7 +1712,7 @@ static Object* Runtime_FunctionGetPositionForOffset(Arguments args) { -static Object* Runtime_FunctionSetInstanceClassName(Arguments args) { +static MaybeObject* Runtime_FunctionSetInstanceClassName(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -1674,7 +1723,7 @@ static Object* Runtime_FunctionSetInstanceClassName(Arguments args) { } -static Object* Runtime_FunctionSetLength(Arguments args) { +static MaybeObject* Runtime_FunctionSetLength(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -1685,19 +1734,22 @@ static Object* Runtime_FunctionSetLength(Arguments args) { } -static Object* Runtime_FunctionSetPrototype(Arguments args) { +static MaybeObject* Runtime_FunctionSetPrototype(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); CONVERT_CHECKED(JSFunction, fun, args[0]); ASSERT(fun->should_have_prototype()); - Object* obj = Accessors::FunctionSetPrototype(fun, args[1], NULL); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = + Accessors::FunctionSetPrototype(fun, args[1], NULL); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return args[0]; // return TOS } -static Object* Runtime_FunctionIsAPIFunction(Arguments args) { +static MaybeObject* Runtime_FunctionIsAPIFunction(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -1706,7 +1758,7 @@ static Object* Runtime_FunctionIsAPIFunction(Arguments args) { : Heap::false_value(); } -static Object* Runtime_FunctionIsBuiltin(Arguments args) { +static MaybeObject* Runtime_FunctionIsBuiltin(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -1715,7 +1767,7 @@ static Object* Runtime_FunctionIsBuiltin(Arguments args) { } -static Object* Runtime_SetCode(Arguments args) { +static MaybeObject* Runtime_SetCode(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); @@ -1772,7 +1824,7 @@ static Object* Runtime_SetCode(Arguments args) { } -static Object* Runtime_SetExpectedNumberOfProperties(Arguments args) { +static MaybeObject* Runtime_SetExpectedNumberOfProperties(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); CONVERT_ARG_CHECKED(JSFunction, function, 0); @@ -1783,7 +1835,7 @@ static Object* Runtime_SetExpectedNumberOfProperties(Arguments args) { } -static Object* CharFromCode(Object* char_code) { +MUST_USE_RESULT static MaybeObject* CharFromCode(Object* char_code) { uint32_t code; if (char_code->ToArrayIndex(&code)) { if (code <= 0xffff) { @@ -1794,7 +1846,7 @@ static Object* CharFromCode(Object* char_code) { } -static Object* Runtime_StringCharCodeAt(Arguments args) { +static MaybeObject* Runtime_StringCharCodeAt(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -1816,8 +1868,10 @@ static Object* Runtime_StringCharCodeAt(Arguments args) { // Flatten the string. If someone wants to get a char at an index // in a cons string, it is likely that more indices will be // accessed. - Object* flat = subject->TryFlatten(); - if (flat->IsFailure()) return flat; + Object* flat; + { MaybeObject* maybe_flat = subject->TryFlatten(); + if (!maybe_flat->ToObject(&flat)) return maybe_flat; + } subject = String::cast(flat); if (i >= static_cast<uint32_t>(subject->length())) { @@ -1828,7 +1882,7 @@ static Object* Runtime_StringCharCodeAt(Arguments args) { } -static Object* Runtime_CharFromCode(Arguments args) { +static MaybeObject* Runtime_CharFromCode(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); return CharFromCode(args[0]); @@ -2317,10 +2371,11 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder, -static Object* StringReplaceRegExpWithString(String* subject, - JSRegExp* regexp, - String* replacement, - JSArray* last_match_info) { +MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString( + String* subject, + JSRegExp* regexp, + String* replacement, + JSArray* last_match_info) { ASSERT(subject->IsFlat()); ASSERT(replacement->IsFlat()); @@ -2425,9 +2480,10 @@ static Object* StringReplaceRegExpWithString(String* subject, template <typename ResultSeqString> -static Object* StringReplaceRegExpWithEmptyString(String* subject, - JSRegExp* regexp, - JSArray* last_match_info) { +MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString( + String* subject, + JSRegExp* regexp, + JSArray* last_match_info) { ASSERT(subject->IsFlat()); HandleScope handles; @@ -2552,23 +2608,27 @@ static Object* StringReplaceRegExpWithEmptyString(String* subject, } -static Object* Runtime_StringReplaceRegExpWithString(Arguments args) { +static MaybeObject* Runtime_StringReplaceRegExpWithString(Arguments args) { ASSERT(args.length() == 4); CONVERT_CHECKED(String, subject, args[0]); if (!subject->IsFlat()) { - Object* flat_subject = subject->TryFlatten(); - if (flat_subject->IsFailure()) { - return flat_subject; + Object* flat_subject; + { MaybeObject* maybe_flat_subject = subject->TryFlatten(); + if (!maybe_flat_subject->ToObject(&flat_subject)) { + return maybe_flat_subject; + } } subject = String::cast(flat_subject); } CONVERT_CHECKED(String, replacement, args[2]); if (!replacement->IsFlat()) { - Object* flat_replacement = replacement->TryFlatten(); - if (flat_replacement->IsFailure()) { - return flat_replacement; + Object* flat_replacement; + { MaybeObject* maybe_flat_replacement = replacement->TryFlatten(); + if (!maybe_flat_replacement->ToObject(&flat_replacement)) { + return maybe_flat_replacement; + } } replacement = String::cast(flat_replacement); } @@ -2636,7 +2696,7 @@ int Runtime::StringMatch(Handle<String> sub, } -static Object* Runtime_StringIndexOf(Arguments args) { +static MaybeObject* Runtime_StringIndexOf(Arguments args) { HandleScope scope; // create a new handle scope ASSERT(args.length() == 3); @@ -2687,7 +2747,7 @@ static int StringMatchBackwards(Vector<const schar> subject, return -1; } -static Object* Runtime_StringLastIndexOf(Arguments args) { +static MaybeObject* Runtime_StringLastIndexOf(Arguments args) { HandleScope scope; // create a new handle scope ASSERT(args.length() == 3); @@ -2744,7 +2804,7 @@ static Object* Runtime_StringLastIndexOf(Arguments args) { } -static Object* Runtime_StringLocaleCompare(Arguments args) { +static MaybeObject* Runtime_StringLocaleCompare(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -2790,7 +2850,7 @@ static Object* Runtime_StringLocaleCompare(Arguments args) { } -static Object* Runtime_SubString(Arguments args) { +static MaybeObject* Runtime_SubString(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 3); @@ -2817,7 +2877,7 @@ static Object* Runtime_SubString(Arguments args) { } -static Object* Runtime_StringMatch(Arguments args) { +static MaybeObject* Runtime_StringMatch(Arguments args) { ASSERT_EQ(3, args.length()); CONVERT_ARG_CHECKED(String, subject, 0); @@ -3172,7 +3232,7 @@ static RegExpImpl::IrregexpResult SearchRegExpMultiple( } -static Object* Runtime_RegExpExecMultiple(Arguments args) { +static MaybeObject* Runtime_RegExpExecMultiple(Arguments args) { ASSERT(args.length() == 4); HandleScope handles; @@ -3221,7 +3281,7 @@ static Object* Runtime_RegExpExecMultiple(Arguments args) { } -static Object* Runtime_NumberToRadixString(Arguments args) { +static MaybeObject* Runtime_NumberToRadixString(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -3252,13 +3312,13 @@ static Object* Runtime_NumberToRadixString(Arguments args) { int radix = FastD2I(radix_number); RUNTIME_ASSERT(2 <= radix && radix <= 36); char* str = DoubleToRadixCString(value, radix); - Object* result = Heap::AllocateStringFromAscii(CStrVector(str)); + MaybeObject* result = Heap::AllocateStringFromAscii(CStrVector(str)); DeleteArray(str); return result; } -static Object* Runtime_NumberToFixed(Arguments args) { +static MaybeObject* Runtime_NumberToFixed(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -3276,13 +3336,13 @@ static Object* Runtime_NumberToFixed(Arguments args) { int f = FastD2I(f_number); RUNTIME_ASSERT(f >= 0); char* str = DoubleToFixedCString(value, f); - Object* res = Heap::AllocateStringFromAscii(CStrVector(str)); + MaybeObject* result = Heap::AllocateStringFromAscii(CStrVector(str)); DeleteArray(str); - return res; + return result; } -static Object* Runtime_NumberToExponential(Arguments args) { +static MaybeObject* Runtime_NumberToExponential(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -3300,13 +3360,13 @@ static Object* Runtime_NumberToExponential(Arguments args) { int f = FastD2I(f_number); RUNTIME_ASSERT(f >= -1 && f <= 20); char* str = DoubleToExponentialCString(value, f); - Object* res = Heap::AllocateStringFromAscii(CStrVector(str)); + MaybeObject* result = Heap::AllocateStringFromAscii(CStrVector(str)); DeleteArray(str); - return res; + return result; } -static Object* Runtime_NumberToPrecision(Arguments args) { +static MaybeObject* Runtime_NumberToPrecision(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -3324,9 +3384,9 @@ static Object* Runtime_NumberToPrecision(Arguments args) { int f = FastD2I(f_number); RUNTIME_ASSERT(f >= 1 && f <= 21); char* str = DoubleToPrecisionCString(value, f); - Object* res = Heap::AllocateStringFromAscii(CStrVector(str)); + MaybeObject* result = Heap::AllocateStringFromAscii(CStrVector(str)); DeleteArray(str); - return res; + return result; } @@ -3342,7 +3402,8 @@ static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { } -Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) { +MaybeObject* Runtime::GetElementOrCharAt(Handle<Object> object, + uint32_t index) { // Handle [] indexing on Strings if (object->IsString()) { Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); @@ -3366,12 +3427,13 @@ Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) { } -Object* Runtime::GetElement(Handle<Object> object, uint32_t index) { +MaybeObject* Runtime::GetElement(Handle<Object> object, uint32_t index) { return object->GetElement(index); } -Object* Runtime::GetObjectProperty(Handle<Object> object, Handle<Object> key) { +MaybeObject* Runtime::GetObjectProperty(Handle<Object> object, + Handle<Object> key) { HandleScope scope; if (object->IsUndefined() || object->IsNull()) { @@ -3411,7 +3473,7 @@ Object* Runtime::GetObjectProperty(Handle<Object> object, Handle<Object> key) { } -static Object* Runtime_GetProperty(Arguments args) { +static MaybeObject* Runtime_GetProperty(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -3423,7 +3485,7 @@ static Object* Runtime_GetProperty(Arguments args) { // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric. -static Object* Runtime_KeyedGetProperty(Arguments args) { +static MaybeObject* Runtime_KeyedGetProperty(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -3488,7 +3550,7 @@ static Object* Runtime_KeyedGetProperty(Arguments args) { } -static Object* Runtime_DefineOrRedefineAccessorProperty(Arguments args) { +static MaybeObject* Runtime_DefineOrRedefineAccessorProperty(Arguments args) { ASSERT(args.length() == 5); HandleScope scope; CONVERT_ARG_CHECKED(JSObject, obj, 0); @@ -3509,13 +3571,16 @@ static Object* Runtime_DefineOrRedefineAccessorProperty(Arguments args) { if (result.IsProperty() && (result.type() == FIELD || result.type() == NORMAL || result.type() == CONSTANT_FUNCTION)) { - Object* ok = obj->DeleteProperty(name, JSObject::NORMAL_DELETION); - if (ok->IsFailure()) return ok; + Object* ok; + { MaybeObject* maybe_ok = + obj->DeleteProperty(name, JSObject::NORMAL_DELETION); + if (!maybe_ok->ToObject(&ok)) return maybe_ok; + } } return obj->DefineAccessor(name, flag_setter->value() == 0, fun, attr); } -static Object* Runtime_DefineOrRedefineDataProperty(Arguments args) { +static MaybeObject* Runtime_DefineOrRedefineDataProperty(Arguments args) { ASSERT(args.length() == 4); HandleScope scope; CONVERT_ARG_CHECKED(JSObject, js_object, 0); @@ -3538,12 +3603,12 @@ static Object* Runtime_DefineOrRedefineDataProperty(Arguments args) { if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) && is_element) { // Normalize the elements to enable attributes on the property. - js_object->NormalizeElements(); - NumberDictionary* dictionary = js_object->element_dictionary(); + NormalizeElements(js_object); + Handle<NumberDictionary> dictionary(js_object->element_dictionary()); // Make sure that we never go back to fast case. dictionary->set_requires_slow_elements(); PropertyDetails details = PropertyDetails(attr, NORMAL); - dictionary->Set(index, *obj_value, details); + NumberDictionarySet(dictionary, index, obj_value, details); } LookupResult result; @@ -3557,7 +3622,7 @@ static Object* Runtime_DefineOrRedefineDataProperty(Arguments args) { // new attributes. if (result.IsProperty() && attr != result.GetAttributes()) { // New attributes - normalize to avoid writing to instance descriptor - js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); + NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); // Use IgnoreAttributes version since a readonly property may be // overridden and SetProperty does not allow this. return js_object->IgnoreAttributesAndSetLocalProperty(*name, @@ -3569,10 +3634,10 @@ static Object* Runtime_DefineOrRedefineDataProperty(Arguments args) { } -Object* Runtime::SetObjectProperty(Handle<Object> object, - Handle<Object> key, - Handle<Object> value, - PropertyAttributes attr) { +MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, + Handle<Object> key, + Handle<Object> value, + PropertyAttributes attr) { HandleScope scope; if (object->IsUndefined() || object->IsNull()) { @@ -3634,10 +3699,10 @@ Object* Runtime::SetObjectProperty(Handle<Object> object, } -Object* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object, - Handle<Object> key, - Handle<Object> value, - PropertyAttributes attr) { +MaybeObject* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object, + Handle<Object> key, + Handle<Object> value, + PropertyAttributes attr) { HandleScope scope; // Check if the given key is an array index. @@ -3683,8 +3748,8 @@ Object* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object, } -Object* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, - Handle<Object> key) { +MaybeObject* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, + Handle<Object> key) { HandleScope scope; // Check if the given key is an array index. @@ -3719,7 +3784,7 @@ Object* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, } -static Object* Runtime_SetProperty(Arguments args) { +static MaybeObject* Runtime_SetProperty(Arguments args) { NoHandleAllocation ha; RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); @@ -3743,7 +3808,7 @@ static Object* Runtime_SetProperty(Arguments args) { // Set a local property, even if it is READ_ONLY. If the property does not // exist, it will be added with attributes NONE. -static Object* Runtime_IgnoreAttributesAndSetProperty(Arguments args) { +static MaybeObject* Runtime_IgnoreAttributesAndSetProperty(Arguments args) { NoHandleAllocation ha; RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); CONVERT_CHECKED(JSObject, object, args[0]); @@ -3764,7 +3829,7 @@ static Object* Runtime_IgnoreAttributesAndSetProperty(Arguments args) { } -static Object* Runtime_DeleteProperty(Arguments args) { +static MaybeObject* Runtime_DeleteProperty(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -3789,7 +3854,7 @@ static Object* HasLocalPropertyImplementation(Handle<JSObject> object, } -static Object* Runtime_HasLocalProperty(Arguments args) { +static MaybeObject* Runtime_HasLocalProperty(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); CONVERT_CHECKED(String, key, args[1]); @@ -3818,7 +3883,7 @@ static Object* Runtime_HasLocalProperty(Arguments args) { } -static Object* Runtime_HasProperty(Arguments args) { +static MaybeObject* Runtime_HasProperty(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 2); @@ -3832,7 +3897,7 @@ static Object* Runtime_HasProperty(Arguments args) { } -static Object* Runtime_HasElement(Arguments args) { +static MaybeObject* Runtime_HasElement(Arguments args) { NoHandleAllocation na; ASSERT(args.length() == 2); @@ -3847,7 +3912,7 @@ static Object* Runtime_HasElement(Arguments args) { } -static Object* Runtime_IsPropertyEnumerable(Arguments args) { +static MaybeObject* Runtime_IsPropertyEnumerable(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -3864,7 +3929,7 @@ static Object* Runtime_IsPropertyEnumerable(Arguments args) { } -static Object* Runtime_GetPropertyNames(Arguments args) { +static MaybeObject* Runtime_GetPropertyNames(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); CONVERT_ARG_CHECKED(JSObject, object, 0); @@ -3877,7 +3942,7 @@ static Object* Runtime_GetPropertyNames(Arguments args) { // all enumerable properties of the object and its prototypes // have none, the map of the object. This is used to speed up // the check for deletions during a for-in. -static Object* Runtime_GetPropertyNamesFast(Arguments args) { +static MaybeObject* Runtime_GetPropertyNamesFast(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(JSObject, raw_object, args[0]); @@ -3913,7 +3978,7 @@ static int LocalPrototypeChainLength(JSObject* obj) { // Return the names of the local named properties. // args[0]: object -static Object* Runtime_GetLocalPropertyNames(Arguments args) { +static MaybeObject* Runtime_GetLocalPropertyNames(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); if (!args[0]->IsJSObject()) { @@ -3996,7 +4061,7 @@ static Object* Runtime_GetLocalPropertyNames(Arguments args) { // Return the names of the local indexed properties. // args[0]: object -static Object* Runtime_GetLocalElementNames(Arguments args) { +static MaybeObject* Runtime_GetLocalElementNames(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); if (!args[0]->IsJSObject()) { @@ -4013,7 +4078,7 @@ static Object* Runtime_GetLocalElementNames(Arguments args) { // Return information on whether an object has a named or indexed interceptor. // args[0]: object -static Object* Runtime_GetInterceptorInfo(Arguments args) { +static MaybeObject* Runtime_GetInterceptorInfo(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); if (!args[0]->IsJSObject()) { @@ -4031,7 +4096,7 @@ static Object* Runtime_GetInterceptorInfo(Arguments args) { // Return property names from named interceptor. // args[0]: object -static Object* Runtime_GetNamedInterceptorPropertyNames(Arguments args) { +static MaybeObject* Runtime_GetNamedInterceptorPropertyNames(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); CONVERT_ARG_CHECKED(JSObject, obj, 0); @@ -4046,7 +4111,7 @@ static Object* Runtime_GetNamedInterceptorPropertyNames(Arguments args) { // Return element names from indexed interceptor. // args[0]: object -static Object* Runtime_GetIndexedInterceptorElementNames(Arguments args) { +static MaybeObject* Runtime_GetIndexedInterceptorElementNames(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); CONVERT_ARG_CHECKED(JSObject, obj, 0); @@ -4059,7 +4124,7 @@ static Object* Runtime_GetIndexedInterceptorElementNames(Arguments args) { } -static Object* Runtime_LocalKeys(Arguments args) { +static MaybeObject* Runtime_LocalKeys(Arguments args) { ASSERT_EQ(args.length(), 1); CONVERT_CHECKED(JSObject, raw_object, args[0]); HandleScope scope; @@ -4087,7 +4152,7 @@ static Object* Runtime_LocalKeys(Arguments args) { } -static Object* Runtime_GetArgumentsProperty(Arguments args) { +static MaybeObject* Runtime_GetArgumentsProperty(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -4132,7 +4197,7 @@ static Object* Runtime_GetArgumentsProperty(Arguments args) { } -static Object* Runtime_ToFastProperties(Arguments args) { +static MaybeObject* Runtime_ToFastProperties(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -4140,27 +4205,28 @@ static Object* Runtime_ToFastProperties(Arguments args) { if (object->IsJSObject()) { Handle<JSObject> js_object = Handle<JSObject>::cast(object); if (!js_object->HasFastProperties() && !js_object->IsGlobalObject()) { - js_object->TransformToFastProperties(0); + MaybeObject* ok = js_object->TransformToFastProperties(0); + if (ok->IsRetryAfterGC()) return ok; } } return *object; } -static Object* Runtime_ToSlowProperties(Arguments args) { +static MaybeObject* Runtime_ToSlowProperties(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); Handle<Object> object = args.at<Object>(0); if (object->IsJSObject()) { Handle<JSObject> js_object = Handle<JSObject>::cast(object); - js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); + NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); } return *object; } -static Object* Runtime_ToBool(Arguments args) { +static MaybeObject* Runtime_ToBool(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -4170,7 +4236,7 @@ static Object* Runtime_ToBool(Arguments args) { // Returns the type string of a value; see ECMA-262, 11.4.3 (p 47). // Possible optimizations: put the type string into the oddballs. -static Object* Runtime_Typeof(Arguments args) { +static MaybeObject* Runtime_Typeof(Arguments args) { NoHandleAllocation ha; Object* obj = args[0]; @@ -4227,7 +4293,7 @@ static int ParseDecimalInteger(const char*s, int from, int to) { } -static Object* Runtime_StringToNumber(Arguments args) { +static MaybeObject* Runtime_StringToNumber(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); CONVERT_CHECKED(String, subject, args[0]); @@ -4281,7 +4347,7 @@ static Object* Runtime_StringToNumber(Arguments args) { } -static Object* Runtime_StringFromCharCodeArray(Arguments args) { +static MaybeObject* Runtime_StringFromCharCodeArray(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -4291,23 +4357,32 @@ static Object* Runtime_StringFromCharCodeArray(Arguments args) { // Check if the string can be ASCII. int i; for (i = 0; i < length; i++) { - Object* element = codes->GetElement(i); + Object* element; + { MaybeObject* maybe_element = codes->GetElement(i); + // We probably can't get an exception here, but just in order to enforce + // the checking of inputs in the runtime calls we check here. + if (!maybe_element->ToObject(&element)) return maybe_element; + } CONVERT_NUMBER_CHECKED(int, chr, Int32, element); if ((chr & 0xffff) > String::kMaxAsciiCharCode) break; } - Object* object = NULL; + MaybeObject* maybe_object = NULL; if (i == length) { // The string is ASCII. - object = Heap::AllocateRawAsciiString(length); + maybe_object = Heap::AllocateRawAsciiString(length); } else { // The string is not ASCII. - object = Heap::AllocateRawTwoByteString(length); + maybe_object = Heap::AllocateRawTwoByteString(length); } - if (object->IsFailure()) return object; + Object* object = NULL; + if (!maybe_object->ToObject(&object)) return maybe_object; String* result = String::cast(object); for (int i = 0; i < length; i++) { - Object* element = codes->GetElement(i); + Object* element; + { MaybeObject* maybe_element = codes->GetElement(i); + if (!maybe_element->ToObject(&element)) return maybe_element; + } CONVERT_NUMBER_CHECKED(int, chr, Int32, element); result->Set(i, chr & 0xffff); } @@ -4352,7 +4427,7 @@ static bool IsNotEscaped(uint16_t character) { } -static Object* Runtime_URIEscape(Arguments args) { +static MaybeObject* Runtime_URIEscape(Arguments args) { const char hex_chars[] = "0123456789ABCDEF"; NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -4386,8 +4461,10 @@ static Object* Runtime_URIEscape(Arguments args) { if (escaped_length == length) { return source; } - Object* o = Heap::AllocateRawAsciiString(escaped_length); - if (o->IsFailure()) return o; + Object* o; + { MaybeObject* maybe_o = Heap::AllocateRawAsciiString(escaped_length); + if (!maybe_o->ToObject(&o)) return maybe_o; + } String* destination = String::cast(o); int dest_position = 0; @@ -4466,7 +4543,7 @@ static inline int Unescape(String* source, } -static Object* Runtime_URIUnescape(Arguments args) { +static MaybeObject* Runtime_URIUnescape(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); CONVERT_CHECKED(String, source, args[0]); @@ -4489,10 +4566,12 @@ static Object* Runtime_URIUnescape(Arguments args) { if (unescaped_length == length) return source; - Object* o = ascii ? - Heap::AllocateRawAsciiString(unescaped_length) : - Heap::AllocateRawTwoByteString(unescaped_length); - if (o->IsFailure()) return o; + Object* o; + { MaybeObject* maybe_o = ascii ? + Heap::AllocateRawAsciiString(unescaped_length) : + Heap::AllocateRawTwoByteString(unescaped_length); + if (!maybe_o->ToObject(&o)) return maybe_o; + } String* destination = String::cast(o); int dest_position = 0; @@ -4505,7 +4584,7 @@ static Object* Runtime_URIUnescape(Arguments args) { } -static Object* Runtime_StringParseInt(Arguments args) { +static MaybeObject* Runtime_StringParseInt(Arguments args) { NoHandleAllocation ha; CONVERT_CHECKED(String, s, args[0]); @@ -4519,7 +4598,7 @@ static Object* Runtime_StringParseInt(Arguments args) { } -static Object* Runtime_StringParseFloat(Arguments args) { +static MaybeObject* Runtime_StringParseFloat(Arguments args) { NoHandleAllocation ha; CONVERT_CHECKED(String, str, args[0]); @@ -4536,10 +4615,11 @@ static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping; template <class Converter> -static Object* ConvertCaseHelper(String* s, - int length, - int input_string_length, - unibrow::Mapping<Converter, 128>* mapping) { +MUST_USE_RESULT static MaybeObject* ConvertCaseHelper( + String* s, + int length, + int input_string_length, + unibrow::Mapping<Converter, 128>* mapping) { // We try this twice, once with the assumption that the result is no longer // than the input and, if that assumption breaks, again with the exact // length. This may not be pretty, but it is nicer than what was here before @@ -4551,10 +4631,12 @@ static Object* ConvertCaseHelper(String* s, // character is also ascii. This is currently the case, but it // might break in the future if we implement more context and locale // dependent upper/lower conversions. - Object* o = s->IsAsciiRepresentation() - ? Heap::AllocateRawAsciiString(length) - : Heap::AllocateRawTwoByteString(length); - if (o->IsFailure()) return o; + Object* o; + { MaybeObject* maybe_o = s->IsAsciiRepresentation() + ? Heap::AllocateRawAsciiString(length) + : Heap::AllocateRawTwoByteString(length); + if (!maybe_o->ToObject(&o)) return maybe_o; + } String* result = String::cast(o); bool has_changed_character = false; @@ -4636,46 +4718,134 @@ static Object* ConvertCaseHelper(String* s, namespace { -struct ToLowerTraits { - typedef unibrow::ToLowercase UnibrowConverter; +static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF; + + +// Given a word and two range boundaries returns a word with high bit +// set in every byte iff the corresponding input byte was strictly in +// the range (m, n). All the other bits in the result are cleared. +// This function is only useful when it can be inlined and the +// boundaries are statically known. +// Requires: all bytes in the input word and the boundaries must be +// ascii (less than 0x7F). +static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) { + // Every byte in an ascii string is less than or equal to 0x7F. + ASSERT((w & (kOneInEveryByte * 0x7F)) == w); + // Use strict inequalities since in edge cases the function could be + // further simplified. + ASSERT(0 < m && m < n && n < 0x7F); + // Has high bit set in every w byte less than n. + uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w; + // Has high bit set in every w byte greater than m. + uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m); + return (tmp1 & tmp2 & (kOneInEveryByte * 0x80)); +} + + +enum AsciiCaseConversion { + ASCII_TO_LOWER, + ASCII_TO_UPPER +}; - static bool ConvertAscii(char* dst, char* src, int length) { + +template <AsciiCaseConversion dir> +struct FastAsciiConverter { + static bool Convert(char* dst, char* src, int length) { +#ifdef DEBUG + char* saved_dst = dst; + char* saved_src = src; +#endif + // We rely on the distance between upper and lower case letters + // being a known power of 2. + ASSERT('a' - 'A' == (1 << 5)); + // Boundaries for the range of input characters than require conversion. + const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1; + const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1; bool changed = false; - for (int i = 0; i < length; ++i) { - char c = src[i]; - if ('A' <= c && c <= 'Z') { - c += ('a' - 'A'); + char* const limit = src + length; +#ifdef V8_HOST_CAN_READ_UNALIGNED + // Process the prefix of the input that requires no conversion one + // (machine) word at a time. + while (src <= limit - sizeof(uintptr_t)) { + uintptr_t w = *reinterpret_cast<uintptr_t*>(src); + if (AsciiRangeMask(w, lo, hi) != 0) { changed = true; + break; } - dst[i] = c; + *reinterpret_cast<uintptr_t*>(dst) = w; + src += sizeof(uintptr_t); + dst += sizeof(uintptr_t); + } + // Process the remainder of the input performing conversion when + // required one word at a time. + while (src <= limit - sizeof(uintptr_t)) { + uintptr_t w = *reinterpret_cast<uintptr_t*>(src); + uintptr_t m = AsciiRangeMask(w, lo, hi); + // The mask has high (7th) bit set in every byte that needs + // conversion and we know that the distance between cases is + // 1 << 5. + *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2); + src += sizeof(uintptr_t); + dst += sizeof(uintptr_t); } +#endif + // Process the last few bytes of the input (or the whole input if + // unaligned access is not supported). + while (src < limit) { + char c = *src; + if (lo < c && c < hi) { + c ^= (1 << 5); + changed = true; + } + *dst = c; + ++src; + ++dst; + } +#ifdef DEBUG + CheckConvert(saved_dst, saved_src, length, changed); +#endif return changed; } + +#ifdef DEBUG + static void CheckConvert(char* dst, char* src, int length, bool changed) { + bool expected_changed = false; + for (int i = 0; i < length; i++) { + if (dst[i] == src[i]) continue; + expected_changed = true; + if (dir == ASCII_TO_LOWER) { + ASSERT('A' <= src[i] && src[i] <= 'Z'); + ASSERT(dst[i] == src[i] + ('a' - 'A')); + } else { + ASSERT(dir == ASCII_TO_UPPER); + ASSERT('a' <= src[i] && src[i] <= 'z'); + ASSERT(dst[i] == src[i] - ('a' - 'A')); + } + } + ASSERT(expected_changed == changed); + } +#endif +}; + + +struct ToLowerTraits { + typedef unibrow::ToLowercase UnibrowConverter; + + typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter; }; struct ToUpperTraits { typedef unibrow::ToUppercase UnibrowConverter; - static bool ConvertAscii(char* dst, char* src, int length) { - bool changed = false; - for (int i = 0; i < length; ++i) { - char c = src[i]; - if ('a' <= c && c <= 'z') { - c -= ('a' - 'A'); - changed = true; - } - dst[i] = c; - } - return changed; - } + typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter; }; } // namespace template <typename ConvertTraits> -static Object* ConvertCase( +MUST_USE_RESULT static MaybeObject* ConvertCase( Arguments args, unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) { NoHandleAllocation ha; @@ -4693,29 +4863,37 @@ static Object* ConvertCase( // might break in the future if we implement more context and locale // dependent upper/lower conversions. if (s->IsSeqAsciiString()) { - Object* o = Heap::AllocateRawAsciiString(length); - if (o->IsFailure()) return o; + Object* o; + { MaybeObject* maybe_o = Heap::AllocateRawAsciiString(length); + if (!maybe_o->ToObject(&o)) return maybe_o; + } SeqAsciiString* result = SeqAsciiString::cast(o); - bool has_changed_character = ConvertTraits::ConvertAscii( + bool has_changed_character = ConvertTraits::AsciiConverter::Convert( result->GetChars(), SeqAsciiString::cast(s)->GetChars(), length); return has_changed_character ? result : s; } - Object* answer = ConvertCaseHelper(s, length, length, mapping); + Object* answer; + { MaybeObject* maybe_answer = ConvertCaseHelper(s, length, length, mapping); + if (!maybe_answer->ToObject(&answer)) return maybe_answer; + } if (answer->IsSmi()) { // Retry with correct length. - answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping); + { MaybeObject* maybe_answer = + ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping); + if (!maybe_answer->ToObject(&answer)) return maybe_answer; + } } - return answer; // This may be a failure. + return answer; } -static Object* Runtime_StringToLowerCase(Arguments args) { +static MaybeObject* Runtime_StringToLowerCase(Arguments args) { return ConvertCase<ToLowerTraits>(args, &to_lower_mapping); } -static Object* Runtime_StringToUpperCase(Arguments args) { +static MaybeObject* Runtime_StringToUpperCase(Arguments args) { return ConvertCase<ToUpperTraits>(args, &to_upper_mapping); } @@ -4725,7 +4903,7 @@ static inline bool IsTrimWhiteSpace(unibrow::uchar c) { } -static Object* Runtime_StringTrim(Arguments args) { +static MaybeObject* Runtime_StringTrim(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 3); @@ -4774,7 +4952,7 @@ void FindStringIndices(Vector<const SubjectChar> subject, } -static Object* Runtime_StringSplit(Arguments args) { +static MaybeObject* Runtime_StringSplit(Arguments args) { ASSERT(args.length() == 3); HandleScope handle_scope; CONVERT_ARG_CHECKED(String, subject, 0); @@ -4900,7 +5078,7 @@ static int CopyCachedAsciiCharsToArray(const char* chars, // Converts a String to JSArray. // For example, "foo" => ["f", "o", "o"]. -static Object* Runtime_StringToArray(Arguments args) { +static MaybeObject* Runtime_StringToArray(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); CONVERT_ARG_CHECKED(String, s, 0); @@ -4910,8 +5088,10 @@ static Object* Runtime_StringToArray(Arguments args) { Handle<FixedArray> elements; if (s->IsFlat() && s->IsAsciiRepresentation()) { - Object* obj = Heap::AllocateUninitializedFixedArray(length); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateUninitializedFixedArray(length); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } elements = Handle<FixedArray>(FixedArray::cast(obj)); Vector<const char> chars = s->ToAsciiVector(); @@ -4943,7 +5123,7 @@ static Object* Runtime_StringToArray(Arguments args) { } -static Object* Runtime_NewStringWrapper(Arguments args) { +static MaybeObject* Runtime_NewStringWrapper(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); CONVERT_CHECKED(String, value, args[0]); @@ -4958,7 +5138,7 @@ bool Runtime::IsUpperCaseChar(uint16_t ch) { } -static Object* Runtime_NumberToString(Arguments args) { +static MaybeObject* Runtime_NumberToString(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -4969,7 +5149,7 @@ static Object* Runtime_NumberToString(Arguments args) { } -static Object* Runtime_NumberToStringSkipCache(Arguments args) { +static MaybeObject* Runtime_NumberToStringSkipCache(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -4980,7 +5160,7 @@ static Object* Runtime_NumberToStringSkipCache(Arguments args) { } -static Object* Runtime_NumberToInteger(Arguments args) { +static MaybeObject* Runtime_NumberToInteger(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -4994,7 +5174,7 @@ static Object* Runtime_NumberToInteger(Arguments args) { } -static Object* Runtime_NumberToIntegerMapMinusZero(Arguments args) { +static MaybeObject* Runtime_NumberToIntegerMapMinusZero(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -5013,7 +5193,7 @@ static Object* Runtime_NumberToIntegerMapMinusZero(Arguments args) { } -static Object* Runtime_NumberToJSUint32(Arguments args) { +static MaybeObject* Runtime_NumberToJSUint32(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -5022,7 +5202,7 @@ static Object* Runtime_NumberToJSUint32(Arguments args) { } -static Object* Runtime_NumberToJSInt32(Arguments args) { +static MaybeObject* Runtime_NumberToJSInt32(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -5038,7 +5218,7 @@ static Object* Runtime_NumberToJSInt32(Arguments args) { // Converts a Number to a Smi, if possible. Returns NaN if the number is not // a small integer. -static Object* Runtime_NumberToSmi(Arguments args) { +static MaybeObject* Runtime_NumberToSmi(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -5057,7 +5237,7 @@ static Object* Runtime_NumberToSmi(Arguments args) { } -static Object* Runtime_NumberAdd(Arguments args) { +static MaybeObject* Runtime_NumberAdd(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5067,7 +5247,7 @@ static Object* Runtime_NumberAdd(Arguments args) { } -static Object* Runtime_NumberSub(Arguments args) { +static MaybeObject* Runtime_NumberSub(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5077,7 +5257,7 @@ static Object* Runtime_NumberSub(Arguments args) { } -static Object* Runtime_NumberMul(Arguments args) { +static MaybeObject* Runtime_NumberMul(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5087,7 +5267,7 @@ static Object* Runtime_NumberMul(Arguments args) { } -static Object* Runtime_NumberUnaryMinus(Arguments args) { +static MaybeObject* Runtime_NumberUnaryMinus(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -5096,7 +5276,7 @@ static Object* Runtime_NumberUnaryMinus(Arguments args) { } -static Object* Runtime_NumberAlloc(Arguments args) { +static MaybeObject* Runtime_NumberAlloc(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 0); @@ -5104,7 +5284,7 @@ static Object* Runtime_NumberAlloc(Arguments args) { } -static Object* Runtime_NumberDiv(Arguments args) { +static MaybeObject* Runtime_NumberDiv(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5114,7 +5294,7 @@ static Object* Runtime_NumberDiv(Arguments args) { } -static Object* Runtime_NumberMod(Arguments args) { +static MaybeObject* Runtime_NumberMod(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5127,7 +5307,7 @@ static Object* Runtime_NumberMod(Arguments args) { } -static Object* Runtime_StringAdd(Arguments args) { +static MaybeObject* Runtime_StringAdd(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); CONVERT_CHECKED(String, str1, args[0]); @@ -5176,7 +5356,7 @@ static inline void StringBuilderConcatHelper(String* special, } -static Object* Runtime_StringBuilderConcat(Arguments args) { +static MaybeObject* Runtime_StringBuilderConcat(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 3); CONVERT_CHECKED(JSArray, array, args[0]); @@ -5264,8 +5444,9 @@ static Object* Runtime_StringBuilderConcat(Arguments args) { Object* object; if (ascii) { - object = Heap::AllocateRawAsciiString(length); - if (object->IsFailure()) return object; + { MaybeObject* maybe_object = Heap::AllocateRawAsciiString(length); + if (!maybe_object->ToObject(&object)) return maybe_object; + } SeqAsciiString* answer = SeqAsciiString::cast(object); StringBuilderConcatHelper(special, answer->GetChars(), @@ -5273,8 +5454,9 @@ static Object* Runtime_StringBuilderConcat(Arguments args) { array_length); return answer; } else { - object = Heap::AllocateRawTwoByteString(length); - if (object->IsFailure()) return object; + { MaybeObject* maybe_object = Heap::AllocateRawTwoByteString(length); + if (!maybe_object->ToObject(&object)) return maybe_object; + } SeqTwoByteString* answer = SeqTwoByteString::cast(object); StringBuilderConcatHelper(special, answer->GetChars(), @@ -5285,7 +5467,7 @@ static Object* Runtime_StringBuilderConcat(Arguments args) { } -static Object* Runtime_NumberOr(Arguments args) { +static MaybeObject* Runtime_NumberOr(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5295,7 +5477,7 @@ static Object* Runtime_NumberOr(Arguments args) { } -static Object* Runtime_NumberAnd(Arguments args) { +static MaybeObject* Runtime_NumberAnd(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5305,7 +5487,7 @@ static Object* Runtime_NumberAnd(Arguments args) { } -static Object* Runtime_NumberXor(Arguments args) { +static MaybeObject* Runtime_NumberXor(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5315,7 +5497,7 @@ static Object* Runtime_NumberXor(Arguments args) { } -static Object* Runtime_NumberNot(Arguments args) { +static MaybeObject* Runtime_NumberNot(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -5324,7 +5506,7 @@ static Object* Runtime_NumberNot(Arguments args) { } -static Object* Runtime_NumberShl(Arguments args) { +static MaybeObject* Runtime_NumberShl(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5334,7 +5516,7 @@ static Object* Runtime_NumberShl(Arguments args) { } -static Object* Runtime_NumberShr(Arguments args) { +static MaybeObject* Runtime_NumberShr(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5344,7 +5526,7 @@ static Object* Runtime_NumberShr(Arguments args) { } -static Object* Runtime_NumberSar(Arguments args) { +static MaybeObject* Runtime_NumberSar(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5354,7 +5536,7 @@ static Object* Runtime_NumberSar(Arguments args) { } -static Object* Runtime_NumberEquals(Arguments args) { +static MaybeObject* Runtime_NumberEquals(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5373,7 +5555,7 @@ static Object* Runtime_NumberEquals(Arguments args) { } -static Object* Runtime_StringEquals(Arguments args) { +static MaybeObject* Runtime_StringEquals(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5391,7 +5573,7 @@ static Object* Runtime_StringEquals(Arguments args) { } -static Object* Runtime_NumberCompare(Arguments args) { +static MaybeObject* Runtime_NumberCompare(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 3); @@ -5406,7 +5588,7 @@ static Object* Runtime_NumberCompare(Arguments args) { // Compare two Smis as if they were converted to strings and then // compared lexicographically. -static Object* Runtime_SmiLexicographicCompare(Arguments args) { +static MaybeObject* Runtime_SmiLexicographicCompare(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5524,7 +5706,7 @@ static Object* FlatStringCompare(String* x, String* y) { } -static Object* Runtime_StringCompare(Arguments args) { +static MaybeObject* Runtime_StringCompare(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -5546,17 +5728,20 @@ static Object* Runtime_StringCompare(Arguments args) { if (d < 0) return Smi::FromInt(LESS); else if (d > 0) return Smi::FromInt(GREATER); - Object* obj = Heap::PrepareForCompare(x); - if (obj->IsFailure()) return obj; - obj = Heap::PrepareForCompare(y); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::PrepareForCompare(x); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } + { MaybeObject* maybe_obj = Heap::PrepareForCompare(y); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y) : StringInputBufferCompare(x, y); } -static Object* Runtime_Math_acos(Arguments args) { +static MaybeObject* Runtime_Math_acos(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_acos.Increment(); @@ -5566,7 +5751,7 @@ static Object* Runtime_Math_acos(Arguments args) { } -static Object* Runtime_Math_asin(Arguments args) { +static MaybeObject* Runtime_Math_asin(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_asin.Increment(); @@ -5576,7 +5761,7 @@ static Object* Runtime_Math_asin(Arguments args) { } -static Object* Runtime_Math_atan(Arguments args) { +static MaybeObject* Runtime_Math_atan(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_atan.Increment(); @@ -5586,7 +5771,7 @@ static Object* Runtime_Math_atan(Arguments args) { } -static Object* Runtime_Math_atan2(Arguments args) { +static MaybeObject* Runtime_Math_atan2(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); Counters::math_atan2.Increment(); @@ -5610,7 +5795,7 @@ static Object* Runtime_Math_atan2(Arguments args) { } -static Object* Runtime_Math_ceil(Arguments args) { +static MaybeObject* Runtime_Math_ceil(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_ceil.Increment(); @@ -5620,7 +5805,7 @@ static Object* Runtime_Math_ceil(Arguments args) { } -static Object* Runtime_Math_cos(Arguments args) { +static MaybeObject* Runtime_Math_cos(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_cos.Increment(); @@ -5630,7 +5815,7 @@ static Object* Runtime_Math_cos(Arguments args) { } -static Object* Runtime_Math_exp(Arguments args) { +static MaybeObject* Runtime_Math_exp(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_exp.Increment(); @@ -5640,7 +5825,7 @@ static Object* Runtime_Math_exp(Arguments args) { } -static Object* Runtime_Math_floor(Arguments args) { +static MaybeObject* Runtime_Math_floor(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_floor.Increment(); @@ -5650,7 +5835,7 @@ static Object* Runtime_Math_floor(Arguments args) { } -static Object* Runtime_Math_log(Arguments args) { +static MaybeObject* Runtime_Math_log(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_log.Increment(); @@ -5691,7 +5876,7 @@ static double powi(double x, int y) { } -static Object* Runtime_Math_pow(Arguments args) { +static MaybeObject* Runtime_Math_pow(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); Counters::math_pow.Increment(); @@ -5731,7 +5916,7 @@ static Object* Runtime_Math_pow(Arguments args) { // Fast version of Math.pow if we know that y is not an integer and // y is not -0.5 or 0.5. Used as slowcase from codegen. -static Object* Runtime_Math_pow_cfunction(Arguments args) { +static MaybeObject* Runtime_Math_pow_cfunction(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); CONVERT_DOUBLE_CHECKED(x, args[0]); @@ -5746,7 +5931,7 @@ static Object* Runtime_Math_pow_cfunction(Arguments args) { } -static Object* Runtime_RoundNumber(Arguments args) { +static MaybeObject* Runtime_RoundNumber(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_round.Increment(); @@ -5782,7 +5967,7 @@ static Object* Runtime_RoundNumber(Arguments args) { } -static Object* Runtime_Math_sin(Arguments args) { +static MaybeObject* Runtime_Math_sin(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_sin.Increment(); @@ -5792,7 +5977,7 @@ static Object* Runtime_Math_sin(Arguments args) { } -static Object* Runtime_Math_sqrt(Arguments args) { +static MaybeObject* Runtime_Math_sqrt(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_sqrt.Increment(); @@ -5802,7 +5987,7 @@ static Object* Runtime_Math_sqrt(Arguments args) { } -static Object* Runtime_Math_tan(Arguments args) { +static MaybeObject* Runtime_Math_tan(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); Counters::math_tan.Increment(); @@ -5857,7 +6042,7 @@ static int MakeDay(int year, int month, int day) { } -static Object* Runtime_DateMakeDay(Arguments args) { +static MaybeObject* Runtime_DateMakeDay(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 3); @@ -6156,7 +6341,7 @@ static inline void DateYMDFromTime(int date, } -static Object* Runtime_DateYMDFromTime(Arguments args) { +static MaybeObject* Runtime_DateYMDFromTime(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -6178,7 +6363,7 @@ static Object* Runtime_DateYMDFromTime(Arguments args) { } -static Object* Runtime_NewArgumentsFast(Arguments args) { +static MaybeObject* Runtime_NewArgumentsFast(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 3); @@ -6186,13 +6371,17 @@ static Object* Runtime_NewArgumentsFast(Arguments args) { Object** parameters = reinterpret_cast<Object**>(args[1]); const int length = Smi::cast(args[2])->value(); - Object* result = Heap::AllocateArgumentsObject(callee, length); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::AllocateArgumentsObject(callee, length); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Allocate the elements if needed. if (length > 0) { // Allocate the fixed array. - Object* obj = Heap::AllocateRawFixedArray(length); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateRawFixedArray(length); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } AssertNoAllocation no_gc; FixedArray* array = reinterpret_cast<FixedArray*>(obj); @@ -6209,7 +6398,7 @@ static Object* Runtime_NewArgumentsFast(Arguments args) { } -static Object* Runtime_NewClosure(Arguments args) { +static MaybeObject* Runtime_NewClosure(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); CONVERT_ARG_CHECKED(Context, context, 0); @@ -6223,7 +6412,7 @@ static Object* Runtime_NewClosure(Arguments args) { return *result; } -static Object* Runtime_NewObjectFromBound(Arguments args) { +static MaybeObject* Runtime_NewObjectFromBound(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); CONVERT_ARG_CHECKED(JSFunction, function, 0); @@ -6257,15 +6446,16 @@ static void TrySettingInlineConstructStub(Handle<JSFunction> function) { } if (function->shared()->CanGenerateInlineConstructor(*prototype)) { ConstructStubCompiler compiler; - Object* code = compiler.CompileConstructStub(function->shared()); + MaybeObject* code = compiler.CompileConstructStub(function->shared()); if (!code->IsFailure()) { - function->shared()->set_construct_stub(Code::cast(code)); + function->shared()->set_construct_stub( + Code::cast(code->ToObjectUnchecked())); } } } -static Object* Runtime_NewObject(Arguments args) { +static MaybeObject* Runtime_NewObject(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -6341,7 +6531,7 @@ static Object* Runtime_NewObject(Arguments args) { } -static Object* Runtime_FinalizeInstanceSize(Arguments args) { +static MaybeObject* Runtime_FinalizeInstanceSize(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -6353,7 +6543,7 @@ static Object* Runtime_FinalizeInstanceSize(Arguments args) { } -static Object* Runtime_LazyCompile(Arguments args) { +static MaybeObject* Runtime_LazyCompile(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -6382,7 +6572,7 @@ static Object* Runtime_LazyCompile(Arguments args) { } -static Object* Runtime_GetFunctionDelegate(Arguments args) { +static MaybeObject* Runtime_GetFunctionDelegate(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); RUNTIME_ASSERT(!args[0]->IsJSFunction()); @@ -6390,7 +6580,7 @@ static Object* Runtime_GetFunctionDelegate(Arguments args) { } -static Object* Runtime_GetConstructorDelegate(Arguments args) { +static MaybeObject* Runtime_GetConstructorDelegate(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); RUNTIME_ASSERT(!args[0]->IsJSFunction()); @@ -6398,27 +6588,33 @@ static Object* Runtime_GetConstructorDelegate(Arguments args) { } -static Object* Runtime_NewContext(Arguments args) { +static MaybeObject* Runtime_NewContext(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); CONVERT_CHECKED(JSFunction, function, args[0]); int length = function->shared()->scope_info()->NumberOfContextSlots(); - Object* result = Heap::AllocateFunctionContext(length, function); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Heap::AllocateFunctionContext(length, function); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Top::set_context(Context::cast(result)); return result; // non-failure } -static Object* PushContextHelper(Object* object, bool is_catch_context) { + +MUST_USE_RESULT static MaybeObject* PushContextHelper(Object* object, + bool is_catch_context) { // Convert the object to a proper JavaScript object. Object* js_object = object; if (!js_object->IsJSObject()) { - js_object = js_object->ToObject(); - if (js_object->IsFailure()) { - if (!Failure::cast(js_object)->IsInternalError()) return js_object; + MaybeObject* maybe_js_object = js_object->ToObject(); + if (!maybe_js_object->ToObject(&js_object)) { + if (!Failure::cast(maybe_js_object)->IsInternalError()) { + return maybe_js_object; + } HandleScope scope; Handle<Object> handle(object); Handle<Object> result = @@ -6427,11 +6623,13 @@ static Object* PushContextHelper(Object* object, bool is_catch_context) { } } - Object* result = - Heap::AllocateWithContext(Top::context(), - JSObject::cast(js_object), - is_catch_context); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + Heap::AllocateWithContext(Top::context(), + JSObject::cast(js_object), + is_catch_context); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Context* context = Context::cast(result); Top::set_context(context); @@ -6440,21 +6638,21 @@ static Object* PushContextHelper(Object* object, bool is_catch_context) { } -static Object* Runtime_PushContext(Arguments args) { +static MaybeObject* Runtime_PushContext(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); return PushContextHelper(args[0], false); } -static Object* Runtime_PushCatchContext(Arguments args) { +static MaybeObject* Runtime_PushCatchContext(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); return PushContextHelper(args[0], true); } -static Object* Runtime_LookupContext(Arguments args) { +static MaybeObject* Runtime_LookupContext(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); @@ -6487,11 +6685,11 @@ static Object* Runtime_LookupContext(Arguments args) { // allocated by the caller, and passed as a pointer in a hidden first parameter. #ifdef V8_HOST_ARCH_64_BIT struct ObjectPair { - Object* x; - Object* y; + MaybeObject* x; + MaybeObject* y; }; -static inline ObjectPair MakePair(Object* x, Object* y) { +static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) { ObjectPair result = {x, y}; // Pointers x and y returned in rax and rdx, in AMD-x64-abi. // In Win64 they are assigned to a hidden first argument. @@ -6499,14 +6697,15 @@ static inline ObjectPair MakePair(Object* x, Object* y) { } #else typedef uint64_t ObjectPair; -static inline ObjectPair MakePair(Object* x, Object* y) { +static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) { return reinterpret_cast<uint32_t>(x) | (reinterpret_cast<ObjectPair>(y) << 32); } #endif -static inline Object* Unhole(Object* x, PropertyAttributes attributes) { +static inline MaybeObject* Unhole(MaybeObject* x, + PropertyAttributes attributes) { ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0); USE(attributes); return x->IsTheHole() ? Heap::undefined_value() : x; @@ -6556,7 +6755,7 @@ static ObjectPair LoadContextSlotHelper(Arguments args, bool throw_error) { // argument in a context, the receiver is the global object; see // ECMA-262, 3rd., 10.1.6 and 10.2.3. JSObject* receiver = Top::context()->global()->global_receiver(); - Object* value = (holder->IsContext()) + MaybeObject* value = (holder->IsContext()) ? Context::cast(*holder)->get(index) : JSObject::cast(*holder)->GetElement(index); return MakePair(Unhole(value, attributes), receiver); @@ -6576,7 +6775,7 @@ static ObjectPair LoadContextSlotHelper(Arguments args, bool throw_error) { } // No need to unhole the value here. This is taken care of by the // GetProperty function. - Object* value = object->GetProperty(*name); + MaybeObject* value = object->GetProperty(*name); return MakePair(value, receiver); } @@ -6602,7 +6801,7 @@ static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) { } -static Object* Runtime_StoreContextSlot(Arguments args) { +static MaybeObject* Runtime_StoreContextSlot(Arguments args) { HandleScope scope; ASSERT(args.length() == 3); @@ -6624,10 +6823,8 @@ static Object* Runtime_StoreContextSlot(Arguments args) { } } else { ASSERT((attributes & READ_ONLY) == 0); - Object* result = - Handle<JSObject>::cast(holder)->SetElement(index, *value); - USE(result); - ASSERT(!result->IsFailure()); + Handle<JSObject>::cast(holder)->SetElement(index, *value)-> + ToObjectUnchecked(); } return *value; } @@ -6663,7 +6860,7 @@ static Object* Runtime_StoreContextSlot(Arguments args) { } -static Object* Runtime_Throw(Arguments args) { +static MaybeObject* Runtime_Throw(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -6671,7 +6868,7 @@ static Object* Runtime_Throw(Arguments args) { } -static Object* Runtime_ReThrow(Arguments args) { +static MaybeObject* Runtime_ReThrow(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -6679,13 +6876,13 @@ static Object* Runtime_ReThrow(Arguments args) { } -static Object* Runtime_PromoteScheduledException(Arguments args) { +static MaybeObject* Runtime_PromoteScheduledException(Arguments args) { ASSERT_EQ(0, args.length()); return Top::PromoteScheduledException(); } -static Object* Runtime_ThrowReferenceError(Arguments args) { +static MaybeObject* Runtime_ThrowReferenceError(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -6696,13 +6893,13 @@ static Object* Runtime_ThrowReferenceError(Arguments args) { } -static Object* Runtime_StackOverflow(Arguments args) { +static MaybeObject* Runtime_StackOverflow(Arguments args) { NoHandleAllocation na; return Top::StackOverflow(); } -static Object* Runtime_StackGuard(Arguments args) { +static MaybeObject* Runtime_StackGuard(Arguments args) { ASSERT(args.length() == 0); // First check if this is a real stack overflow. @@ -6800,7 +6997,7 @@ static void PrintTransition(Object* result) { } -static Object* Runtime_TraceEnter(Arguments args) { +static MaybeObject* Runtime_TraceEnter(Arguments args) { ASSERT(args.length() == 0); NoHandleAllocation ha; PrintTransition(NULL); @@ -6808,14 +7005,14 @@ static Object* Runtime_TraceEnter(Arguments args) { } -static Object* Runtime_TraceExit(Arguments args) { +static MaybeObject* Runtime_TraceExit(Arguments args) { NoHandleAllocation ha; PrintTransition(args[0]); return args[0]; // return TOS } -static Object* Runtime_DebugPrint(Arguments args) { +static MaybeObject* Runtime_DebugPrint(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -6846,7 +7043,7 @@ static Object* Runtime_DebugPrint(Arguments args) { } -static Object* Runtime_DebugTrace(Arguments args) { +static MaybeObject* Runtime_DebugTrace(Arguments args) { ASSERT(args.length() == 0); NoHandleAllocation ha; Top::PrintStack(); @@ -6854,7 +7051,7 @@ static Object* Runtime_DebugTrace(Arguments args) { } -static Object* Runtime_DateCurrentTime(Arguments args) { +static MaybeObject* Runtime_DateCurrentTime(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 0); @@ -6867,7 +7064,7 @@ static Object* Runtime_DateCurrentTime(Arguments args) { } -static Object* Runtime_DateParseString(Arguments args) { +static MaybeObject* Runtime_DateParseString(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); @@ -6897,7 +7094,7 @@ static Object* Runtime_DateParseString(Arguments args) { } -static Object* Runtime_DateLocalTimezone(Arguments args) { +static MaybeObject* Runtime_DateLocalTimezone(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -6907,7 +7104,7 @@ static Object* Runtime_DateLocalTimezone(Arguments args) { } -static Object* Runtime_DateLocalTimeOffset(Arguments args) { +static MaybeObject* Runtime_DateLocalTimeOffset(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 0); @@ -6915,7 +7112,7 @@ static Object* Runtime_DateLocalTimeOffset(Arguments args) { } -static Object* Runtime_DateDaylightSavingsOffset(Arguments args) { +static MaybeObject* Runtime_DateDaylightSavingsOffset(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -6924,7 +7121,7 @@ static Object* Runtime_DateDaylightSavingsOffset(Arguments args) { } -static Object* Runtime_GlobalReceiver(Arguments args) { +static MaybeObject* Runtime_GlobalReceiver(Arguments args) { ASSERT(args.length() == 1); Object* global = args[0]; if (!global->IsJSGlobalObject()) return Heap::null_value(); @@ -6932,7 +7129,7 @@ static Object* Runtime_GlobalReceiver(Arguments args) { } -static Object* Runtime_CompileString(Arguments args) { +static MaybeObject* Runtime_CompileString(Arguments args) { HandleScope scope; ASSERT_EQ(2, args.length()); CONVERT_ARG_CHECKED(String, source, 0); @@ -7060,7 +7257,7 @@ static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(Arguments args) { } -static Object* Runtime_SetNewFunctionAttributes(Arguments args) { +static MaybeObject* Runtime_SetNewFunctionAttributes(Arguments args) { // This utility adjusts the property attributes for newly created Function // object ("new Function(...)") by changing the map. // All it does is changing the prototype property to enumerable @@ -7077,7 +7274,7 @@ static Object* Runtime_SetNewFunctionAttributes(Arguments args) { } -static Object* Runtime_AllocateInNewSpace(Arguments args) { +static MaybeObject* Runtime_AllocateInNewSpace(Arguments args) { // Allocate a block of memory in NewSpace (filled with a filler). // Use as fallback for allocation in generated code when NewSpace // is full. @@ -7089,18 +7286,20 @@ static Object* Runtime_AllocateInNewSpace(Arguments args) { static const int kMinFreeNewSpaceAfterGC = Heap::InitialSemiSpaceSize() * 3/4; RUNTIME_ASSERT(size <= kMinFreeNewSpaceAfterGC); - Object* allocation = Heap::new_space()->AllocateRaw(size); - if (!allocation->IsFailure()) { - Heap::CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size); + Object* allocation; + { MaybeObject* maybe_allocation = Heap::new_space()->AllocateRaw(size); + if (maybe_allocation->ToObject(&allocation)) { + Heap::CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size); + } + return maybe_allocation; } - return allocation; } // Push an array unto an array of arrays if it is not already in the // array. Returns true if the element was pushed on the stack and // false otherwise. -static Object* Runtime_PushIfAbsent(Arguments args) { +static MaybeObject* Runtime_PushIfAbsent(Arguments args) { ASSERT(args.length() == 2); CONVERT_CHECKED(JSArray, array, args[0]); CONVERT_CHECKED(JSArray, element, args[1]); @@ -7110,8 +7309,10 @@ static Object* Runtime_PushIfAbsent(Arguments args) { for (int i = 0; i < length; i++) { if (elements->get(i) == element) return Heap::false_value(); } - Object* obj = array->SetFastElement(length, element); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = array->SetFastElement(length, element); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } return Heap::true_value(); } @@ -7405,30 +7606,36 @@ static uint32_t IterateArguments(Handle<JSArray> arguments, uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number()); for (uint32_t i = 0; i < num_of_args; i++) { - Handle<Object> obj(arguments->GetElement(i)); - if (obj->IsJSArray()) { - Handle<JSArray> array = Handle<JSArray>::cast(obj); - uint32_t len = static_cast<uint32_t>(array->length()->Number()); - uint32_t nof_elements = - IterateArrayAndPrototypeElements(array, visitor); - // Total elements of array and its prototype chain can be more than - // the array length, but ArrayConcat can only concatenate at most - // the array length number of elements. We use the length as an estimate - // for the actual number of elements added. - uint32_t added_elements = (nof_elements > len) ? len : nof_elements; - if (JSArray::kMaxElementCount - visited_elements < added_elements) { - visited_elements = JSArray::kMaxElementCount; + Object *element; + MaybeObject* maybe_element = arguments->GetElement(i); + // This if() is not expected to fail, but we have the check in the + // interest of hardening the runtime calls. + if (maybe_element->ToObject(&element)) { + Handle<Object> obj(element); + if (obj->IsJSArray()) { + Handle<JSArray> array = Handle<JSArray>::cast(obj); + uint32_t len = static_cast<uint32_t>(array->length()->Number()); + uint32_t nof_elements = + IterateArrayAndPrototypeElements(array, visitor); + // Total elements of array and its prototype chain can be more than + // the array length, but ArrayConcat can only concatenate at most + // the array length number of elements. We use the length as an estimate + // for the actual number of elements added. + uint32_t added_elements = (nof_elements > len) ? len : nof_elements; + if (JSArray::kMaxElementCount - visited_elements < added_elements) { + visited_elements = JSArray::kMaxElementCount; + } else { + visited_elements += added_elements; + } + if (visitor) visitor->increase_index_offset(len); } else { - visited_elements += added_elements; - } - if (visitor) visitor->increase_index_offset(len); - } else { - if (visitor) { - visitor->visit(0, obj); - visitor->increase_index_offset(1); - } - if (visited_elements < JSArray::kMaxElementCount) { - visited_elements++; + if (visitor) { + visitor->visit(0, obj); + visitor->increase_index_offset(1); + } + if (visited_elements < JSArray::kMaxElementCount) { + visited_elements++; + } } } } @@ -7442,7 +7649,7 @@ static uint32_t IterateArguments(Handle<JSArray> arguments, * TODO(lrn): Fix non-compliance for very large concatenations and update to * following the ECMAScript 5 specification. */ -static Object* Runtime_ArrayConcat(Arguments args) { +static MaybeObject* Runtime_ArrayConcat(Arguments args) { ASSERT(args.length() == 1); HandleScope handle_scope; @@ -7456,19 +7663,24 @@ static Object* Runtime_ArrayConcat(Arguments args) { { AssertNoAllocation nogc; for (uint32_t i = 0; i < num_of_args; i++) { - Object* obj = arguments->GetElement(i); - uint32_t length_estimate; - if (obj->IsJSArray()) { - length_estimate = - static_cast<uint32_t>(JSArray::cast(obj)->length()->Number()); - } else { - length_estimate = 1; - } - if (JSObject::kMaxElementCount - result_length < length_estimate) { - result_length = JSObject::kMaxElementCount; - break; + Object* obj; + MaybeObject* maybe_object = arguments->GetElement(i); + // This if() is not expected to fail, but we have the check in the + // interest of hardening the runtime calls. + if (maybe_object->ToObject(&obj)) { + uint32_t length_estimate; + if (obj->IsJSArray()) { + length_estimate = + static_cast<uint32_t>(JSArray::cast(obj)->length()->Number()); + } else { + length_estimate = 1; + } + if (JSObject::kMaxElementCount - result_length < length_estimate) { + result_length = JSObject::kMaxElementCount; + break; + } + result_length += length_estimate; } - result_length += length_estimate; } } @@ -7516,7 +7728,7 @@ static Object* Runtime_ArrayConcat(Arguments args) { // This will not allocate (flatten the string), but it may run // very slowly for very deeply nested ConsStrings. For debugging use only. -static Object* Runtime_GlobalPrint(Arguments args) { +static MaybeObject* Runtime_GlobalPrint(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -7534,7 +7746,7 @@ static Object* Runtime_GlobalPrint(Arguments args) { // and are followed by non-existing element. Does not change the length // property. // Returns the number of non-undefined elements collected. -static Object* Runtime_RemoveArrayHoles(Arguments args) { +static MaybeObject* Runtime_RemoveArrayHoles(Arguments args) { ASSERT(args.length() == 2); CONVERT_CHECKED(JSObject, object, args[0]); CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]); @@ -7543,31 +7755,34 @@ static Object* Runtime_RemoveArrayHoles(Arguments args) { // Move contents of argument 0 (an array) to argument 1 (an array) -static Object* Runtime_MoveArrayContents(Arguments args) { +static MaybeObject* Runtime_MoveArrayContents(Arguments args) { ASSERT(args.length() == 2); CONVERT_CHECKED(JSArray, from, args[0]); CONVERT_CHECKED(JSArray, to, args[1]); HeapObject* new_elements = from->elements(); - Object* new_map; + MaybeObject* maybe_new_map; if (new_elements->map() == Heap::fixed_array_map() || new_elements->map() == Heap::fixed_cow_array_map()) { - new_map = to->map()->GetFastElementsMap(); + maybe_new_map = to->map()->GetFastElementsMap(); } else { - new_map = to->map()->GetSlowElementsMap(); + maybe_new_map = to->map()->GetSlowElementsMap(); } - if (new_map->IsFailure()) return new_map; + Object* new_map; + if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; to->set_map(Map::cast(new_map)); to->set_elements(new_elements); to->set_length(from->length()); - Object* obj = from->ResetElements(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = from->ResetElements(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } from->set_length(Smi::FromInt(0)); return to; } // How many elements does this object/array have? -static Object* Runtime_EstimateNumberOfElements(Arguments args) { +static MaybeObject* Runtime_EstimateNumberOfElements(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(JSObject, object, args[0]); HeapObject* elements = object->elements(); @@ -7581,7 +7796,7 @@ static Object* Runtime_EstimateNumberOfElements(Arguments args) { } -static Object* Runtime_SwapElements(Arguments args) { +static MaybeObject* Runtime_SwapElements(Arguments args) { HandleScope handle_scope; ASSERT_EQ(3, args.length()); @@ -7612,7 +7827,7 @@ static Object* Runtime_SwapElements(Arguments args) { // intervals (pair of a negative integer (-start-1) followed by a // positive (length)) or undefined values. // Intervals can span over some keys that are not in the object. -static Object* Runtime_GetArrayKeys(Arguments args) { +static MaybeObject* Runtime_GetArrayKeys(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; CONVERT_ARG_CHECKED(JSObject, array, 0); @@ -7652,7 +7867,7 @@ static Object* Runtime_GetArrayKeys(Arguments args) { // to the way accessors are implemented, it is set for both the getter // and setter on the first call to DefineAccessor and ignored on // subsequent calls. -static Object* Runtime_DefineAccessor(Arguments args) { +static MaybeObject* Runtime_DefineAccessor(Arguments args) { RUNTIME_ASSERT(args.length() == 4 || args.length() == 5); // Compute attributes. PropertyAttributes attributes = NONE; @@ -7672,7 +7887,7 @@ static Object* Runtime_DefineAccessor(Arguments args) { } -static Object* Runtime_LookupAccessor(Arguments args) { +static MaybeObject* Runtime_LookupAccessor(Arguments args) { ASSERT(args.length() == 3); CONVERT_CHECKED(JSObject, obj, args[0]); CONVERT_CHECKED(String, name, args[1]); @@ -7682,7 +7897,7 @@ static Object* Runtime_LookupAccessor(Arguments args) { #ifdef ENABLE_DEBUGGER_SUPPORT -static Object* Runtime_DebugBreak(Arguments args) { +static MaybeObject* Runtime_DebugBreak(Arguments args) { ASSERT(args.length() == 0); return Execution::DebugBreakHelper(); } @@ -7704,7 +7919,7 @@ static StackFrame::Id UnwrapFrameId(Smi* wrapped) { // args[0]: debug event listener function to set or null or undefined for // clearing the event listener function // args[1]: object supplied during callback -static Object* Runtime_SetDebugEventListener(Arguments args) { +static MaybeObject* Runtime_SetDebugEventListener(Arguments args) { ASSERT(args.length() == 2); RUNTIME_ASSERT(args[0]->IsJSFunction() || args[0]->IsUndefined() || @@ -7717,16 +7932,16 @@ static Object* Runtime_SetDebugEventListener(Arguments args) { } -static Object* Runtime_Break(Arguments args) { +static MaybeObject* Runtime_Break(Arguments args) { ASSERT(args.length() == 0); StackGuard::DebugBreak(); return Heap::undefined_value(); } -static Object* DebugLookupResultValue(Object* receiver, String* name, - LookupResult* result, - bool* caught_exception) { +static MaybeObject* DebugLookupResultValue(Object* receiver, String* name, + LookupResult* result, + bool* caught_exception) { Object* value; switch (result->type()) { case NORMAL: @@ -7748,14 +7963,16 @@ static Object* DebugLookupResultValue(Object* receiver, String* name, case CALLBACKS: { Object* structure = result->GetCallbackObject(); if (structure->IsProxy() || structure->IsAccessorInfo()) { - value = receiver->GetPropertyWithCallback( + MaybeObject* maybe_value = receiver->GetPropertyWithCallback( receiver, structure, name, result->holder()); - if (value->IsException()) { - value = Top::pending_exception(); + if (!maybe_value->ToObject(&value)) { + ASSERT(maybe_value->IsException()); + maybe_value = Top::pending_exception(); Top::clear_pending_exception(); if (caught_exception != NULL) { *caught_exception = true; } + return maybe_value; } return value; } else { @@ -7787,7 +8004,7 @@ static Object* DebugLookupResultValue(Object* receiver, String* name, // 4: Setter function if defined // Items 2-4 are only filled if the property has either a getter or a setter // defined through __defineGetter__ and/or __defineSetter__. -static Object* Runtime_DebugGetPropertyDetails(Arguments args) { +static MaybeObject* Runtime_DebugGetPropertyDetails(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); @@ -7818,7 +8035,13 @@ static Object* Runtime_DebugGetPropertyDetails(Arguments args) { uint32_t index; if (name->AsArrayIndex(&index)) { Handle<FixedArray> details = Factory::NewFixedArray(2); - Object* element_or_char = Runtime::GetElementOrCharAt(obj, index); + Object* element_or_char; + { MaybeObject* maybe_element_or_char = + Runtime::GetElementOrCharAt(obj, index); + if (!maybe_element_or_char->ToObject(&element_or_char)) { + return maybe_element_or_char; + } + } details->set(0, element_or_char); details->set(1, PropertyDetails(NONE, NORMAL).AsSmi()); return *Factory::NewJSArrayWithElements(details); @@ -7845,9 +8068,11 @@ static Object* Runtime_DebugGetPropertyDetails(Arguments args) { // DebugLookupResultValue can cause GC so details from LookupResult needs // to be copied to handles before this. bool caught_exception = false; - Object* raw_value = DebugLookupResultValue(*obj, *name, &result, - &caught_exception); - if (raw_value->IsFailure()) return raw_value; + Object* raw_value; + { MaybeObject* maybe_raw_value = + DebugLookupResultValue(*obj, *name, &result, &caught_exception); + if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value; + } Handle<Object> value(raw_value); // If the callback object is a fixed array then it contains JavaScript @@ -7877,7 +8102,7 @@ static Object* Runtime_DebugGetPropertyDetails(Arguments args) { } -static Object* Runtime_DebugGetProperty(Arguments args) { +static MaybeObject* Runtime_DebugGetProperty(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); @@ -7896,7 +8121,7 @@ static Object* Runtime_DebugGetProperty(Arguments args) { // Return the property type calculated from the property details. // args[0]: smi with property details. -static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) { +static MaybeObject* Runtime_DebugPropertyTypeFromDetails(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(Smi, details, args[0]); PropertyType type = PropertyDetails(details).type(); @@ -7906,7 +8131,7 @@ static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) { // Return the property attribute calculated from the property details. // args[0]: smi with property details. -static Object* Runtime_DebugPropertyAttributesFromDetails(Arguments args) { +static MaybeObject* Runtime_DebugPropertyAttributesFromDetails(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(Smi, details, args[0]); PropertyAttributes attributes = PropertyDetails(details).attributes(); @@ -7916,7 +8141,7 @@ static Object* Runtime_DebugPropertyAttributesFromDetails(Arguments args) { // Return the property insertion index calculated from the property details. // args[0]: smi with property details. -static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) { +static MaybeObject* Runtime_DebugPropertyIndexFromDetails(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(Smi, details, args[0]); int index = PropertyDetails(details).index(); @@ -7927,7 +8152,7 @@ static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) { // Return property value from named interceptor. // args[0]: object // args[1]: property name -static Object* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) { +static MaybeObject* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); CONVERT_ARG_CHECKED(JSObject, obj, 0); @@ -7942,7 +8167,8 @@ static Object* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) { // Return element value from indexed interceptor. // args[0]: object // args[1]: index -static Object* Runtime_DebugIndexedInterceptorElementValue(Arguments args) { +static MaybeObject* Runtime_DebugIndexedInterceptorElementValue( + Arguments args) { HandleScope scope; ASSERT(args.length() == 2); CONVERT_ARG_CHECKED(JSObject, obj, 0); @@ -7953,7 +8179,7 @@ static Object* Runtime_DebugIndexedInterceptorElementValue(Arguments args) { } -static Object* Runtime_CheckExecutionState(Arguments args) { +static MaybeObject* Runtime_CheckExecutionState(Arguments args) { ASSERT(args.length() >= 1); CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]); // Check that the break id is valid. @@ -7965,13 +8191,15 @@ static Object* Runtime_CheckExecutionState(Arguments args) { } -static Object* Runtime_GetFrameCount(Arguments args) { +static MaybeObject* Runtime_GetFrameCount(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); // Check arguments. - Object* result = Runtime_CheckExecutionState(args); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Runtime_CheckExecutionState(args); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Count all frames which are relevant to debugging stack trace. int n = 0; @@ -8013,13 +8241,15 @@ static const int kFrameDetailsFirstDynamicIndex = 9; // Arguments name, value // Locals name, value // Return value if any -static Object* Runtime_GetFrameDetails(Arguments args) { +static MaybeObject* Runtime_GetFrameDetails(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); // Check arguments. - Object* check = Runtime_CheckExecutionState(args); - if (check->IsFailure()) return check; + Object* check; + { MaybeObject* maybe_check = Runtime_CheckExecutionState(args); + if (!maybe_check->ToObject(&check)) return maybe_check; + } CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); // Find the relevant frame with the requested index. @@ -8320,9 +8550,12 @@ static Handle<JSObject> MaterializeClosure(Handle<Context> context) { Handle<JSObject> arguments_shadow( JSObject::cast(context->get(arguments_shadow_index))); for (int i = 0; i < scope_info.number_of_parameters(); ++i) { + // We don't expect exception-throwing getters on the arguments shadow. + Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked(); SetProperty(closure_scope, scope_info.parameter_name(i), - Handle<Object>(arguments_shadow->GetElement(i)), NONE); + Handle<Object>(element), + NONE); } } @@ -8554,13 +8787,15 @@ class ScopeIterator { }; -static Object* Runtime_GetScopeCount(Arguments args) { +static MaybeObject* Runtime_GetScopeCount(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); // Check arguments. - Object* check = Runtime_CheckExecutionState(args); - if (check->IsFailure()) return check; + Object* check; + { MaybeObject* maybe_check = Runtime_CheckExecutionState(args); + if (!maybe_check->ToObject(&check)) return maybe_check; + } CONVERT_CHECKED(Smi, wrapped_id, args[1]); // Get the frame where the debugging is performed. @@ -8590,13 +8825,15 @@ static const int kScopeDetailsSize = 2; // The array returned contains the following information: // 0: Scope type // 1: Scope object -static Object* Runtime_GetScopeDetails(Arguments args) { +static MaybeObject* Runtime_GetScopeDetails(Arguments args) { HandleScope scope; ASSERT(args.length() == 3); // Check arguments. - Object* check = Runtime_CheckExecutionState(args); - if (check->IsFailure()) return check; + Object* check; + { MaybeObject* maybe_check = Runtime_CheckExecutionState(args); + if (!maybe_check->ToObject(&check)) return maybe_check; + } CONVERT_CHECKED(Smi, wrapped_id, args[1]); CONVERT_NUMBER_CHECKED(int, index, Int32, args[2]); @@ -8628,7 +8865,7 @@ static Object* Runtime_GetScopeDetails(Arguments args) { } -static Object* Runtime_DebugPrintScopes(Arguments args) { +static MaybeObject* Runtime_DebugPrintScopes(Arguments args) { HandleScope scope; ASSERT(args.length() == 0); @@ -8644,60 +8881,21 @@ static Object* Runtime_DebugPrintScopes(Arguments args) { } -static Object* Runtime_GetCFrames(Arguments args) { - HandleScope scope; - ASSERT(args.length() == 1); - Object* result = Runtime_CheckExecutionState(args); - if (result->IsFailure()) return result; - -#if V8_HOST_ARCH_64_BIT - UNIMPLEMENTED(); +static MaybeObject* Runtime_GetCFrames(Arguments args) { + // See bug 906. return Heap::undefined_value(); -#else - - static const int kMaxCFramesSize = 200; - ScopedVector<OS::StackFrame> frames(kMaxCFramesSize); - int frames_count = OS::StackWalk(frames); - if (frames_count == OS::kStackWalkError) { - return Heap::undefined_value(); - } - - Handle<String> address_str = Factory::LookupAsciiSymbol("address"); - Handle<String> text_str = Factory::LookupAsciiSymbol("text"); - Handle<FixedArray> frames_array = Factory::NewFixedArray(frames_count); - for (int i = 0; i < frames_count; i++) { - Handle<JSObject> frame_value = Factory::NewJSObject(Top::object_function()); - Handle<Object> frame_address = - Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address)); - - frame_value->SetProperty(*address_str, *frame_address, NONE); - - // Get the stack walk text for this frame. - Handle<String> frame_text; - int frame_text_length = StrLength(frames[i].text); - if (frame_text_length > 0) { - Vector<const char> str(frames[i].text, frame_text_length); - frame_text = Factory::NewStringFromAscii(str); - } - - if (!frame_text.is_null()) { - frame_value->SetProperty(*text_str, *frame_text, NONE); - } - - frames_array->set(i, *frame_value); - } - return *Factory::NewJSArrayWithElements(frames_array); -#endif // V8_HOST_ARCH_64_BIT } -static Object* Runtime_GetThreadCount(Arguments args) { +static MaybeObject* Runtime_GetThreadCount(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); // Check arguments. - Object* result = Runtime_CheckExecutionState(args); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = Runtime_CheckExecutionState(args); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // Count all archived V8 threads. int n = 0; @@ -8723,13 +8921,15 @@ static const int kThreadDetailsSize = 2; // The array returned contains the following information: // 0: Is current thread? // 1: Thread id -static Object* Runtime_GetThreadDetails(Arguments args) { +static MaybeObject* Runtime_GetThreadDetails(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); // Check arguments. - Object* check = Runtime_CheckExecutionState(args); - if (check->IsFailure()) return check; + Object* check; + { MaybeObject* maybe_check = Runtime_CheckExecutionState(args); + if (!maybe_check->ToObject(&check)) return maybe_check; + } CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]); // Allocate array for result. @@ -8765,7 +8965,7 @@ static Object* Runtime_GetThreadDetails(Arguments args) { // Sets the disable break state // args[0]: disable break state -static Object* Runtime_SetDisableBreak(Arguments args) { +static MaybeObject* Runtime_SetDisableBreak(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); CONVERT_BOOLEAN_CHECKED(disable_break, args[0]); @@ -8774,7 +8974,7 @@ static Object* Runtime_SetDisableBreak(Arguments args) { } -static Object* Runtime_GetBreakLocations(Arguments args) { +static MaybeObject* Runtime_GetBreakLocations(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -8793,7 +8993,7 @@ static Object* Runtime_GetBreakLocations(Arguments args) { // args[0]: function // args[1]: number: break source position (within the function source) // args[2]: number: break point object -static Object* Runtime_SetFunctionBreakPoint(Arguments args) { +static MaybeObject* Runtime_SetFunctionBreakPoint(Arguments args) { HandleScope scope; ASSERT(args.length() == 3); CONVERT_ARG_CHECKED(JSFunction, fun, 0); @@ -8892,7 +9092,7 @@ Object* Runtime::FindSharedFunctionInfoInScript(Handle<Script> script, // args[0]: script to set break point in // args[1]: number: break source position (within the script source) // args[2]: number: break point object -static Object* Runtime_SetScriptBreakPoint(Arguments args) { +static MaybeObject* Runtime_SetScriptBreakPoint(Arguments args) { HandleScope scope; ASSERT(args.length() == 3); CONVERT_ARG_CHECKED(JSValue, wrapper, 0); @@ -8926,7 +9126,7 @@ static Object* Runtime_SetScriptBreakPoint(Arguments args) { // Clear a break point // args[0]: number: break point object -static Object* Runtime_ClearBreakPoint(Arguments args) { +static MaybeObject* Runtime_ClearBreakPoint(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); Handle<Object> break_point_object_arg = args.at<Object>(0); @@ -8941,7 +9141,7 @@ static Object* Runtime_ClearBreakPoint(Arguments args) { // Change the state of break on exceptions. // args[0]: Enum value indicating whether to affect caught/uncaught exceptions. // args[1]: Boolean indicating on/off. -static Object* Runtime_ChangeBreakOnException(Arguments args) { +static MaybeObject* Runtime_ChangeBreakOnException(Arguments args) { HandleScope scope; ASSERT(args.length() == 2); RUNTIME_ASSERT(args[0]->IsNumber()); @@ -8959,7 +9159,7 @@ static Object* Runtime_ChangeBreakOnException(Arguments args) { // Returns the state of break on exceptions // args[0]: boolean indicating uncaught exceptions -static Object* Runtime_IsBreakOnException(Arguments args) { +static MaybeObject* Runtime_IsBreakOnException(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); RUNTIME_ASSERT(args[0]->IsNumber()); @@ -8976,12 +9176,14 @@ static Object* Runtime_IsBreakOnException(Arguments args) { // args[1]: step action from the enumeration StepAction // args[2]: number of times to perform the step, for step out it is the number // of frames to step down. -static Object* Runtime_PrepareStep(Arguments args) { +static MaybeObject* Runtime_PrepareStep(Arguments args) { HandleScope scope; ASSERT(args.length() == 3); // Check arguments. - Object* check = Runtime_CheckExecutionState(args); - if (check->IsFailure()) return check; + Object* check; + { MaybeObject* maybe_check = Runtime_CheckExecutionState(args); + if (!maybe_check->ToObject(&check)) return maybe_check; + } if (!args[1]->IsNumber() || !args[2]->IsNumber()) { return Top::Throw(Heap::illegal_argument_symbol()); } @@ -9012,7 +9214,7 @@ static Object* Runtime_PrepareStep(Arguments args) { // Clear all stepping set by PrepareStep. -static Object* Runtime_ClearStepping(Arguments args) { +static MaybeObject* Runtime_ClearStepping(Arguments args) { HandleScope scope; ASSERT(args.length() == 0); Debug::ClearStepping(); @@ -9089,14 +9291,18 @@ static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame, // stack frame presenting the same view of the values of parameters and // local variables as if the piece of JavaScript was evaluated at the point // where the function on the stack frame is currently stopped. -static Object* Runtime_DebugEvaluate(Arguments args) { +static MaybeObject* Runtime_DebugEvaluate(Arguments args) { HandleScope scope; // Check the execution state and decode arguments frame and source to be // evaluated. ASSERT(args.length() == 4); - Object* check_result = Runtime_CheckExecutionState(args); - if (check_result->IsFailure()) return check_result; + Object* check_result; + { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args); + if (!maybe_check_result->ToObject(&check_result)) { + return maybe_check_result; + } + } CONVERT_CHECKED(Smi, wrapped_id, args[1]); CONVERT_ARG_CHECKED(String, source, 2); CONVERT_BOOLEAN_CHECKED(disable_break, args[3]); @@ -9200,14 +9406,18 @@ static Object* Runtime_DebugEvaluate(Arguments args) { } -static Object* Runtime_DebugEvaluateGlobal(Arguments args) { +static MaybeObject* Runtime_DebugEvaluateGlobal(Arguments args) { HandleScope scope; // Check the execution state and decode arguments frame and source to be // evaluated. ASSERT(args.length() == 3); - Object* check_result = Runtime_CheckExecutionState(args); - if (check_result->IsFailure()) return check_result; + Object* check_result; + { MaybeObject* maybe_check_result = Runtime_CheckExecutionState(args); + if (!maybe_check_result->ToObject(&check_result)) { + return maybe_check_result; + } + } CONVERT_ARG_CHECKED(String, source, 1); CONVERT_BOOLEAN_CHECKED(disable_break, args[2]); @@ -9250,7 +9460,7 @@ static Object* Runtime_DebugEvaluateGlobal(Arguments args) { } -static Object* Runtime_DebugGetLoadedScripts(Arguments args) { +static MaybeObject* Runtime_DebugGetLoadedScripts(Arguments args) { HandleScope scope; ASSERT(args.length() == 0); @@ -9350,7 +9560,7 @@ static int DebugReferencedBy(JSObject* target, // args[0]: the object to find references to // args[1]: constructor function for instances to exclude (Mirror) // args[2]: the the maximum number of objects to return -static Object* Runtime_DebugReferencedBy(Arguments args) { +static MaybeObject* Runtime_DebugReferencedBy(Arguments args) { ASSERT(args.length() == 3); // First perform a full GC in order to avoid references from dead objects. @@ -9376,8 +9586,10 @@ static Object* Runtime_DebugReferencedBy(Arguments args) { NULL, 0, arguments_function); // Allocate an array to hold the result. - Object* object = Heap::AllocateFixedArray(count); - if (object->IsFailure()) return object; + Object* object; + { MaybeObject* maybe_object = Heap::AllocateFixedArray(count); + if (!maybe_object->ToObject(&object)) return maybe_object; + } FixedArray* instances = FixedArray::cast(object); // Fill the referencing objects. @@ -9385,10 +9597,12 @@ static Object* Runtime_DebugReferencedBy(Arguments args) { instances, count, arguments_function); // Return result as JS array. - Object* result = - Heap::AllocateJSObject( - Top::context()->global_context()->array_function()); - if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances); + Object* result; + { MaybeObject* maybe_result = Heap::AllocateJSObject( + Top::context()->global_context()->array_function()); + if (!maybe_result->ToObject(&result)) return maybe_result; + } + JSArray::cast(result)->SetContent(instances); return result; } @@ -9426,7 +9640,7 @@ static int DebugConstructedBy(JSFunction* constructor, int max_references, // Scan the heap for objects constructed by a specific function. // args[0]: the constructor to find instances of // args[1]: the the maximum number of objects to return -static Object* Runtime_DebugConstructedBy(Arguments args) { +static MaybeObject* Runtime_DebugConstructedBy(Arguments args) { ASSERT(args.length() == 2); // First perform a full GC in order to avoid dead objects. @@ -9442,25 +9656,29 @@ static Object* Runtime_DebugConstructedBy(Arguments args) { count = DebugConstructedBy(constructor, max_references, NULL, 0); // Allocate an array to hold the result. - Object* object = Heap::AllocateFixedArray(count); - if (object->IsFailure()) return object; + Object* object; + { MaybeObject* maybe_object = Heap::AllocateFixedArray(count); + if (!maybe_object->ToObject(&object)) return maybe_object; + } FixedArray* instances = FixedArray::cast(object); // Fill the referencing objects. count = DebugConstructedBy(constructor, max_references, instances, count); // Return result as JS array. - Object* result = - Heap::AllocateJSObject( - Top::context()->global_context()->array_function()); - if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances); + Object* result; + { MaybeObject* maybe_result = Heap::AllocateJSObject( + Top::context()->global_context()->array_function()); + if (!maybe_result->ToObject(&result)) return maybe_result; + } + JSArray::cast(result)->SetContent(instances); return result; } // Find the effective prototype object as returned by __proto__. // args[0]: the object to find the prototype for. -static Object* Runtime_DebugGetPrototype(Arguments args) { +static MaybeObject* Runtime_DebugGetPrototype(Arguments args) { ASSERT(args.length() == 1); CONVERT_CHECKED(JSObject, obj, args[0]); @@ -9470,14 +9688,14 @@ static Object* Runtime_DebugGetPrototype(Arguments args) { } -static Object* Runtime_SystemBreak(Arguments args) { +static MaybeObject* Runtime_SystemBreak(Arguments args) { ASSERT(args.length() == 0); CPU::DebugBreak(); return Heap::undefined_value(); } -static Object* Runtime_DebugDisassembleFunction(Arguments args) { +static MaybeObject* Runtime_DebugDisassembleFunction(Arguments args) { #ifdef DEBUG HandleScope scope; ASSERT(args.length() == 1); @@ -9493,7 +9711,7 @@ static Object* Runtime_DebugDisassembleFunction(Arguments args) { } -static Object* Runtime_DebugDisassembleConstructor(Arguments args) { +static MaybeObject* Runtime_DebugDisassembleConstructor(Arguments args) { #ifdef DEBUG HandleScope scope; ASSERT(args.length() == 1); @@ -9509,7 +9727,7 @@ static Object* Runtime_DebugDisassembleConstructor(Arguments args) { } -static Object* Runtime_FunctionGetInferredName(Arguments args) { +static MaybeObject* Runtime_FunctionGetInferredName(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 1); @@ -9545,7 +9763,7 @@ static int FindSharedFunctionInfosForScript(Script* script, // For a script finds all SharedFunctionInfo's in the heap that points // to this script. Returns JSArray of SharedFunctionInfo wrapped // in OpaqueReferences. -static Object* Runtime_LiveEditFindSharedFunctionInfosForScript( +static MaybeObject* Runtime_LiveEditFindSharedFunctionInfosForScript( Arguments args) { ASSERT(args.length() == 1); HandleScope scope; @@ -9578,7 +9796,7 @@ static Object* Runtime_LiveEditFindSharedFunctionInfosForScript( // Returns a JSArray of compilation infos. The array is ordered so that // each function with all its descendant is always stored in a continues range // with the function itself going first. The root function is a script function. -static Object* Runtime_LiveEditGatherCompileInfo(Arguments args) { +static MaybeObject* Runtime_LiveEditGatherCompileInfo(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; CONVERT_CHECKED(JSValue, script, args[0]); @@ -9597,7 +9815,7 @@ static Object* Runtime_LiveEditGatherCompileInfo(Arguments args) { // Changes the source of the script to a new_source. // If old_script_name is provided (i.e. is a String), also creates a copy of // the script with its original source and sends notification to debugger. -static Object* Runtime_LiveEditReplaceScript(Arguments args) { +static MaybeObject* Runtime_LiveEditReplaceScript(Arguments args) { ASSERT(args.length() == 3); HandleScope scope; CONVERT_CHECKED(JSValue, original_script_value, args[0]); @@ -9621,7 +9839,7 @@ static Object* Runtime_LiveEditReplaceScript(Arguments args) { } // Replaces code of SharedFunctionInfo with a new one. -static Object* Runtime_LiveEditReplaceFunctionCode(Arguments args) { +static MaybeObject* Runtime_LiveEditReplaceFunctionCode(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; CONVERT_ARG_CHECKED(JSArray, new_compile_info, 0); @@ -9631,7 +9849,7 @@ static Object* Runtime_LiveEditReplaceFunctionCode(Arguments args) { } // Connects SharedFunctionInfo to another script. -static Object* Runtime_LiveEditFunctionSetScript(Arguments args) { +static MaybeObject* Runtime_LiveEditFunctionSetScript(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; Handle<Object> function_object(args[0]); @@ -9656,7 +9874,7 @@ static Object* Runtime_LiveEditFunctionSetScript(Arguments args) { // In a code of a parent function replaces original function as embedded object // with a substitution one. -static Object* Runtime_LiveEditReplaceRefToNestedFunction(Arguments args) { +static MaybeObject* Runtime_LiveEditReplaceRefToNestedFunction(Arguments args) { ASSERT(args.length() == 3); HandleScope scope; @@ -9676,7 +9894,7 @@ static Object* Runtime_LiveEditReplaceRefToNestedFunction(Arguments args) { // array of groups of 3 numbers: // (change_begin, change_end, change_end_new_position). // Each group describes a change in text; groups are sorted by change_begin. -static Object* Runtime_LiveEditPatchFunctionPositions(Arguments args) { +static MaybeObject* Runtime_LiveEditPatchFunctionPositions(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; CONVERT_ARG_CHECKED(JSArray, shared_array, 0); @@ -9690,7 +9908,7 @@ static Object* Runtime_LiveEditPatchFunctionPositions(Arguments args) { // checks that none of them have activations on stacks (of any thread). // Returns array of the same length with corresponding results of // LiveEdit::FunctionPatchabilityStatus type. -static Object* Runtime_LiveEditCheckAndDropActivations(Arguments args) { +static MaybeObject* Runtime_LiveEditCheckAndDropActivations(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; CONVERT_ARG_CHECKED(JSArray, shared_array, 0); @@ -9701,7 +9919,7 @@ static Object* Runtime_LiveEditCheckAndDropActivations(Arguments args) { // Compares 2 strings line-by-line and returns diff in form of JSArray of // triplets (pos1, pos1_end, pos2_end) describing list of diff chunks. -static Object* Runtime_LiveEditCompareStringsLinewise(Arguments args) { +static MaybeObject* Runtime_LiveEditCompareStringsLinewise(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; CONVERT_ARG_CHECKED(String, s1, 0); @@ -9714,7 +9932,7 @@ static Object* Runtime_LiveEditCompareStringsLinewise(Arguments args) { // A testing entry. Returns statement position which is the closest to // source_position. -static Object* Runtime_GetFunctionCodePositionFromSource(Arguments args) { +static MaybeObject* Runtime_GetFunctionCodePositionFromSource(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; CONVERT_ARG_CHECKED(JSFunction, function, 0); @@ -9746,7 +9964,7 @@ static Object* Runtime_GetFunctionCodePositionFromSource(Arguments args) { // Calls specified function with or without entering the debugger. // This is used in unit tests to run code as if debugger is entered or simply // to have a stack with C++ frame in the middle. -static Object* Runtime_ExecuteInDebugContext(Arguments args) { +static MaybeObject* Runtime_ExecuteInDebugContext(Arguments args) { ASSERT(args.length() == 2); HandleScope scope; CONVERT_ARG_CHECKED(JSFunction, function, 0); @@ -9776,7 +9994,7 @@ static Object* Runtime_ExecuteInDebugContext(Arguments args) { #ifdef ENABLE_LOGGING_AND_PROFILING -static Object* Runtime_ProfilerResume(Arguments args) { +static MaybeObject* Runtime_ProfilerResume(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -9787,7 +10005,7 @@ static Object* Runtime_ProfilerResume(Arguments args) { } -static Object* Runtime_ProfilerPause(Arguments args) { +static MaybeObject* Runtime_ProfilerPause(Arguments args) { NoHandleAllocation ha; ASSERT(args.length() == 2); @@ -9834,7 +10052,7 @@ static Handle<Object> Runtime_GetScriptFromScriptName( // Get the script object from script data. NOTE: Regarding performance // see the NOTE for GetScriptFromScriptData. // args[0]: script data for the script to find the source for -static Object* Runtime_GetScript(Arguments args) { +static MaybeObject* Runtime_GetScript(Arguments args) { HandleScope scope; ASSERT(args.length() == 1); @@ -9879,7 +10097,7 @@ static bool ShowFrameInStackTrace(StackFrame* raw_frame, Object* caller, // Collect the raw data for a stack trace. Returns an array of three // element segments each containing a receiver, function and native // code offset. -static Object* Runtime_CollectStackTrace(Arguments args) { +static MaybeObject* Runtime_CollectStackTrace(Arguments args) { ASSERT_EQ(args.length(), 2); Handle<Object> caller = args.at<Object>(0); CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]); @@ -9929,7 +10147,7 @@ static Object* Runtime_CollectStackTrace(Arguments args) { // Returns V8 version as a string. -static Object* Runtime_GetV8Version(Arguments args) { +static MaybeObject* Runtime_GetV8Version(Arguments args) { ASSERT_EQ(args.length(), 0); NoHandleAllocation ha; @@ -9940,7 +10158,7 @@ static Object* Runtime_GetV8Version(Arguments args) { } -static Object* Runtime_Abort(Arguments args) { +static MaybeObject* Runtime_Abort(Arguments args) { ASSERT(args.length() == 2); OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) + Smi::cast(args[1])->value()); @@ -9951,14 +10169,9 @@ static Object* Runtime_Abort(Arguments args) { } -static Object* Runtime_DeleteHandleScopeExtensions(Arguments args) { - ASSERT(args.length() == 0); - HandleScope::DeleteExtensions(); - return Heap::undefined_value(); -} - - -static Object* CacheMiss(FixedArray* cache_obj, int index, Object* key_obj) { +MUST_USE_RESULT static MaybeObject* CacheMiss(FixedArray* cache_obj, + int index, + Object* key_obj) { ASSERT(index % 2 == 0); // index of the key ASSERT(index >= JSFunctionResultCache::kEntriesIndex); ASSERT(index < cache_obj->length()); @@ -9993,7 +10206,7 @@ static Object* CacheMiss(FixedArray* cache_obj, int index, Object* key_obj) { } -static Object* Runtime_GetFromCache(Arguments args) { +static MaybeObject* Runtime_GetFromCache(Arguments args) { // This is only called from codegen, so checks might be more lax. CONVERT_CHECKED(FixedArray, cache, args[0]); Object* key = args[1]; @@ -10046,7 +10259,7 @@ static Object* Runtime_GetFromCache(Arguments args) { #ifdef DEBUG // ListNatives is ONLY used by the fuzz-natives.js in debug mode // Exclude the code in release mode. -static Object* Runtime_ListNatives(Arguments args) { +static MaybeObject* Runtime_ListNatives(Arguments args) { ASSERT(args.length() == 0); HandleScope scope; Handle<JSArray> result = Factory::NewJSArray(0); @@ -10080,7 +10293,7 @@ static Object* Runtime_ListNatives(Arguments args) { #endif -static Object* Runtime_Log(Arguments args) { +static MaybeObject* Runtime_Log(Arguments args) { ASSERT(args.length() == 2); CONVERT_CHECKED(String, format, args[0]); CONVERT_CHECKED(JSArray, elms, args[1]); @@ -10090,7 +10303,7 @@ static Object* Runtime_Log(Arguments args) { } -static Object* Runtime_IS_VAR(Arguments args) { +static MaybeObject* Runtime_IS_VAR(Arguments args) { UNREACHABLE(); // implemented as macro in the parser return NULL; } @@ -10115,18 +10328,26 @@ Runtime::Function kIntrinsicFunctions[] = { }; -Object* Runtime::InitializeIntrinsicFunctionNames(Object* dictionary) { +MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Object* dictionary) { ASSERT(dictionary != NULL); ASSERT(StringDictionary::cast(dictionary)->NumberOfElements() == 0); for (int i = 0; i < kNumFunctions; ++i) { - Object* name_symbol = Heap::LookupAsciiSymbol(kIntrinsicFunctions[i].name); - if (name_symbol->IsFailure()) return name_symbol; + Object* name_symbol; + { MaybeObject* maybe_name_symbol = + Heap::LookupAsciiSymbol(kIntrinsicFunctions[i].name); + if (!maybe_name_symbol->ToObject(&name_symbol)) return maybe_name_symbol; + } StringDictionary* string_dictionary = StringDictionary::cast(dictionary); - dictionary = string_dictionary->Add(String::cast(name_symbol), - Smi::FromInt(i), - PropertyDetails(NONE, NORMAL)); - // Non-recoverable failure. Calling code must restart heap initialization. - if (dictionary->IsFailure()) return dictionary; + { MaybeObject* maybe_dictionary = string_dictionary->Add( + String::cast(name_symbol), + Smi::FromInt(i), + PropertyDetails(NONE, NORMAL)); + if (!maybe_dictionary->ToObject(&dictionary)) { + // Non-recoverable failure. Calling code must restart heap + // initialization. + return maybe_dictionary; + } + } } return dictionary; } diff --git a/deps/v8/src/runtime.h b/deps/v8/src/runtime.h index 2cd95c493d..8057d8bd30 100644 --- a/deps/v8/src/runtime.h +++ b/deps/v8/src/runtime.h @@ -297,8 +297,6 @@ namespace internal { F(Log, 2, 1) \ /* ES5 */ \ F(LocalKeys, 1, 1) \ - /* Handle scopes */ \ - F(DeleteHandleScopeExtensions, 0, 1) \ /* Cache suport */ \ F(GetFromCache, 2, 1) \ \ @@ -488,7 +486,8 @@ class Runtime : public AllStatic { // Returns failure if an allocation fails. In this case, it must be // retried with a new, empty StringDictionary, not with the same one. // 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. static Function* FunctionForSymbol(Handle<String> name); @@ -506,23 +505,29 @@ class Runtime : public AllStatic { // Support getting the characters in a string using [] notation as // in Firefox/SpiderMonkey, Safari and Opera. - static Object* GetElementOrCharAt(Handle<Object> object, uint32_t index); - static Object* GetElement(Handle<Object> object, uint32_t index); - - static Object* SetObjectProperty(Handle<Object> object, - Handle<Object> key, - Handle<Object> value, - PropertyAttributes attr); - - static Object* ForceSetObjectProperty(Handle<JSObject> object, - Handle<Object> key, - Handle<Object> value, - PropertyAttributes attr); - - static Object* ForceDeleteObjectProperty(Handle<JSObject> object, - Handle<Object> key); - - static Object* GetObjectProperty(Handle<Object> object, Handle<Object> key); + MUST_USE_RESULT static MaybeObject* GetElementOrCharAt(Handle<Object> object, + uint32_t index); + MUST_USE_RESULT static MaybeObject* GetElement(Handle<Object> object, + uint32_t index); + + MUST_USE_RESULT static MaybeObject* SetObjectProperty( + Handle<Object> object, + Handle<Object> key, + Handle<Object> value, + PropertyAttributes attr); + + MUST_USE_RESULT static MaybeObject* ForceSetObjectProperty( + Handle<JSObject> object, + Handle<Object> key, + Handle<Object> value, + PropertyAttributes attr); + + 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. static Object* FindSharedFunctionInfoInScript(Handle<Script> script, diff --git a/deps/v8/src/serialize.cc b/deps/v8/src/serialize.cc index ccba737d15..763c12f4f5 100644 --- a/deps/v8/src/serialize.cc +++ b/deps/v8/src/serialize.cc @@ -337,6 +337,11 @@ void ExternalReferenceTable::PopulateTable() { 3, "V8::Random"); + Add(ExternalReference::delete_handle_scope_extensions().address(), + RUNTIME_ENTRY, + 3, + "HandleScope::DeleteExtensions"); + // Miscellaneous Add(ExternalReference::the_hole_value_location().address(), UNCLASSIFIED, @@ -457,6 +462,18 @@ void ExternalReferenceTable::PopulateTable() { UNCLASSIFIED, 29, "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)) { ASSERT(!SpaceIsPaged(space_index) || size <= Page::kPageSize - Page::kObjectStartOffset); - Object* new_allocation; + MaybeObject* maybe_new_allocation; if (space_index == NEW_SPACE) { - new_allocation = reinterpret_cast<NewSpace*>(space)->AllocateRaw(size); + maybe_new_allocation = + reinterpret_cast<NewSpace*>(space)->AllocateRaw(size); } 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); - ASSERT(!new_object->IsFailure()); address = new_object->address(); high_water_[space_index] = address + size; } else { @@ -554,14 +573,14 @@ Address Deserializer::Allocate(int space_index, Space* space, int size) { LargeObjectSpace* lo_space = reinterpret_cast<LargeObjectSpace*>(space); Object* new_allocation; if (space_index == kLargeData) { - new_allocation = lo_space->AllocateRaw(size); + new_allocation = lo_space->AllocateRaw(size)->ToObjectUnchecked(); } else if (space_index == kLargeFixedArray) { - new_allocation = lo_space->AllocateRawFixedArray(size); + new_allocation = + lo_space->AllocateRawFixedArray(size)->ToObjectUnchecked(); } else { 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); // Record all large objects in the same space. address = new_object->address(); diff --git a/deps/v8/src/spaces-inl.h b/deps/v8/src/spaces-inl.h index 8a0dd07c20..7806223216 100644 --- a/deps/v8/src/spaces-inl.h +++ b/deps/v8/src/spaces-inl.h @@ -430,7 +430,7 @@ HeapObject* PagedSpace::AllocateLinearly(AllocationInfo* alloc_info, // Raw allocation. -Object* PagedSpace::AllocateRaw(int size_in_bytes) { +MaybeObject* PagedSpace::AllocateRaw(int size_in_bytes) { ASSERT(HasBeenSetup()); ASSERT_OBJECT_SIZE(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. -Object* PagedSpace::MCAllocateRaw(int size_in_bytes) { +MaybeObject* PagedSpace::MCAllocateRaw(int size_in_bytes) { ASSERT(HasBeenSetup()); ASSERT_OBJECT_SIZE(size_in_bytes); HeapObject* object = AllocateLinearly(&mc_forwarding_info_, size_in_bytes); @@ -471,8 +471,8 @@ HeapObject* LargeObjectChunk::GetObject() { // ----------------------------------------------------------------------------- // LargeObjectSpace -Object* NewSpace::AllocateRawInternal(int size_in_bytes, - AllocationInfo* alloc_info) { +MaybeObject* NewSpace::AllocateRawInternal(int size_in_bytes, + AllocationInfo* alloc_info) { Address new_top = alloc_info->top + size_in_bytes; if (new_top > alloc_info->limit) return Failure::RetryAfterGC(); diff --git a/deps/v8/src/spaces.cc b/deps/v8/src/spaces.cc index 5bdbcc7842..e3fb923312 100644 --- a/deps/v8/src/spaces.cc +++ b/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 // because it accesses map pointers. 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(size_in_bytes <= kMaxBlockSize); ASSERT(IsAligned(size_in_bytes, kPointerSize)); @@ -1924,7 +1924,7 @@ void FixedSizeFreeList::Free(Address start) { } -Object* FixedSizeFreeList::Allocate() { +MaybeObject* FixedSizeFreeList::Allocate() { if (head_ == NULL) { return Failure::RetryAfterGC(owner_); } @@ -2187,9 +2187,10 @@ HeapObject* OldSpace::SlowAllocateRaw(int size_in_bytes) { // is currently forbidden. if (!Heap::linear_allocation()) { 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); - if (!result->IsFailure()) { + if (maybe->ToObject(&result)) { accounting_stats_.AllocateBytes(size_in_bytes); 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 all free blocks are of the fixed size. if (!Heap::linear_allocation()) { - Object* result = free_list_.Allocate(); - if (!result->IsFailure()) { + Object* result; + MaybeObject* maybe = free_list_.Allocate(); + if (maybe->ToObject(&result)) { accounting_stats_.AllocateBytes(size_in_bytes); HeapObject* obj = HeapObject::cast(result); Page* p = Page::FromAddress(obj->address()); @@ -2745,9 +2747,9 @@ void LargeObjectSpace::Unprotect() { #endif -Object* LargeObjectSpace::AllocateRawInternal(int requested_size, - int object_size, - Executability executable) { +MaybeObject* LargeObjectSpace::AllocateRawInternal(int requested_size, + int object_size, + Executability executable) { ASSERT(0 < object_size && object_size <= requested_size); // 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); return AllocateRawInternal(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); return AllocateRawInternal(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); return AllocateRawInternal(size_in_bytes, size_in_bytes, @@ -2808,7 +2810,7 @@ Object* LargeObjectSpace::AllocateRaw(int size_in_bytes) { // GC support -Object* LargeObjectSpace::FindObject(Address a) { +MaybeObject* LargeObjectSpace::FindObject(Address a) { for (LargeObjectChunk* chunk = first_chunk_; chunk != NULL; chunk = chunk->next()) { diff --git a/deps/v8/src/spaces.h b/deps/v8/src/spaces.h index 0e6a91e2ae..3ed2fe8b98 100644 --- a/deps/v8/src/spaces.h +++ b/deps/v8/src/spaces.h @@ -425,7 +425,8 @@ class CodeRange : public AllStatic { // Allocates a chunk of memory from the large-object portion of // the code range. On platforms with no separate code range, should // 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); private: @@ -563,9 +564,9 @@ class MemoryAllocator : public AllStatic { // If the flag is EXECUTABLE and a code range exists, the requested // 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. - static void* AllocateRawMemory(const size_t requested, - size_t* allocated, - Executability executable); + MUST_USE_RESULT static void* AllocateRawMemory(const size_t requested, + size_t* allocated, + Executability executable); static void FreeRawMemory(void* buf, size_t length, Executability executable); @@ -1010,7 +1011,7 @@ class PagedSpace : public Space { // in this space, or Failure::Exception() if it is not. The implementation // 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. - Object* FindObject(Address addr); + MUST_USE_RESULT MaybeObject* FindObject(Address addr); // Checks whether page is currently in use by this space. 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 // 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 // collection. - inline Object* MCAllocateRaw(int size_in_bytes); + MUST_USE_RESULT inline MaybeObject* MCAllocateRaw(int size_in_bytes); virtual bool ReserveSpace(int bytes); @@ -1206,10 +1207,10 @@ class PagedSpace : public Space { int size_in_bytes) = 0; // 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. - HeapObject* SlowMCAllocateRaw(int size_in_bytes); + MUST_USE_RESULT HeapObject* SlowMCAllocateRaw(int size_in_bytes); #ifdef DEBUG // 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_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_); } // Allocate the requested number of bytes for relocation during mark-compact // collection. - Object* MCAllocateRaw(int size_in_bytes) { + MUST_USE_RESULT MaybeObject* MCAllocateRaw(int size_in_bytes) { return AllocateRawInternal(size_in_bytes, &mc_forwarding_info_); } @@ -1635,8 +1636,9 @@ class NewSpace : public Space { #endif // Implementation of AllocateRaw and MCAllocateRaw. - inline Object* AllocateRawInternal(int size_in_bytes, - AllocationInfo* alloc_info); + MUST_USE_RESULT inline MaybeObject* AllocateRawInternal( + int size_in_bytes, + AllocationInfo* alloc_info); friend class SemiSpaceIterator; @@ -1703,7 +1705,7 @@ class OldSpaceFreeList BASE_EMBEDDED { // is unitialized. A failure is returned if no block is available. The // 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. - Object* Allocate(int size_in_bytes, int* wasted_bytes); + MUST_USE_RESULT MaybeObject* Allocate(int size_in_bytes, int* wasted_bytes); private: // 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. // A failure is returned if no block is available. - Object* Allocate(); + MUST_USE_RESULT MaybeObject* Allocate(); private: // Available bytes on the free list. @@ -1881,7 +1883,7 @@ class OldSpace : public PagedSpace { protected: // 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 // the page after current_page (there is assumed to be one). @@ -1948,7 +1950,7 @@ class FixedSpace : public PagedSpace { protected: // 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 // the page after current_page (there is assumed to be one). @@ -2166,11 +2168,11 @@ class LargeObjectSpace : public Space { void TearDown(); // 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. - Object* AllocateRawCode(int size_in_bytes); + MUST_USE_RESULT MaybeObject* AllocateRawCode(int size_in_bytes); // 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. intptr_t Available() { @@ -2188,7 +2190,7 @@ class LargeObjectSpace : public Space { // Finds an object for a given address, returns Failure::Exception() // if it is not found. The function iterates through all objects in this // space, may be slow. - Object* FindObject(Address a); + MaybeObject* FindObject(Address a); // Finds a large object page containing the given pc, returns NULL // if such a page doesn't exist. @@ -2236,9 +2238,9 @@ class LargeObjectSpace : public Space { // Shared implementation of AllocateRaw, AllocateRawCode and // AllocateRawFixedArray. - Object* AllocateRawInternal(int requested_size, - int object_size, - Executability executable); + MUST_USE_RESULT MaybeObject* AllocateRawInternal(int requested_size, + int object_size, + Executability executable); friend class LargeObjectIterator; diff --git a/deps/v8/src/strtod.cc b/deps/v8/src/strtod.cc index ae278bd98c..0ed1b0d914 100644 --- a/deps/v8/src/strtod.cc +++ b/deps/v8/src/strtod.cc @@ -31,7 +31,8 @@ #include "v8.h" #include "strtod.h" -// #include "cached-powers.h" +#include "cached-powers.h" +#include "double.h" namespace v8 { namespace internal { @@ -40,9 +41,9 @@ namespace internal { // Any integer with at most 15 decimal digits will hence fit into a double // (which has a 53bit significand) without loss of precision. static const int kMaxExactDoubleIntegerDecimalDigits = 15; -// 2^64 = 18446744073709551616 -// Any integer with at most 19 digits will hence fit into a 64bit datatype. +// 2^64 = 18446744073709551616 > 10^19 static const int kMaxUint64DecimalDigits = 19; + // Max double: 1.7976931348623157 x 10^308 // Min non-zero double: 4.9406564584124654 x 10^-324 // 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 kMinDecimalPower = -324; +// 2^64 = 18446744073709551616 +static const uint64_t kMaxUint64 = V8_2PART_UINT64_C(0xFFFFFFFF, FFFFFFFF); + + static const double exact_powers_of_ten[] = { 1.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) { for (int i = 0; i < buffer.length(); i++) { 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); @@ -130,25 +135,57 @@ static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) { static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) { for (int i = buffer.length() - 1; i >= 0; --i) { 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); } -uint64_t ReadUint64(Vector<const char> buffer) { - ASSERT(buffer.length() <= kMaxUint64DecimalDigits); +// Reads digits from the buffer and converts them to a uint64. +// 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; - for (int i = 0; i < buffer.length(); ++i) { - int digit = buffer[i] - '0'; + int i = 0; + while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { + int digit = buffer[i++] - '0'; ASSERT(0 <= digit && digit <= 9); result = 10 * result + digit; } + *number_of_read_digits = i; 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, int exponent, double* result) { @@ -162,6 +199,7 @@ static bool DoubleStrtod(Vector<const char> trimmed, return false; #endif if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { + int read_digits; // The trimmed input fits into a double. // 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 @@ -170,13 +208,15 @@ static bool DoubleStrtod(Vector<const char> trimmed, // return the best possible approximation. if (exponent < 0 && -exponent < kExactPowersOfTenSize) { // 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]; return true; } if (0 <= exponent && exponent < kExactPowersOfTenSize) { // 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]; return true; } @@ -187,7 +227,8 @@ static bool DoubleStrtod(Vector<const char> trimmed, // The trimmed string was short and we can multiply it with // 10^remaining_digits. As a result the remaining exponent now fits // 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[exponent - remaining_digits]; 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) { Vector<const char> left_trimmed = TrimLeadingZeros(buffer); 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 (exponent + trimmed.length() - 1 >= kMaxDecimalPower) return V8_INFINITY; if (exponent + trimmed.length() <= kMinDecimalPower) return 0.0; + double result; - if (DoubleStrtod(trimmed, exponent, &result)) { + if (DoubleStrtod(trimmed, exponent, &result) || + DiyFpStrtod(trimmed, exponent, &result)) { return result; } return old_strtod(trimmed, exponent); diff --git a/deps/v8/src/stub-cache.cc b/deps/v8/src/stub-cache.cc index e6df1b49e3..e794f0932d 100644 --- a/deps/v8/src/stub-cache.cc +++ b/deps/v8/src/stub-cache.cc @@ -93,7 +93,8 @@ Code* StubCache::Set(String* name, Map* map, Code* code) { } -Object* StubCache::ComputeLoadNonexistent(String* name, JSObject* receiver) { +MaybeObject* StubCache::ComputeLoadNonexistent(String* name, + JSObject* receiver) { ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties()); // If no global objects are present in the prototype chain, the load // nonexistent IC stub can be shared for all names for a given map @@ -115,344 +116,431 @@ Object* StubCache::ComputeLoadNonexistent(String* name, JSObject* receiver) { Object* code = receiver->map()->FindInCodeCache(cache_name, flags); if (code->IsUndefined()) { LoadStubCompiler compiler; - code = compiler.CompileLoadNonexistent(cache_name, receiver, last); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileLoadNonexistent(cache_name, receiver, last); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), cache_name)); - Object* result = - receiver->UpdateMapCodeCache(cache_name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(cache_name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeLoadField(String* name, - JSObject* receiver, - JSObject* holder, - int field_index) { +MaybeObject* StubCache::ComputeLoadField(String* name, + JSObject* receiver, + JSObject* holder, + int field_index) { ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { LoadStubCompiler compiler; - code = compiler.CompileLoadField(receiver, holder, field_index, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileLoadField(receiver, holder, field_index, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeLoadCallback(String* name, - JSObject* receiver, - JSObject* holder, - AccessorInfo* callback) { +MaybeObject* StubCache::ComputeLoadCallback(String* name, + JSObject* receiver, + JSObject* holder, + AccessorInfo* callback) { ASSERT(v8::ToCData<Address>(callback->getter()) != 0); ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { LoadStubCompiler compiler; - code = compiler.CompileLoadCallback(name, receiver, holder, callback); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileLoadCallback(name, receiver, holder, callback); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeLoadConstant(String* name, - JSObject* receiver, - JSObject* holder, - Object* value) { +MaybeObject* StubCache::ComputeLoadConstant(String* name, + JSObject* receiver, + JSObject* holder, + Object* value) { ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { LoadStubCompiler compiler; - code = compiler.CompileLoadConstant(receiver, holder, value, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileLoadConstant(receiver, holder, value, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeLoadInterceptor(String* name, - JSObject* receiver, - JSObject* holder) { +MaybeObject* StubCache::ComputeLoadInterceptor(String* name, + JSObject* receiver, + JSObject* holder) { ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { LoadStubCompiler compiler; - code = compiler.CompileLoadInterceptor(receiver, holder, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileLoadInterceptor(receiver, holder, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeLoadNormal() { +MaybeObject* StubCache::ComputeLoadNormal() { return Builtins::builtin(Builtins::LoadIC_Normal); } -Object* StubCache::ComputeLoadGlobal(String* name, - JSObject* receiver, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - bool is_dont_delete) { +MaybeObject* StubCache::ComputeLoadGlobal(String* name, + JSObject* receiver, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + bool is_dont_delete) { ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { LoadStubCompiler compiler; - code = compiler.CompileLoadGlobal(receiver, - holder, - cell, - name, - is_dont_delete); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = compiler.CompileLoadGlobal(receiver, + holder, + cell, + name, + is_dont_delete); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeKeyedLoadField(String* name, - JSObject* receiver, - JSObject* holder, - int field_index) { +MaybeObject* StubCache::ComputeKeyedLoadField(String* name, + JSObject* receiver, + JSObject* holder, + int field_index) { ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { KeyedLoadStubCompiler compiler; - code = compiler.CompileLoadField(name, receiver, holder, field_index); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileLoadField(name, receiver, holder, field_index); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeKeyedLoadConstant(String* name, - JSObject* receiver, - JSObject* holder, - Object* value) { +MaybeObject* StubCache::ComputeKeyedLoadConstant(String* name, + JSObject* receiver, + JSObject* holder, + Object* value) { ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { KeyedLoadStubCompiler compiler; - code = compiler.CompileLoadConstant(name, receiver, holder, value); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileLoadConstant(name, receiver, holder, value); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeKeyedLoadInterceptor(String* name, - JSObject* receiver, - JSObject* holder) { +MaybeObject* StubCache::ComputeKeyedLoadInterceptor(String* name, + JSObject* receiver, + JSObject* holder) { ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { KeyedLoadStubCompiler compiler; - code = compiler.CompileLoadInterceptor(receiver, holder, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileLoadInterceptor(receiver, holder, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeKeyedLoadCallback(String* name, - JSObject* receiver, - JSObject* holder, - AccessorInfo* callback) { +MaybeObject* StubCache::ComputeKeyedLoadCallback(String* name, + JSObject* receiver, + JSObject* holder, + AccessorInfo* callback) { ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { KeyedLoadStubCompiler compiler; - code = compiler.CompileLoadCallback(name, receiver, holder, callback); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileLoadCallback(name, receiver, holder, callback); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeKeyedLoadArrayLength(String* name, - JSArray* receiver) { +MaybeObject* StubCache::ComputeKeyedLoadArrayLength(String* name, + JSArray* receiver) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); ASSERT(receiver->IsJSObject()); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { KeyedLoadStubCompiler compiler; - code = compiler.CompileLoadArrayLength(name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeKeyedLoadStringLength(String* name, - String* receiver) { +MaybeObject* StubCache::ComputeKeyedLoadStringLength(String* name, + String* receiver) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); Map* map = receiver->map(); Object* code = map->FindInCodeCache(name, flags); if (code->IsUndefined()) { KeyedLoadStubCompiler compiler; - code = compiler.CompileLoadStringLength(name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = compiler.CompileLoadStringLength(name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); - Object* result = map->UpdateCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = map->UpdateCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeKeyedLoadFunctionPrototype(String* name, - JSFunction* receiver) { +MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype( + String* name, + JSFunction* receiver) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { KeyedLoadStubCompiler compiler; - code = compiler.CompileLoadFunctionPrototype(name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeStoreField(String* name, - JSObject* receiver, - int field_index, - Map* transition) { +MaybeObject* StubCache::ComputeStoreField(String* name, + JSObject* receiver, + int field_index, + Map* transition) { PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION; Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { StoreStubCompiler compiler; - code = compiler.CompileStoreField(receiver, field_index, transition, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileStoreField(receiver, field_index, transition, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeStoreNormal() { +MaybeObject* StubCache::ComputeStoreNormal() { return Builtins::builtin(Builtins::StoreIC_Normal); } -Object* StubCache::ComputeStoreGlobal(String* name, - GlobalObject* receiver, - JSGlobalPropertyCell* cell) { +MaybeObject* StubCache::ComputeStoreGlobal(String* name, + GlobalObject* receiver, + JSGlobalPropertyCell* cell) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { StoreStubCompiler compiler; - code = compiler.CompileStoreGlobal(receiver, cell, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileStoreGlobal(receiver, cell, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeStoreCallback(String* name, - JSObject* receiver, - AccessorInfo* callback) { +MaybeObject* StubCache::ComputeStoreCallback(String* name, + JSObject* receiver, + AccessorInfo* callback) { ASSERT(v8::ToCData<Address>(callback->setter()) != 0); Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, CALLBACKS); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { StoreStubCompiler compiler; - code = compiler.CompileStoreCallback(receiver, callback, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileStoreCallback(receiver, callback, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeStoreInterceptor(String* name, - JSObject* receiver) { +MaybeObject* StubCache::ComputeStoreInterceptor(String* name, + JSObject* receiver) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, INTERCEPTOR); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { StoreStubCompiler compiler; - code = compiler.CompileStoreInterceptor(receiver, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileStoreInterceptor(receiver, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeKeyedStoreField(String* name, JSObject* receiver, - int field_index, Map* transition) { +MaybeObject* StubCache::ComputeKeyedStoreField(String* name, + JSObject* receiver, + int field_index, + Map* transition) { PropertyType type = (transition == NULL) ? FIELD : MAP_TRANSITION; Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type); Object* code = receiver->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { KeyedStoreStubCompiler compiler; - code = compiler.CompileStoreField(receiver, field_index, transition, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileStoreField(receiver, field_index, transition, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } PROFILE(CodeCreateEvent( Logger::KEYED_STORE_IC_TAG, Code::cast(code), name)); - Object* result = receiver->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + receiver->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } @@ -460,13 +548,13 @@ Object* StubCache::ComputeKeyedStoreField(String* name, JSObject* receiver, #define CALL_LOGGER_TAG(kind, type) \ (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) -Object* StubCache::ComputeCallConstant(int argc, - InLoopFlag in_loop, - Code::Kind kind, - String* name, - Object* object, - JSObject* holder, - JSFunction* function) { +MaybeObject* StubCache::ComputeCallConstant(int argc, + InLoopFlag in_loop, + Code::Kind kind, + String* name, + Object* object, + JSObject* holder, + JSFunction* function) { // Compute the check type and the map. InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(object, holder); @@ -497,25 +585,30 @@ Object* StubCache::ComputeCallConstant(int argc, if (!function->is_compiled()) return Failure::InternalError(); // Compile the stub - only create stubs for fully compiled functions. CallStubCompiler compiler(argc, in_loop, kind, cache_holder); - code = compiler.CompileCallConstant(object, holder, function, name, check); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileCallConstant(object, holder, function, name, check); + if (!maybe_code->ToObject(&code)) return maybe_code; + } ASSERT_EQ(flags, Code::cast(code)->flags()); PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), Code::cast(code), name)); - Object* result = map_holder->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + map_holder->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeCallField(int argc, - InLoopFlag in_loop, - Code::Kind kind, - String* name, - Object* object, - JSObject* holder, - int index) { +MaybeObject* StubCache::ComputeCallField(int argc, + InLoopFlag in_loop, + Code::Kind kind, + String* name, + Object* object, + JSObject* holder, + int index) { // Compute the check type and the map. InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(object, holder); @@ -536,26 +629,31 @@ Object* StubCache::ComputeCallField(int argc, Object* code = map_holder->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { CallStubCompiler compiler(argc, in_loop, kind, cache_holder); - code = compiler.CompileCallField(JSObject::cast(object), - holder, - index, - name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileCallField(JSObject::cast(object), + holder, + index, + name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } ASSERT_EQ(flags, Code::cast(code)->flags()); PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), Code::cast(code), name)); - Object* result = map_holder->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + map_holder->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeCallInterceptor(int argc, - Code::Kind kind, - String* name, - Object* object, - JSObject* holder) { +MaybeObject* StubCache::ComputeCallInterceptor(int argc, + Code::Kind kind, + String* name, + Object* object, + JSObject* holder) { // Compute the check type and the map. InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(object, holder); @@ -577,39 +675,44 @@ Object* StubCache::ComputeCallInterceptor(int argc, Object* code = map_holder->map()->FindInCodeCache(name, flags); if (code->IsUndefined()) { CallStubCompiler compiler(argc, NOT_IN_LOOP, kind, cache_holder); - code = compiler.CompileCallInterceptor(JSObject::cast(object), - holder, - name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileCallInterceptor(JSObject::cast(object), holder, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } ASSERT_EQ(flags, Code::cast(code)->flags()); PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), Code::cast(code), name)); - Object* result = map_holder->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + map_holder->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } -Object* StubCache::ComputeCallNormal(int argc, - InLoopFlag in_loop, - Code::Kind kind, - String* name, - JSObject* receiver) { - Object* code = ComputeCallNormal(argc, in_loop, kind); - if (code->IsFailure()) return code; +MaybeObject* StubCache::ComputeCallNormal(int argc, + InLoopFlag in_loop, + Code::Kind kind, + String* name, + JSObject* receiver) { + Object* code; + { MaybeObject* maybe_code = ComputeCallNormal(argc, in_loop, kind); + if (!maybe_code->ToObject(&code)) return maybe_code; + } return code; } -Object* StubCache::ComputeCallGlobal(int argc, - InLoopFlag in_loop, - Code::Kind kind, - String* name, - JSObject* receiver, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function) { +MaybeObject* StubCache::ComputeCallGlobal(int argc, + InLoopFlag in_loop, + Code::Kind kind, + String* name, + JSObject* receiver, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function) { InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(receiver, holder); JSObject* map_holder = IC::GetCodeCacheHolder(receiver, cache_holder); @@ -627,13 +730,18 @@ Object* StubCache::ComputeCallGlobal(int argc, // caches. if (!function->is_compiled()) return Failure::InternalError(); CallStubCompiler compiler(argc, in_loop, kind, cache_holder); - code = compiler.CompileCallGlobal(receiver, holder, cell, function, name); - if (code->IsFailure()) return code; + { MaybeObject* maybe_code = + compiler.CompileCallGlobal(receiver, holder, cell, function, name); + if (!maybe_code->ToObject(&code)) return maybe_code; + } ASSERT_EQ(flags, Code::cast(code)->flags()); PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), Code::cast(code), name)); - Object* result = map_holder->UpdateMapCodeCache(name, Code::cast(code)); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + map_holder->UpdateMapCodeCache(name, Code::cast(code)); + if (!maybe_result->ToObject(&result)) return maybe_result; + } } return code; } @@ -648,34 +756,39 @@ static Object* GetProbeValue(Code::Flags flags) { } -static Object* ProbeCache(Code::Flags flags) { +MUST_USE_RESULT static MaybeObject* ProbeCache(Code::Flags flags) { Object* probe = GetProbeValue(flags); if (probe != Heap::undefined_value()) return probe; // Seed the cache with an undefined value to make sure that any // generated code object can always be inserted into the cache // without causing allocation failures. - Object* result = - Heap::non_monomorphic_cache()->AtNumberPut(flags, - Heap::undefined_value()); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = + Heap::non_monomorphic_cache()->AtNumberPut(flags, + Heap::undefined_value()); + if (!maybe_result->ToObject(&result)) return maybe_result; + } Heap::public_set_non_monomorphic_cache(NumberDictionary::cast(result)); return probe; } -static Object* FillCache(Object* code) { - if (code->IsCode()) { - int entry = - Heap::non_monomorphic_cache()->FindEntry( - Code::cast(code)->flags()); - // The entry must be present see comment in ProbeCache. - ASSERT(entry != -1); - ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) == - Heap::undefined_value()); - Heap::non_monomorphic_cache()->ValueAtPut(entry, code); - CHECK(GetProbeValue(Code::cast(code)->flags()) == code); +static MaybeObject* FillCache(MaybeObject* maybe_code) { + Object* code; + if (maybe_code->ToObject(&code)) { + if (code->IsCode()) { + int entry = + Heap::non_monomorphic_cache()->FindEntry( + Code::cast(code)->flags()); + // The entry must be present see comment in ProbeCache. + ASSERT(entry != -1); + ASSERT(Heap::non_monomorphic_cache()->ValueAt(entry) == + Heap::undefined_value()); + Heap::non_monomorphic_cache()->ValueAtPut(entry, code); + CHECK(GetProbeValue(Code::cast(code)->flags()) == code); + } } - return code; + return maybe_code; } @@ -684,7 +797,7 @@ Code* StubCache::FindCallInitialize(int argc, Code::Kind kind) { Code::Flags flags = Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc); - Object* result = ProbeCache(flags); + Object* result = ProbeCache(flags)->ToObjectUnchecked(); ASSERT(!result->IsUndefined()); // This might be called during the marking phase of the collector // hence the unchecked cast. @@ -692,60 +805,75 @@ Code* StubCache::FindCallInitialize(int argc, } -Object* StubCache::ComputeCallInitialize(int argc, - InLoopFlag in_loop, - Code::Kind kind) { +MaybeObject* StubCache::ComputeCallInitialize(int argc, + InLoopFlag in_loop, + Code::Kind kind) { Code::Flags flags = Code::ComputeFlags(kind, in_loop, UNINITIALIZED, NORMAL, argc); - Object* probe = ProbeCache(flags); + Object* probe; + { MaybeObject* maybe_probe = ProbeCache(flags); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } if (!probe->IsUndefined()) return probe; StubCompiler compiler; return FillCache(compiler.CompileCallInitialize(flags)); } -Object* StubCache::ComputeCallPreMonomorphic(int argc, - InLoopFlag in_loop, - Code::Kind kind) { +MaybeObject* StubCache::ComputeCallPreMonomorphic(int argc, + InLoopFlag in_loop, + Code::Kind kind) { Code::Flags flags = Code::ComputeFlags(kind, in_loop, PREMONOMORPHIC, NORMAL, argc); - Object* probe = ProbeCache(flags); + Object* probe; + { MaybeObject* maybe_probe = ProbeCache(flags); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } if (!probe->IsUndefined()) return probe; StubCompiler compiler; return FillCache(compiler.CompileCallPreMonomorphic(flags)); } -Object* StubCache::ComputeCallNormal(int argc, - InLoopFlag in_loop, - Code::Kind kind) { +MaybeObject* StubCache::ComputeCallNormal(int argc, + InLoopFlag in_loop, + Code::Kind kind) { Code::Flags flags = Code::ComputeFlags(kind, in_loop, MONOMORPHIC, NORMAL, argc); - Object* probe = ProbeCache(flags); + Object* probe; + { MaybeObject* maybe_probe = ProbeCache(flags); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } if (!probe->IsUndefined()) return probe; StubCompiler compiler; return FillCache(compiler.CompileCallNormal(flags)); } -Object* StubCache::ComputeCallMegamorphic(int argc, - InLoopFlag in_loop, - Code::Kind kind) { +MaybeObject* StubCache::ComputeCallMegamorphic(int argc, + InLoopFlag in_loop, + Code::Kind kind) { Code::Flags flags = Code::ComputeFlags(kind, in_loop, MEGAMORPHIC, NORMAL, argc); - Object* probe = ProbeCache(flags); + Object* probe; + { MaybeObject* maybe_probe = ProbeCache(flags); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } if (!probe->IsUndefined()) return probe; StubCompiler compiler; return FillCache(compiler.CompileCallMegamorphic(flags)); } -Object* StubCache::ComputeCallMiss(int argc, Code::Kind kind) { +MaybeObject* StubCache::ComputeCallMiss(int argc, Code::Kind kind) { // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs // and monomorphic stubs are not mixed up together in the stub cache. Code::Flags flags = Code::ComputeFlags( kind, NOT_IN_LOOP, MONOMORPHIC_PROTOTYPE_FAILURE, NORMAL, argc); - Object* probe = ProbeCache(flags); + Object* probe; + { MaybeObject* maybe_probe = ProbeCache(flags); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } if (!probe->IsUndefined()) return probe; StubCompiler compiler; return FillCache(compiler.CompileCallMiss(flags)); @@ -753,24 +881,31 @@ Object* StubCache::ComputeCallMiss(int argc, Code::Kind kind) { #ifdef ENABLE_DEBUGGER_SUPPORT -Object* StubCache::ComputeCallDebugBreak(int argc, Code::Kind kind) { +MaybeObject* StubCache::ComputeCallDebugBreak(int argc, Code::Kind kind) { Code::Flags flags = Code::ComputeFlags(kind, NOT_IN_LOOP, DEBUG_BREAK, NORMAL, argc); - Object* probe = ProbeCache(flags); + Object* probe; + { MaybeObject* maybe_probe = ProbeCache(flags); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } if (!probe->IsUndefined()) return probe; StubCompiler compiler; return FillCache(compiler.CompileCallDebugBreak(flags)); } -Object* StubCache::ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) { +MaybeObject* StubCache::ComputeCallDebugPrepareStepIn(int argc, + Code::Kind kind) { Code::Flags flags = Code::ComputeFlags(kind, NOT_IN_LOOP, DEBUG_PREPARE_STEP_IN, NORMAL, argc); - Object* probe = ProbeCache(flags); + Object* probe; + { MaybeObject* maybe_probe = ProbeCache(flags); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } if (!probe->IsUndefined()) return probe; StubCompiler compiler; return FillCache(compiler.CompileCallDebugPrepareStepIn(flags)); @@ -794,7 +929,7 @@ void StubCache::Clear() { // StubCompiler implementation. -Object* LoadCallbackProperty(Arguments args) { +MaybeObject* LoadCallbackProperty(Arguments args) { ASSERT(args[0]->IsJSObject()); ASSERT(args[1]->IsJSObject()); AccessorInfo* callback = AccessorInfo::cast(args[2]); @@ -821,7 +956,7 @@ Object* LoadCallbackProperty(Arguments args) { } -Object* StoreCallbackProperty(Arguments args) { +MaybeObject* StoreCallbackProperty(Arguments args) { JSObject* recv = JSObject::cast(args[0]); AccessorInfo* callback = AccessorInfo::cast(args[1]); Address setter_address = v8::ToCData<Address>(callback->setter()); @@ -856,7 +991,7 @@ static const int kAccessorInfoOffsetInInterceptorArgs = 2; * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't * provide any value for the given name. */ -Object* LoadPropertyWithInterceptorOnly(Arguments args) { +MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args) { Handle<String> name_handle = args.at<String>(0); Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>(1); ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2); @@ -890,7 +1025,7 @@ Object* LoadPropertyWithInterceptorOnly(Arguments args) { } -static Object* ThrowReferenceError(String* name) { +static MaybeObject* ThrowReferenceError(String* name) { // If the load is non-contextual, just return the undefined result. // Note that both keyed and non-keyed loads may end up here, so we // can't use either LoadIC or KeyedLoadIC constructors. @@ -908,8 +1043,8 @@ static Object* ThrowReferenceError(String* name) { } -static Object* LoadWithInterceptor(Arguments* args, - PropertyAttributes* attrs) { +static MaybeObject* LoadWithInterceptor(Arguments* args, + PropertyAttributes* attrs) { Handle<String> name_handle = args->at<String>(0); Handle<InterceptorInfo> interceptor_info = args->at<InterceptorInfo>(1); ASSERT(kAccessorInfoOffsetInInterceptorArgs == 2); @@ -940,7 +1075,7 @@ static Object* LoadWithInterceptor(Arguments* args, } } - Object* result = holder_handle->GetPropertyPostInterceptor( + MaybeObject* result = holder_handle->GetPropertyPostInterceptor( *receiver_handle, *name_handle, attrs); @@ -953,10 +1088,12 @@ static Object* LoadWithInterceptor(Arguments* args, * Loads a property with an interceptor performing post interceptor * lookup if interceptor failed. */ -Object* LoadPropertyWithInterceptorForLoad(Arguments args) { +MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args) { PropertyAttributes attr = NONE; - Object* result = LoadWithInterceptor(&args, &attr); - if (result->IsFailure()) return result; + Object* result; + { MaybeObject* maybe_result = LoadWithInterceptor(&args, &attr); + if (!maybe_result->ToObject(&result)) return maybe_result; + } // If the property is present, return it. if (attr != ABSENT) return result; @@ -964,9 +1101,9 @@ Object* LoadPropertyWithInterceptorForLoad(Arguments args) { } -Object* LoadPropertyWithInterceptorForCall(Arguments args) { +MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args) { PropertyAttributes attr; - Object* result = LoadWithInterceptor(&args, &attr); + MaybeObject* result = LoadWithInterceptor(&args, &attr); RETURN_IF_SCHEDULED_EXCEPTION(); // This is call IC. In this case, we simply return the undefined result which // will lead to an exception when trying to invoke the result as a @@ -975,18 +1112,18 @@ Object* LoadPropertyWithInterceptorForCall(Arguments args) { } -Object* StoreInterceptorProperty(Arguments args) { +MaybeObject* StoreInterceptorProperty(Arguments args) { JSObject* recv = JSObject::cast(args[0]); String* name = String::cast(args[1]); Object* value = args[2]; ASSERT(recv->HasNamedInterceptor()); PropertyAttributes attr = NONE; - Object* result = recv->SetPropertyWithInterceptor(name, value, attr); + MaybeObject* result = recv->SetPropertyWithInterceptor(name, value, attr); return result; } -Object* KeyedLoadPropertyWithInterceptor(Arguments args) { +MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args) { JSObject* receiver = JSObject::cast(args[0]); ASSERT(Smi::cast(args[1])->value() >= 0); uint32_t index = Smi::cast(args[1])->value(); @@ -994,7 +1131,7 @@ Object* KeyedLoadPropertyWithInterceptor(Arguments args) { } -Object* StubCompiler::CompileCallInitialize(Code::Flags flags) { +MaybeObject* StubCompiler::CompileCallInitialize(Code::Flags flags) { HandleScope scope; int argc = Code::ExtractArgumentsCountFromFlags(flags); Code::Kind kind = Code::ExtractKindFromFlags(flags); @@ -1003,19 +1140,21 @@ Object* StubCompiler::CompileCallInitialize(Code::Flags flags) { } else { KeyedCallIC::GenerateInitialize(masm(), argc); } - Object* result = GetCodeWithFlags(flags, "CompileCallInitialize"); - if (!result->IsFailure()) { - Counters::call_initialize_stubs.Increment(); - Code* code = Code::cast(result); - USE(code); - PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG), - code, code->arguments_count())); + Object* result; + { MaybeObject* maybe_result = + GetCodeWithFlags(flags, "CompileCallInitialize"); + if (!maybe_result->ToObject(&result)) return maybe_result; } + Counters::call_initialize_stubs.Increment(); + Code* code = Code::cast(result); + USE(code); + PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG), + code, code->arguments_count())); return result; } -Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { +MaybeObject* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { HandleScope scope; int argc = Code::ExtractArgumentsCountFromFlags(flags); // The code of the PreMonomorphic stub is the same as the code @@ -1026,19 +1165,21 @@ Object* StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { } else { KeyedCallIC::GenerateInitialize(masm(), argc); } - Object* result = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); - if (!result->IsFailure()) { - Counters::call_premonomorphic_stubs.Increment(); - Code* code = Code::cast(result); - USE(code); - PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG), - code, code->arguments_count())); + Object* result; + { MaybeObject* maybe_result = + GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); + if (!maybe_result->ToObject(&result)) return maybe_result; } + Counters::call_premonomorphic_stubs.Increment(); + Code* code = Code::cast(result); + USE(code); + PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG), + code, code->arguments_count())); return result; } -Object* StubCompiler::CompileCallNormal(Code::Flags flags) { +MaybeObject* StubCompiler::CompileCallNormal(Code::Flags flags) { HandleScope scope; int argc = Code::ExtractArgumentsCountFromFlags(flags); Code::Kind kind = Code::ExtractKindFromFlags(flags); @@ -1047,19 +1188,20 @@ Object* StubCompiler::CompileCallNormal(Code::Flags flags) { } else { KeyedCallIC::GenerateNormal(masm(), argc); } - Object* result = GetCodeWithFlags(flags, "CompileCallNormal"); - if (!result->IsFailure()) { - Counters::call_normal_stubs.Increment(); - Code* code = Code::cast(result); - USE(code); - PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), - code, code->arguments_count())); + Object* result; + { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallNormal"); + if (!maybe_result->ToObject(&result)) return maybe_result; } + Counters::call_normal_stubs.Increment(); + Code* code = Code::cast(result); + USE(code); + PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), + code, code->arguments_count())); return result; } -Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { +MaybeObject* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { HandleScope scope; int argc = Code::ExtractArgumentsCountFromFlags(flags); Code::Kind kind = Code::ExtractKindFromFlags(flags); @@ -1069,19 +1211,21 @@ Object* StubCompiler::CompileCallMegamorphic(Code::Flags flags) { KeyedCallIC::GenerateMegamorphic(masm(), argc); } - Object* result = GetCodeWithFlags(flags, "CompileCallMegamorphic"); - if (!result->IsFailure()) { - Counters::call_megamorphic_stubs.Increment(); - Code* code = Code::cast(result); - USE(code); - PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), - code, code->arguments_count())); + Object* result; + { MaybeObject* maybe_result = + GetCodeWithFlags(flags, "CompileCallMegamorphic"); + if (!maybe_result->ToObject(&result)) return maybe_result; } + Counters::call_megamorphic_stubs.Increment(); + Code* code = Code::cast(result); + USE(code); + PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), + code, code->arguments_count())); return result; } -Object* StubCompiler::CompileCallMiss(Code::Flags flags) { +MaybeObject* StubCompiler::CompileCallMiss(Code::Flags flags) { HandleScope scope; int argc = Code::ExtractArgumentsCountFromFlags(flags); Code::Kind kind = Code::ExtractKindFromFlags(flags); @@ -1090,36 +1234,39 @@ Object* StubCompiler::CompileCallMiss(Code::Flags flags) { } else { KeyedCallIC::GenerateMiss(masm(), argc); } - Object* result = GetCodeWithFlags(flags, "CompileCallMiss"); - if (!result->IsFailure()) { - Counters::call_megamorphic_stubs.Increment(); - Code* code = Code::cast(result); - USE(code); - PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), - code, code->arguments_count())); + Object* result; + { MaybeObject* maybe_result = GetCodeWithFlags(flags, "CompileCallMiss"); + if (!maybe_result->ToObject(&result)) return maybe_result; } + Counters::call_megamorphic_stubs.Increment(); + Code* code = Code::cast(result); + USE(code); + PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), + code, code->arguments_count())); return result; } #ifdef ENABLE_DEBUGGER_SUPPORT -Object* StubCompiler::CompileCallDebugBreak(Code::Flags flags) { +MaybeObject* StubCompiler::CompileCallDebugBreak(Code::Flags flags) { HandleScope scope; Debug::GenerateCallICDebugBreak(masm()); - Object* result = GetCodeWithFlags(flags, "CompileCallDebugBreak"); - if (!result->IsFailure()) { - Code* code = Code::cast(result); - USE(code); - Code::Kind kind = Code::ExtractKindFromFlags(flags); - USE(kind); - PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG), - code, code->arguments_count())); + Object* result; + { MaybeObject* maybe_result = + GetCodeWithFlags(flags, "CompileCallDebugBreak"); + if (!maybe_result->ToObject(&result)) return maybe_result; } + Code* code = Code::cast(result); + USE(code); + Code::Kind kind = Code::ExtractKindFromFlags(flags); + USE(kind); + PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_DEBUG_BREAK_TAG), + code, code->arguments_count())); return result; } -Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { +MaybeObject* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { HandleScope scope; // Use the same code for the the step in preparations as we do for // the miss case. @@ -1130,39 +1277,42 @@ Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { } else { KeyedCallIC::GenerateMiss(masm(), argc); } - Object* result = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); - if (!result->IsFailure()) { - Code* code = Code::cast(result); - USE(code); - PROFILE(CodeCreateEvent( - CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG), - code, - code->arguments_count())); + Object* result; + { MaybeObject* maybe_result = + GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); + if (!maybe_result->ToObject(&result)) return maybe_result; } + Code* code = Code::cast(result); + USE(code); + PROFILE(CodeCreateEvent( + CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG), + code, + code->arguments_count())); return result; } #endif #undef CALL_LOGGER_TAG -Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) { +MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, + const char* name) { // Check for allocation failures during stub compilation. if (failure_->IsFailure()) return failure_; // Create code object in the heap. CodeDesc desc; masm_.GetCode(&desc); - Object* result = Heap::CreateCode(desc, flags, masm_.CodeObject()); + MaybeObject* result = Heap::CreateCode(desc, flags, masm_.CodeObject()); #ifdef ENABLE_DISASSEMBLER if (FLAG_print_code_stubs && !result->IsFailure()) { - Code::cast(result)->Disassemble(name); + Code::cast(result->ToObjectUnchecked())->Disassemble(name); } #endif return result; } -Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) { +MaybeObject* StubCompiler::GetCodeWithFlags(Code::Flags flags, String* name) { if (FLAG_print_code_stubs && (name != NULL)) { return GetCodeWithFlags(flags, *name->ToCString()); } @@ -1185,43 +1335,49 @@ void StubCompiler::LookupPostInterceptor(JSObject* holder, -Object* LoadStubCompiler::GetCode(PropertyType type, String* name) { +MaybeObject* LoadStubCompiler::GetCode(PropertyType type, String* name) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, type); - Object* result = GetCodeWithFlags(flags, name); + MaybeObject* result = GetCodeWithFlags(flags, name); if (!result->IsFailure()) { - PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(result), name)); + PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, + Code::cast(result->ToObjectUnchecked()), + name)); } return result; } -Object* KeyedLoadStubCompiler::GetCode(PropertyType type, String* name) { +MaybeObject* KeyedLoadStubCompiler::GetCode(PropertyType type, String* name) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, type); - Object* result = GetCodeWithFlags(flags, name); + MaybeObject* result = GetCodeWithFlags(flags, name); if (!result->IsFailure()) { - PROFILE( - CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(result), name)); + PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, + Code::cast(result->ToObjectUnchecked()), + name)); } return result; } -Object* StoreStubCompiler::GetCode(PropertyType type, String* name) { +MaybeObject* StoreStubCompiler::GetCode(PropertyType type, String* name) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, type); - Object* result = GetCodeWithFlags(flags, name); + MaybeObject* result = GetCodeWithFlags(flags, name); if (!result->IsFailure()) { - PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(result), name)); + PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, + Code::cast(result->ToObjectUnchecked()), + name)); } return result; } -Object* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) { +MaybeObject* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) { Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type); - Object* result = GetCodeWithFlags(flags, name); + MaybeObject* result = GetCodeWithFlags(flags, name); if (!result->IsFailure()) { - PROFILE( - CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, Code::cast(result), name)); + PROFILE(CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, + Code::cast(result->ToObjectUnchecked()), + name)); } return result; } @@ -1238,12 +1394,12 @@ CallStubCompiler::CallStubCompiler(int argc, } -Object* CallStubCompiler::CompileCustomCall(int generator_id, - Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* fname) { +MaybeObject* CallStubCompiler::CompileCustomCall(int generator_id, + Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* fname) { ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators); switch (generator_id) { #define CALL_GENERATOR_CASE(ignored1, ignored2, name) \ @@ -1261,7 +1417,7 @@ Object* CallStubCompiler::CompileCustomCall(int generator_id, } -Object* CallStubCompiler::GetCode(PropertyType type, String* name) { +MaybeObject* CallStubCompiler::GetCode(PropertyType type, String* name) { int argc = arguments_.immediate(); Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, type, @@ -1272,7 +1428,7 @@ Object* CallStubCompiler::GetCode(PropertyType type, String* name) { } -Object* CallStubCompiler::GetCode(JSFunction* function) { +MaybeObject* CallStubCompiler::GetCode(JSFunction* function) { String* function_name = NULL; if (function->shared()->name()->IsString()) { function_name = String::cast(function->shared()->name()); @@ -1281,14 +1437,15 @@ Object* CallStubCompiler::GetCode(JSFunction* function) { } -Object* ConstructStubCompiler::GetCode() { +MaybeObject* ConstructStubCompiler::GetCode() { Code::Flags flags = Code::ComputeFlags(Code::STUB); - Object* result = GetCodeWithFlags(flags, "ConstructStub"); - if (!result->IsFailure()) { - Code* code = Code::cast(result); - USE(code); - PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub")); + Object* result; + { MaybeObject* maybe_result = GetCodeWithFlags(flags, "ConstructStub"); + if (!maybe_result->ToObject(&result)) return maybe_result; } + Code* code = Code::cast(result); + USE(code); + PROFILE(CodeCreateEvent(Logger::STUB_TAG, code, "ConstructStub")); return result; } diff --git a/deps/v8/src/stub-cache.h b/deps/v8/src/stub-cache.h index e4a9e955fc..07d21979bf 100644 --- a/deps/v8/src/stub-cache.h +++ b/deps/v8/src/stub-cache.h @@ -56,155 +56,169 @@ class StubCache : public AllStatic { // Computes the right stub matching. Inserts the result in the // cache before returning. This might compile a stub if needed. - MUST_USE_RESULT static Object* ComputeLoadNonexistent(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 MaybeObject* ComputeLoadNonexistent( + String* name, + JSObject* receiver); - MUST_USE_RESULT static Object* ComputeKeyedLoadField(String* name, + MUST_USE_RESULT static MaybeObject* ComputeLoadField(String* name, JSObject* receiver, JSObject* holder, int field_index); - MUST_USE_RESULT static Object* ComputeKeyedLoadCallback( + MUST_USE_RESULT static MaybeObject* ComputeLoadCallback( String* name, JSObject* receiver, JSObject* holder, AccessorInfo* callback); - MUST_USE_RESULT static Object* ComputeKeyedLoadConstant(String* name, + MUST_USE_RESULT static MaybeObject* ComputeLoadConstant(String* name, JSObject* receiver, JSObject* holder, Object* value); - MUST_USE_RESULT static Object* ComputeKeyedLoadInterceptor(String* name, + MUST_USE_RESULT static MaybeObject* ComputeLoadInterceptor(String* name, JSObject* receiver, JSObject* holder); - MUST_USE_RESULT static Object* ComputeKeyedLoadArrayLength(String* name, - JSArray* receiver); + MUST_USE_RESULT static MaybeObject* ComputeLoadNormal(); - MUST_USE_RESULT static Object* ComputeKeyedLoadStringLength(String* name, - String* receiver); - MUST_USE_RESULT static Object* ComputeKeyedLoadFunctionPrototype( + MUST_USE_RESULT static MaybeObject* ComputeLoadGlobal( String* name, - JSFunction* receiver); + JSObject* receiver, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + bool is_dont_delete); + // --- - MUST_USE_RESULT static Object* ComputeStoreField(String* name, - JSObject* receiver, - int field_index, - Map* transition = NULL); + MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadField(String* name, + JSObject* receiver, + JSObject* holder, + 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, - GlobalObject* receiver, - JSGlobalPropertyCell* cell); + MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadArrayLength( + String* name, + JSArray* receiver); - MUST_USE_RESULT static Object* ComputeStoreCallback(String* name, - JSObject* receiver, - AccessorInfo* callback); + MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadStringLength( + String* name, + String* receiver); - MUST_USE_RESULT static Object* ComputeStoreInterceptor(String* name, - JSObject* receiver); + MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadFunctionPrototype( + String* name, + JSFunction* receiver); // --- - MUST_USE_RESULT static Object* ComputeKeyedStoreField(String* name, + MUST_USE_RESULT static MaybeObject* ComputeStoreField(String* name, JSObject* receiver, int field_index, 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, - InLoopFlag in_loop, - Code::Kind, - String* name, - Object* object, - JSObject* holder, - int index); - - MUST_USE_RESULT static Object* ComputeCallConstant(int argc, - InLoopFlag in_loop, - Code::Kind, - String* name, - Object* object, - JSObject* holder, - JSFunction* function); - - MUST_USE_RESULT static Object* ComputeCallNormal(int argc, - InLoopFlag in_loop, - Code::Kind, - String* name, - JSObject* receiver); + MUST_USE_RESULT static MaybeObject* ComputeKeyedStoreField( + String* name, + JSObject* receiver, + int field_index, + Map* transition = NULL); + + // --- + + MUST_USE_RESULT static MaybeObject* ComputeCallField(int argc, + InLoopFlag in_loop, + Code::Kind, + String* name, + Object* object, + JSObject* holder, + int index); + + MUST_USE_RESULT static MaybeObject* ComputeCallConstant(int argc, + InLoopFlag in_loop, + Code::Kind, + String* name, + 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, String* name, - Object* object, - JSObject* holder); + JSObject* receiver); - MUST_USE_RESULT static Object* ComputeCallGlobal(int argc, - InLoopFlag in_loop, - Code::Kind, - String* name, - JSObject* receiver, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function); + MUST_USE_RESULT static MaybeObject* ComputeCallInterceptor(int argc, + Code::Kind, + String* name, + Object* object, + JSObject* holder); - // --- + 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, - InLoopFlag in_loop, - Code::Kind kind); + MUST_USE_RESULT static MaybeObject* ComputeCallInitialize(int argc, + InLoopFlag in_loop, + Code::Kind kind); - MUST_USE_RESULT static Object* ComputeCallNormal(int argc, - InLoopFlag in_loop, - Code::Kind kind); + MUST_USE_RESULT static MaybeObject* ComputeCallPreMonomorphic( + int argc, + 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, 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(). MUST_USE_RESULT static Code* FindCallInitialize(int argc, @@ -212,11 +226,12 @@ class StubCache : public AllStatic { Code::Kind kind); #ifdef ENABLE_DEBUGGER_SUPPORT - MUST_USE_RESULT static Object* ComputeCallDebugBreak(int argc, - Code::Kind kind); + MUST_USE_RESULT static MaybeObject* ComputeCallDebugBreak(int argc, + Code::Kind kind); - MUST_USE_RESULT static Object* ComputeCallDebugPrepareStepIn(int argc, - Code::Kind kind); + MUST_USE_RESULT static MaybeObject* ComputeCallDebugPrepareStepIn( + int argc, + Code::Kind kind); #endif // Update cache for entry hash(name, map). @@ -329,17 +344,17 @@ class SCTableReference { // Support functions for IC stubs for callbacks. -Object* LoadCallbackProperty(Arguments args); -Object* StoreCallbackProperty(Arguments args); +MaybeObject* LoadCallbackProperty(Arguments args); +MaybeObject* StoreCallbackProperty(Arguments args); // Support functions for IC stubs for interceptors. -Object* LoadPropertyWithInterceptorOnly(Arguments args); -Object* LoadPropertyWithInterceptorForLoad(Arguments args); -Object* LoadPropertyWithInterceptorForCall(Arguments args); -Object* StoreInterceptorProperty(Arguments args); -Object* CallInterceptorProperty(Arguments args); -Object* KeyedLoadPropertyWithInterceptor(Arguments args); +MaybeObject* LoadPropertyWithInterceptorOnly(Arguments args); +MaybeObject* LoadPropertyWithInterceptorForLoad(Arguments args); +MaybeObject* LoadPropertyWithInterceptorForCall(Arguments args); +MaybeObject* StoreInterceptorProperty(Arguments args); +MaybeObject* CallInterceptorProperty(Arguments args); +MaybeObject* KeyedLoadPropertyWithInterceptor(Arguments args); // The stub compiler compiles stubs for the stub cache. @@ -354,14 +369,14 @@ class StubCompiler BASE_EMBEDDED { StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { } - Object* CompileCallInitialize(Code::Flags flags); - Object* CompileCallPreMonomorphic(Code::Flags flags); - Object* CompileCallNormal(Code::Flags flags); - Object* CompileCallMegamorphic(Code::Flags flags); - Object* CompileCallMiss(Code::Flags flags); + MUST_USE_RESULT MaybeObject* CompileCallInitialize(Code::Flags flags); + MUST_USE_RESULT MaybeObject* CompileCallPreMonomorphic(Code::Flags flags); + MUST_USE_RESULT MaybeObject* CompileCallNormal(Code::Flags flags); + MUST_USE_RESULT MaybeObject* CompileCallMegamorphic(Code::Flags flags); + MUST_USE_RESULT MaybeObject* CompileCallMiss(Code::Flags flags); #ifdef ENABLE_DEBUGGER_SUPPORT - Object* CompileCallDebugBreak(Code::Flags flags); - Object* CompileCallDebugPrepareStepIn(Code::Flags flags); + MUST_USE_RESULT MaybeObject* CompileCallDebugBreak(Code::Flags flags); + MUST_USE_RESULT MaybeObject* CompileCallDebugPrepareStepIn(Code::Flags flags); #endif // Static functions for generating parts of stubs. @@ -451,8 +466,8 @@ class StubCompiler BASE_EMBEDDED { Label* miss); protected: - Object* GetCodeWithFlags(Code::Flags flags, const char* name); - Object* GetCodeWithFlags(Code::Flags flags, String* name); + MaybeObject* GetCodeWithFlags(Code::Flags flags, const char* name); + MaybeObject* GetCodeWithFlags(Code::Flags flags, String* name); MacroAssembler* masm() { return &masm_; } void set_failure(Failure* failure) { failure_ = failure; } @@ -513,99 +528,100 @@ class StubCompiler BASE_EMBEDDED { class LoadStubCompiler: public StubCompiler { public: - Object* CompileLoadNonexistent(String* name, - JSObject* object, - JSObject* last); - - Object* CompileLoadField(JSObject* object, - JSObject* holder, - int index, - String* name); - - Object* CompileLoadCallback(String* name, - JSObject* object, - JSObject* holder, - AccessorInfo* callback); - - Object* CompileLoadConstant(JSObject* object, - JSObject* holder, - Object* value, - String* name); - - Object* CompileLoadInterceptor(JSObject* object, - JSObject* holder, - String* name); - - Object* CompileLoadGlobal(JSObject* object, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - String* name, - bool is_dont_delete); + MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name, + JSObject* object, + JSObject* last); + + MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object, + JSObject* holder, + int index, + String* name); + + MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name, + JSObject* object, + JSObject* holder, + AccessorInfo* callback); + + MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object, + JSObject* holder, + Object* value, + String* name); + + MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object, + JSObject* holder, + String* name); + + MUST_USE_RESULT MaybeObject* CompileLoadGlobal(JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + String* name, + bool is_dont_delete); private: - Object* GetCode(PropertyType type, String* name); + MaybeObject* GetCode(PropertyType type, String* name); }; class KeyedLoadStubCompiler: public StubCompiler { public: - Object* CompileLoadField(String* name, - JSObject* object, - JSObject* holder, - int index); + MUST_USE_RESULT MaybeObject* CompileLoadField(String* name, + JSObject* object, + JSObject* holder, + int index); - Object* CompileLoadCallback(String* name, - JSObject* object, - JSObject* holder, - AccessorInfo* callback); + MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name, + JSObject* object, + JSObject* holder, + AccessorInfo* callback); - Object* CompileLoadConstant(String* name, - JSObject* object, - JSObject* holder, - Object* value); + MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name, + JSObject* object, + JSObject* holder, + Object* value); - Object* CompileLoadInterceptor(JSObject* object, - JSObject* holder, - String* name); + MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object, + JSObject* holder, + String* name); - Object* CompileLoadArrayLength(String* name); - Object* CompileLoadStringLength(String* name); - Object* CompileLoadFunctionPrototype(String* name); + MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name); + MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name); + MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name); private: - Object* GetCode(PropertyType type, String* name); + MaybeObject* GetCode(PropertyType type, String* name); }; class StoreStubCompiler: public StubCompiler { public: - Object* CompileStoreField(JSObject* object, - int index, - Map* transition, - String* name); - Object* CompileStoreCallback(JSObject* object, - AccessorInfo* callbacks, - String* name); - Object* CompileStoreInterceptor(JSObject* object, String* name); - Object* CompileStoreGlobal(GlobalObject* object, - JSGlobalPropertyCell* holder, - String* name); + MUST_USE_RESULT MaybeObject* CompileStoreField(JSObject* object, + int index, + Map* transition, + String* name); + MUST_USE_RESULT MaybeObject* CompileStoreCallback(JSObject* object, + AccessorInfo* callbacks, + String* name); + MUST_USE_RESULT MaybeObject* CompileStoreInterceptor(JSObject* object, + String* name); + MUST_USE_RESULT MaybeObject* CompileStoreGlobal(GlobalObject* object, + JSGlobalPropertyCell* holder, + String* name); private: - Object* GetCode(PropertyType type, String* name); + MUST_USE_RESULT MaybeObject* GetCode(PropertyType type, String* name); }; class KeyedStoreStubCompiler: public StubCompiler { public: - Object* CompileStoreField(JSObject* object, - int index, - Map* transition, - String* name); + MaybeObject* CompileStoreField(JSObject* object, + int index, + Map* transition, + String* name); private: - Object* GetCode(PropertyType type, String* name); + MaybeObject* GetCode(PropertyType type, String* name); }; @@ -645,39 +661,39 @@ class CallStubCompiler: public StubCompiler { Code::Kind kind, InlineCacheHolderFlag cache_holder); - Object* CompileCallField(JSObject* object, - JSObject* holder, - int index, - String* name); - Object* CompileCallConstant(Object* object, - JSObject* holder, - JSFunction* function, - String* name, - CheckType check); - Object* CompileCallInterceptor(JSObject* object, - JSObject* holder, - String* name); - Object* CompileCallGlobal(JSObject* object, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name); + MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object, + JSObject* holder, + int index, + String* name); + MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object, + JSObject* holder, + JSFunction* function, + String* name, + CheckType check); + MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object, + JSObject* holder, + String* name); + MUST_USE_RESULT MaybeObject* CompileCallGlobal(JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name); // Compiles a custom call constant/global IC using the generator // with given id. For constant calls cell is NULL. - Object* CompileCustomCall(int generator_id, - Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name); - -#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \ - Object* Compile##name##Call(Object* object, \ - JSObject* holder, \ - JSGlobalPropertyCell* cell, \ - JSFunction* function, \ - String* fname); + MUST_USE_RESULT MaybeObject* CompileCustomCall(int generator_id, + Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name); + +#define DECLARE_CALL_GENERATOR(ignored1, ignored2, name) \ + MUST_USE_RESULT MaybeObject* Compile##name##Call(Object* object, \ + JSObject* holder, \ + JSGlobalPropertyCell* cell, \ + JSFunction* function, \ + String* fname); CUSTOM_CALL_IC_GENERATORS(DECLARE_CALL_GENERATOR) #undef DECLARE_CALL_GENERATOR @@ -689,11 +705,11 @@ class CallStubCompiler: public StubCompiler { 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 // 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); @@ -710,7 +726,7 @@ class CallStubCompiler: public StubCompiler { // Generates a jump to CallIC miss stub. Returns Failure if the jump cannot // be generated. - Object* GenerateMissBranch(); + MUST_USE_RESULT MaybeObject* GenerateMissBranch(); }; @@ -718,10 +734,10 @@ class ConstructStubCompiler: public StubCompiler { public: explicit ConstructStubCompiler() {} - Object* CompileConstructStub(SharedFunctionInfo* shared); + MUST_USE_RESULT MaybeObject* CompileConstructStub(SharedFunctionInfo* shared); private: - Object* GetCode(); + MaybeObject* GetCode(); }; diff --git a/deps/v8/src/top.cc b/deps/v8/src/top.cc index 9ce6542964..1f0d159fe8 100644 --- a/deps/v8/src/top.cc +++ b/deps/v8/src/top.cc @@ -66,6 +66,13 @@ v8::TryCatch* ThreadLocalTop::TryCatchHandler() { void ThreadLocalTop::Initialize() { c_entry_fp_ = 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 js_entry_sp_ = 0; #endif @@ -107,11 +114,22 @@ void Top::IterateThread(ThreadVisitor* v, char* t) { 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(BitCast<Object**>(&(thread->pending_message_script_))); 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(); 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_pending_exception(exception); return Failure::Exception(); @@ -710,8 +728,8 @@ void Top::ScheduleThrow(Object* exception) { } -Object* Top::PromoteScheduledException() { - Object* thrown = scheduled_exception(); +Failure* Top::PromoteScheduledException() { + MaybeObject* thrown = scheduled_exception(); clear_scheduled_exception(); // Re-throw the exception to avoid getting repeated error reporting. 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, const char* message) { ASSERT(!has_pending_exception()); 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. bool is_caught_externally = false; bool is_out_of_memory = exception == Failure::OutOfMemoryException(); bool is_termination_exception = exception == Heap::termination_exception(); 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 = ShouldReturnException(&is_caught_externally, catchable_by_javascript); 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_options); } + ASSERT(is_object); // Can't use the handle unless there's a real object. message_obj = MessageHandler::MakeMessageObject("uncaught_exception", location, HandleVector<Object>(&exception_handle, 1), stack_trace, stack_trace_object); @@ -867,7 +890,13 @@ void Top::DoThrow(Object* exception, // NOTE: Notifying the debugger or generating the message // may have caused new exceptions. For now, we just ignore // 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(); } } 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; if (external_caught) { thread_local_.TryCatchHandler()->can_continue_ = true; @@ -983,13 +1015,13 @@ void Top::SetCaptureStackTraceForUncaughtExceptions( bool Top::is_out_of_memory() { if (has_pending_exception()) { - Object* e = pending_exception(); + MaybeObject* e = pending_exception(); if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { return true; } } if (has_scheduled_exception()) { - Object* e = scheduled_exception(); + MaybeObject* e = scheduled_exception(); if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { return true; } @@ -1035,6 +1067,15 @@ char* Top::ArchiveThread(char* to) { char* Top::RestoreThread(char* from) { 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_); } diff --git a/deps/v8/src/top.h b/deps/v8/src/top.h index a2ba3ddde6..e97289f359 100644 --- a/deps/v8/src/top.h +++ b/deps/v8/src/top.h @@ -29,6 +29,7 @@ #define V8_TOP_H_ #include "frames-inl.h" +#include "simulator.h" namespace v8 { namespace internal { @@ -84,7 +85,7 @@ class ThreadLocalTop BASE_EMBEDDED { // lookups. Context* context_; int thread_id_; - Object* pending_exception_; + MaybeObject* pending_exception_; bool has_pending_message_; const char* pending_message_; Object* pending_message_obj_; @@ -94,7 +95,7 @@ class ThreadLocalTop BASE_EMBEDDED { // Use a separate value for scheduled exceptions to preserve the // invariants that hold about pending_exception. We may want to // unify them later. - Object* scheduled_exception_; + MaybeObject* scheduled_exception_; bool external_caught_exception_; SaveContext* save_context_; 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 handler_; // try-blocks are chained through the stack +#ifdef USE_SIMULATOR + assembler::arm::Simulator* simulator_; +#endif // USE_SIMULATOR + #ifdef ENABLE_LOGGING_AND_PROFILING Address js_entry_sp_; // the stack pointer of the bottom js entry frame #endif @@ -165,21 +170,21 @@ class Top { static void set_thread_id(int id) { thread_local_.thread_id_ = id; } // Interface to pending exception. - static Object* pending_exception() { + static MaybeObject* pending_exception() { ASSERT(has_pending_exception()); return thread_local_.pending_exception_; } static bool 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; } static void clear_pending_exception() { thread_local_.pending_exception_ = Heap::the_hole_value(); } - static Object** pending_exception_address() { + static MaybeObject** pending_exception_address() { return &thread_local_.pending_exception_; } static bool has_pending_exception() { @@ -208,11 +213,11 @@ class Top { return &thread_local_.external_caught_exception_; } - static Object** scheduled_exception_address() { + static MaybeObject** scheduled_exception_address() { return &thread_local_.scheduled_exception_; } - static Object* scheduled_exception() { + static MaybeObject* scheduled_exception() { ASSERT(has_scheduled_exception()); return thread_local_.scheduled_exception_; } @@ -302,14 +307,15 @@ class Top { // Re-throw an exception. This involves no error reporting since // error reporting was handled when the exception was thrown // originally. - static Failure* ReThrow(Object* exception, MessageLocation* location = NULL); + static Failure* ReThrow(MaybeObject* exception, + MessageLocation* location = NULL); static void ScheduleThrow(Object* exception); static void ReportPendingMessages(); static Failure* ThrowIllegalOperation(); // Promote a scheduled exception to pending. Asserts has_scheduled_exception. - static Object* PromoteScheduledException(); - static void DoThrow(Object* exception, + static Failure* PromoteScheduledException(); + static void DoThrow(MaybeObject* exception, MessageLocation* location, const char* message); static bool ShouldReturnException(bool* is_caught_externally, diff --git a/deps/v8/src/v8.cc b/deps/v8/src/v8.cc index b30564a391..0623400abb 100644 --- a/deps/v8/src/v8.cc +++ b/deps/v8/src/v8.cc @@ -68,8 +68,12 @@ bool V8::Initialize(Deserializer* des) { OS::Setup(); // 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(); +#elif defined(V8_TARGET_ARCH_MIPS) + ::assembler::mips::Simulator::Initialize(); +#endif #endif { // NOLINT diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index 6d98b044f5..4017ae5e3d 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -34,7 +34,7 @@ // cannot be changed without changing the SCons build script. #define MAJOR_VERSION 2 #define MINOR_VERSION 5 -#define BUILD_NUMBER 1 +#define BUILD_NUMBER 2 #define PATCH_LEVEL 0 #define CANDIDATE_VERSION false diff --git a/deps/v8/src/x64/assembler-x64.cc b/deps/v8/src/x64/assembler-x64.cc index 6e29b7a5a6..bf5ee5bbb7 100644 --- a/deps/v8/src/x64/assembler-x64.cc +++ b/deps/v8/src/x64/assembler-x64.cc @@ -118,9 +118,11 @@ void CpuFeatures::Probe() { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>()); + MaybeObject* maybe_code = Heap::CreateCode(desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>()); + Object* code; + if (!maybe_code->ToObject(&code)) return; if (!code->IsCode()) return; PROFILE(CodeCreateEvent(Logger::BUILTIN_TAG, Code::cast(code), "CpuFeatures::Probe")); diff --git a/deps/v8/src/x64/code-stubs-x64.cc b/deps/v8/src/x64/code-stubs-x64.cc index 2d87667bae..c179769b8a 100644 --- a/deps/v8/src/x64/code-stubs-x64.cc +++ b/deps/v8/src/x64/code-stubs-x64.cc @@ -2484,11 +2484,7 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { void ApiGetterEntryStub::Generate(MacroAssembler* masm) { - Label empty_result; - Label prologue; - Label promote_scheduled_exception; - __ EnterApiExitFrame(kStackSpace, 0); - ASSERT_EQ(kArgc, 4); + __ PrepareCallApiFunction(kStackSpace); #ifdef _WIN64 // All the parameters should be set up by a caller. #else @@ -2497,35 +2493,7 @@ void ApiGetterEntryStub::Generate(MacroAssembler* masm) { // Second parameter register rdi should be set with pointer to AccessorInfo // by a caller. #endif - // Call the api function! - __ 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); + __ CallApiFunctionAndReturn(fun()); } diff --git a/deps/v8/src/x64/macro-assembler-x64.cc b/deps/v8/src/x64/macro-assembler-x64.cc index 2c946f56b9..293d8a5633 100644 --- a/deps/v8/src/x64/macro-assembler-x64.cc +++ b/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. - Object* result = stub->TryGetCode(); + MaybeObject* result = stub->TryGetCode(); if (!result->IsFailure()) { - call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); + call(Handle<Code>(Code::cast(result->ToObjectUnchecked())), + RelocInfo::CODE_TARGET); } 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. - Object* result = stub->TryGetCode(); + MaybeObject* result = stub->TryGetCode(); if (!result->IsFailure()) { - jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); + jmp(Handle<Code>(Code::cast(result->ToObjectUnchecked())), + RelocInfo::CODE_TARGET); } return result; } @@ -379,8 +381,8 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { } -Object* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, - int num_arguments) { +MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, + int 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, - int num_arguments) { +MaybeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f, + int num_arguments) { if (f->nargs >= 0 && f->nargs != num_arguments) { IllegalOperation(num_arguments); // 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) { - ExternalReference extensions_address = - 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)); +void MacroAssembler::PrepareCallApiFunction(int stack_space) { + EnterApiExitFrame(stack_space, 0); } -Object* MacroAssembler::PopHandleScopeHelper(Register saved, - Register scratch, - bool gc_allowed) { - ExternalReference extensions_address = - 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); - - Object* result = NULL; +void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function) { + Label empty_result; + Label prologue; + Label promote_scheduled_exception; + Label delete_allocated_handles; + Label leave_exit_frame; 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) { - PopHandleScopeHelper(saved, scratch, true); -} + 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); -Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { - return PopHandleScopeHelper(saved, scratch, false); + // HandleScope limit has changed. Delete allocated extensions. + 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, Label* gc_required, 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)); // Load address of new object into result. @@ -1935,6 +1964,19 @@ void MacroAssembler::AllocateInNewSpace(int header_size, Register scratch, Label* gc_required, 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)); // Load address of new object into result. @@ -1964,6 +2006,21 @@ void MacroAssembler::AllocateInNewSpace(Register object_size, Register scratch, Label* gc_required, 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. LoadAllocationTopHelper(result, result_end, scratch, flags); diff --git a/deps/v8/src/x64/macro-assembler-x64.h b/deps/v8/src/x64/macro-assembler-x64.h index cb9106751c..2f6e956165 100644 --- a/deps/v8/src/x64/macro-assembler-x64.h +++ b/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 // the code if necessary. Do not perform a GC but instead return a retry // after GC failure. - Object* TryCallStub(CodeStub* stub); + MUST_USE_RESULT MaybeObject* TryCallStub(CodeStub* stub); // Tail call a code stub (jump). 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 // generate the code if necessary. Do not perform a GC but instead return // 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. void StubReturn(int argc); @@ -792,13 +792,15 @@ class MacroAssembler: public Assembler { // Call a runtime function, returning the CodeStub object called. // Try to generate the stub code if necessary. Do not perform a GC // 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. void CallRuntime(Runtime::FunctionId id, int num_arguments); // 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. void CallExternalReference(const ExternalReference& ext, @@ -816,19 +818,18 @@ class MacroAssembler: public Assembler { int num_arguments, 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. 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. // 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. diff --git a/deps/v8/src/x64/regexp-macro-assembler-x64.cc b/deps/v8/src/x64/regexp-macro-assembler-x64.cc index 47c19c7e1f..2cf85f1165 100644 --- a/deps/v8/src/x64/regexp-macro-assembler-x64.cc +++ b/deps/v8/src/x64/regexp-macro-assembler-x64.cc @@ -1169,7 +1169,7 @@ int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address, ASSERT(*return_address <= 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 intptr_t delta = *code_handle - re_code; diff --git a/deps/v8/src/x64/simulator-x64.h b/deps/v8/src/x64/simulator-x64.h index a0fc3cbf4f..e607c8b87d 100644 --- a/deps/v8/src/x64/simulator-x64.h +++ b/deps/v8/src/x64/simulator-x64.h @@ -30,11 +30,22 @@ #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. // TODO(X64): Don't pass p0, since it isn't used? #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 // 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() { } }; -// Call the generated regexp code directly. The entry function pointer should -// 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) +} } // namespace v8::internal #endif // V8_X64_SIMULATOR_X64_H_ diff --git a/deps/v8/src/x64/stub-cache-x64.cc b/deps/v8/src/x64/stub-cache-x64.cc index eb48da9a9c..3891e1d5a3 100644 --- a/deps/v8/src/x64/stub-cache-x64.cc +++ b/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 // the property cell at compilation time if no cell exists for the // property. -static Object* GenerateCheckPropertyCell(MacroAssembler* masm, - GlobalObject* global, - String* name, - Register scratch, - Label* miss) { - Object* probe = global->EnsurePropertyCell(name); - if (probe->IsFailure()) return probe; +MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( + MacroAssembler* masm, + GlobalObject* global, + String* name, + Register scratch, + Label* miss) { + Object* probe; + { MaybeObject* maybe_probe = global->EnsurePropertyCell(name); + if (!maybe_probe->ToObject(&probe)) return maybe_probe; + } JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); ASSERT(cell->value()->IsTheHole()); __ Move(scratch, Handle<Object>(cell)); @@ -879,19 +882,23 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, } -Object* CallStubCompiler::GenerateMissBranch() { - Object* obj = StubCache::ComputeCallMiss(arguments().immediate(), kind_); - if (obj->IsFailure()) return obj; +MaybeObject* CallStubCompiler::GenerateMissBranch() { + Object* 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); return obj; } -Object* CallStubCompiler::CompileCallConstant(Object* object, - JSObject* holder, - JSFunction* function, - String* name, - StubCompiler::CheckType check) { +MaybeObject* CallStubCompiler::CompileCallConstant( + Object* object, + JSObject* holder, + JSFunction* function, + String* name, + StubCompiler::CheckType check) { // ----------- S t a t e ------------- // rcx : function name // rsp[0] : return address @@ -905,8 +912,10 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, SharedFunctionInfo* function_info = function->shared(); if (function_info->HasCustomCallGenerator()) { const int id = function_info->custom_call_generator_id(); - Object* result = CompileCustomCall( + MaybeObject* maybe_result = CompileCustomCall( id, object, holder, NULL, function, name); + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // undefined means bail out to regular compiler. if (!result->IsUndefined()) return result; } @@ -1034,18 +1043,20 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, // Handle call cache miss. __ bind(&miss_in_smi_check); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileCallField(JSObject* object, - JSObject* holder, - int index, - String* name) { +MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, + JSObject* holder, + int index, + String* name) { // ----------- S t a t e ------------- // rcx : function name // rsp[0] : return address @@ -1089,19 +1100,21 @@ Object* CallStubCompiler::CompileCallField(JSObject* object, // Handle call cache miss. __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(FIELD, name); } -Object* CallStubCompiler::CompileArrayPushCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- rcx : name // -- rsp[0] : return address @@ -1191,6 +1204,10 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, __ ret((argc + 1) * kPointerSize); __ bind(&attempt_to_grow_elements); + if (!FLAG_inline_new) { + __ jmp(&call_builtin); + } + ExternalReference new_space_allocation_top = ExternalReference::new_space_allocation_top_address(); ExternalReference new_space_allocation_limit = @@ -1247,19 +1264,21 @@ Object* CallStubCompiler::CompileArrayPushCall(Object* object, } __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileArrayPopCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- rcx : name // -- rsp[0] : return address @@ -1329,19 +1348,22 @@ Object* CallStubCompiler::CompileArrayPopCall(Object* object, 1); __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileStringCharAtCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileStringCharAtCall( + Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- rcx : function name // -- rsp[0] : return address @@ -1401,15 +1423,17 @@ Object* CallStubCompiler::CompileStringCharAtCall(Object* object, __ ret((argc + 1) * kPointerSize); __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileStringCharCodeAtCall( +MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall( Object* object, JSObject* holder, JSGlobalPropertyCell* cell, @@ -1471,15 +1495,17 @@ Object* CallStubCompiler::CompileStringCharCodeAtCall( __ ret((argc + 1) * kPointerSize); __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(function); } -Object* CallStubCompiler::CompileStringFromCharCodeCall( +MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall( Object* object, JSObject* holder, JSGlobalPropertyCell* cell, @@ -1540,29 +1566,31 @@ Object* CallStubCompiler::CompileStringFromCharCodeCall( __ bind(&miss); // rcx: function name. - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } -Object* CallStubCompiler::CompileMathFloorCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // TODO(872): implement this. return Heap::undefined_value(); } -Object* CallStubCompiler::CompileMathAbsCall(Object* object, - JSObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, + JSObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // -- rcx : function name // -- rsp[0] : return address @@ -1653,17 +1681,19 @@ Object* CallStubCompiler::CompileMathAbsCall(Object* object, __ bind(&miss); // rcx: function name. - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); } -Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, - JSObject* holder, - String* name) { +MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object, + JSObject* holder, + String* name) { // ----------- S t a t e ------------- // rcx : function name // rsp[0] : return address @@ -1719,19 +1749,21 @@ Object* CallStubCompiler::CompileCallInterceptor(JSObject* object, // Handle load cache miss. __ bind(&miss); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(INTERCEPTOR, name); } -Object* CallStubCompiler::CompileCallGlobal(JSObject* object, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - JSFunction* function, - String* name) { +MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + JSFunction* function, + String* name) { // ----------- S t a t e ------------- // rcx : function name // rsp[0] : return address @@ -1745,8 +1777,10 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, SharedFunctionInfo* function_info = function->shared(); if (function_info->HasCustomCallGenerator()) { const int id = function_info->custom_call_generator_id(); - Object* result = CompileCustomCall( + MaybeObject* maybe_result = CompileCustomCall( id, object, holder, cell, function, name); + Object* result; + if (!maybe_result->ToObject(&result)) return maybe_result; // undefined means bail out to regular compiler. if (!result->IsUndefined()) return result; } @@ -1782,18 +1816,20 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, // Handle call cache miss. __ bind(&miss); __ IncrementCounter(&Counters::call_global_inline_miss, 1); - Object* obj = GenerateMissBranch(); - if (obj->IsFailure()) return obj; + Object* obj; + { MaybeObject* maybe_obj = GenerateMissBranch(); + if (!maybe_obj->ToObject(&obj)) return maybe_obj; + } // Return the generated code. return GetCode(NORMAL, name); } -Object* LoadStubCompiler::CompileLoadCallback(String* name, - JSObject* object, - JSObject* holder, - AccessorInfo* callback) { +MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name, + JSObject* object, + JSObject* holder, + AccessorInfo* callback) { // ----------- S t a t e ------------- // -- rax : receiver // -- rcx : name @@ -1817,10 +1853,10 @@ Object* LoadStubCompiler::CompileLoadCallback(String* name, } -Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, - JSObject* holder, - Object* value, - String* name) { +MaybeObject* LoadStubCompiler::CompileLoadConstant(JSObject* object, + JSObject* holder, + Object* value, + String* name) { // ----------- S t a t e ------------- // -- rax : receiver // -- rcx : name @@ -1837,9 +1873,9 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, } -Object* LoadStubCompiler::CompileLoadNonexistent(String* name, - JSObject* object, - JSObject* last) { +MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, + JSObject* object, + JSObject* last) { // ----------- S t a t e ------------- // -- rax : receiver // -- rcx : name @@ -1858,11 +1894,11 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name, // If the last object in the prototype chain is a global object, // check that the global property cell is empty. if (last->IsGlobalObject()) { - Object* cell = GenerateCheckPropertyCell(masm(), - GlobalObject::cast(last), - name, - rdx, - &miss); + MaybeObject* cell = GenerateCheckPropertyCell(masm(), + GlobalObject::cast(last), + name, + rdx, + &miss); if (cell->IsFailure()) { miss.Unuse(); return cell; @@ -1882,10 +1918,10 @@ Object* LoadStubCompiler::CompileLoadNonexistent(String* name, } -Object* LoadStubCompiler::CompileLoadField(JSObject* object, - JSObject* holder, - int index, - String* name) { +MaybeObject* LoadStubCompiler::CompileLoadField(JSObject* object, + JSObject* holder, + int index, + String* name) { // ----------- S t a t e ------------- // -- rax : receiver // -- rcx : name @@ -1902,9 +1938,9 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object, } -Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, - JSObject* holder, - String* name) { +MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, + JSObject* holder, + String* name) { // ----------- S t a t e ------------- // -- rax : receiver // -- rcx : name @@ -1936,11 +1972,11 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, } -Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, - GlobalObject* holder, - JSGlobalPropertyCell* cell, - String* name, - bool is_dont_delete) { +MaybeObject* LoadStubCompiler::CompileLoadGlobal(JSObject* object, + GlobalObject* holder, + JSGlobalPropertyCell* cell, + String* name, + bool is_dont_delete) { // ----------- S t a t e ------------- // -- rax : receiver // -- rcx : name @@ -1984,10 +2020,11 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, } -Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, - JSObject* receiver, - JSObject* holder, - AccessorInfo* callback) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback( + String* name, + JSObject* receiver, + JSObject* holder, + AccessorInfo* callback) { // ----------- S t a t e ------------- // -- rax : key // -- 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 ------------- // -- rax : key // -- rdx : receiver @@ -2042,10 +2079,10 @@ Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) { } -Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, - JSObject* receiver, - JSObject* holder, - Object* value) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadConstant(String* name, + JSObject* receiver, + JSObject* holder, + Object* value) { // ----------- S t a t e ------------- // -- rax : key // -- 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 ------------- // -- rax : key // -- rdx : receiver @@ -2094,9 +2131,9 @@ Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { } -Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, - JSObject* holder, - String* name) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, + JSObject* holder, + String* name) { // ----------- S t a t e ------------- // -- rax : key // -- 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 ------------- // -- rax : key // -- rdx : receiver @@ -2155,9 +2192,9 @@ Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { } -Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, - AccessorInfo* callback, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreCallback(JSObject* object, + AccessorInfo* callback, + String* name) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : name @@ -2205,10 +2242,10 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object, } -Object* StoreStubCompiler::CompileStoreField(JSObject* object, - int index, - Map* transition, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreField(JSObject* object, + int index, + Map* transition, + String* name) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : name @@ -2235,8 +2272,8 @@ Object* StoreStubCompiler::CompileStoreField(JSObject* object, } -Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, + String* name) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : name @@ -2283,9 +2320,9 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver, } -Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, - JSGlobalPropertyCell* cell, - String* name) { +MaybeObject* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, + JSGlobalPropertyCell* cell, + String* name) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : name @@ -2318,10 +2355,10 @@ Object* StoreStubCompiler::CompileStoreGlobal(GlobalObject* object, } -Object* KeyedLoadStubCompiler::CompileLoadField(String* name, - JSObject* receiver, - JSObject* holder, - int index) { +MaybeObject* KeyedLoadStubCompiler::CompileLoadField(String* name, + JSObject* receiver, + JSObject* holder, + int index) { // ----------- S t a t e ------------- // -- rax : key // -- rdx : receiver @@ -2346,10 +2383,10 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name, } -Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, - int index, - Map* transition, - String* name) { +MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, + int index, + Map* transition, + String* name) { // ----------- S t a t e ------------- // -- rax : value // -- rcx : key @@ -2543,7 +2580,6 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, Handle<AccessorInfo> callback_handle(callback); __ EnterInternalFrame(); - __ PushHandleScope(scratch2); // Push the stack address where the list of arguments ends. __ movq(scratch2, rsp); __ subq(scratch2, Immediate(2 * kPointerSize)); @@ -2588,7 +2624,7 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, // already generated). Do not allow the assembler to perform a // garbage collection but instead return the allocation failure // object. - Object* result = masm()->TryCallStub(&stub); + MaybeObject* result = masm()->TryCallStub(&stub); if (result->IsFailure()) { *failure = Failure::cast(result); return false; @@ -2597,17 +2633,6 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object, // Discard allocated slot. __ addq(rsp, Immediate(kPointerSize)); #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(); __ ret(0); @@ -2655,12 +2680,12 @@ Register StubCompiler::CheckPrototypes(JSObject* object, !current->IsJSGlobalObject() && !current->IsJSGlobalProxy()) { if (!name->IsSymbol()) { - Object* lookup_result = Heap::LookupSymbol(name); + MaybeObject* lookup_result = Heap::LookupSymbol(name); if (lookup_result->IsFailure()) { set_failure(Failure::cast(lookup_result)); return reg; } else { - name = String::cast(lookup_result); + name = String::cast(lookup_result->ToObjectUnchecked()); } } ASSERT(current->property_dictionary()->FindEntry(name) == @@ -2742,11 +2767,11 @@ Register StubCompiler::CheckPrototypes(JSObject* object, current = object; while (current != holder) { if (current->IsGlobalObject()) { - Object* cell = GenerateCheckPropertyCell(masm(), - GlobalObject::cast(current), - name, - scratch1, - miss); + MaybeObject* cell = GenerateCheckPropertyCell(masm(), + GlobalObject::cast(current), + name, + scratch1, + miss); if (cell->IsFailure()) { set_failure(Failure::cast(cell)); return reg; @@ -2808,7 +2833,7 @@ void StubCompiler::GenerateLoadConstant(JSObject* object, // Specialized stub for constructing objects from functions which only have only // simple assignments of the form this.x = ...; in their body. -Object* ConstructStubCompiler::CompileConstructStub( +MaybeObject* ConstructStubCompiler::CompileConstructStub( SharedFunctionInfo* shared) { // ----------- S t a t e ------------- // -- rax : argc diff --git a/deps/v8/test/cctest/test-alloc.cc b/deps/v8/test/cctest/test-alloc.cc index 2936d6e7e1..fcf2ce4f1b 100644 --- a/deps/v8/test/cctest/test-alloc.cc +++ b/deps/v8/test/cctest/test-alloc.cc @@ -35,7 +35,7 @@ using namespace v8::internal; -static Object* AllocateAfterFailures() { +static MaybeObject* AllocateAfterFailures() { static int attempts = 0; if (++attempts < 3) return Failure::RetryAfterGC(); @@ -60,7 +60,8 @@ static Object* AllocateAfterFailures() { CHECK(!Heap::AllocateFixedArray(100)->IsFailure()); CHECK(!Heap::AllocateHeapNumber(0.42)->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()); // Old data space. @@ -111,7 +112,7 @@ TEST(StressHandles) { } -static Object* TestAccessorGet(Object* object, void*) { +static MaybeObject* TestAccessorGet(Object* object, void*) { return AllocateAfterFailures(); } diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index fd44aec47b..6eb15d8fbf 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -9278,7 +9278,9 @@ class RegExpStringModificationTest { // Inject the input as a global variable. i::Handle<i::String> input_name = 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); @@ -9750,7 +9752,7 @@ THREADED_TEST(PixelArray) { // Set the elements to be the pixels. // jsobj->set_elements(*pixels); 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)); context->Global()->Set(v8_str("pixels"), obj); 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::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); 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); 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++) {" " pixels[i] = (i * 65) - 109;" "}" "pixels[1] + pixels[6];"); CHECK_EQ(255, result->Int32Value()); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0))->value()); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1))->value()); - CHECK_EQ(21, i::Smi::cast(jsobj->GetElement(2))->value()); - CHECK_EQ(86, i::Smi::cast(jsobj->GetElement(3))->value()); - CHECK_EQ(151, i::Smi::cast(jsobj->GetElement(4))->value()); - CHECK_EQ(216, i::Smi::cast(jsobj->GetElement(5))->value()); - CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(6))->value()); - CHECK_EQ(255, i::Smi::cast(jsobj->GetElement(7))->value()); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value()); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); + CHECK_EQ(21, + i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value()); + CHECK_EQ(86, + i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value()); + CHECK_EQ(151, + 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;" "for (var i = 0; i < 8; i++) {" " sum += pixels[i];" @@ -9835,49 +9844,50 @@ THREADED_TEST(PixelArray) { "}" "pixels[1] + pixels[6];"); CHECK_EQ(8, result->Int32Value()); - CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0))->value()); - CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1))->value()); - CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2))->value()); - CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3))->value()); - CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4))->value()); - CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5))->value()); - CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6))->value()); - CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7))->value()); + CHECK_EQ(0, i::Smi::cast(jsobj->GetElement(0)->ToObjectChecked())->value()); + CHECK_EQ(1, i::Smi::cast(jsobj->GetElement(1)->ToObjectChecked())->value()); + CHECK_EQ(2, i::Smi::cast(jsobj->GetElement(2)->ToObjectChecked())->value()); + CHECK_EQ(3, i::Smi::cast(jsobj->GetElement(3)->ToObjectChecked())->value()); + CHECK_EQ(4, i::Smi::cast(jsobj->GetElement(4)->ToObjectChecked())->value()); + CHECK_EQ(6, i::Smi::cast(jsobj->GetElement(5)->ToObjectChecked())->value()); + CHECK_EQ(7, i::Smi::cast(jsobj->GetElement(6)->ToObjectChecked())->value()); + CHECK_EQ(8, i::Smi::cast(jsobj->GetElement(7)->ToObjectChecked())->value()); result = CompileRun("for (var i = 0; i < 8; i++) {" " pixels[7] = undefined;" "}" "pixels[7];"); 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++) {" " pixels[6] = '2.3';" "}" "pixels[6];"); 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++) {" " pixels[5] = NaN;" "}" "pixels[5];"); 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++) {" " pixels[8] = Infinity;" "}" "pixels[8];"); 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++) {" " pixels[9] = -Infinity;" "}" "pixels[9];"); 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;" "delete pixels[3];" @@ -9987,7 +9997,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, obj->SetIndexedPropertiesToExternalArrayData(array_data, array_type, 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)); context->Global()->Set(v8_str("ext_array"), obj); v8::Handle<v8::Value> result = CompileRun("ext_array.field"); @@ -10126,14 +10137,16 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, "}" "ext_array[7];"); 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++) {" " ext_array[6] = '2.3';" "}" "ext_array[6];"); 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) { // Though the specification doesn't state it, be explicit about @@ -10146,7 +10159,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, "}" "ext_array[5];"); 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++) {" " ext_array[i] = 5;" @@ -10156,7 +10170,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, "}" "ext_array[5];"); 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++) {" " ext_array[i] = 5;" @@ -10166,7 +10181,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, "}" "ext_array[5];"); 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;" diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc index 7c669d30b7..4f90b613a8 100644 --- a/deps/v8/test/cctest/test-assembler-arm.cc +++ b/deps/v8/test/cctest/test-assembler-arm.cc @@ -69,9 +69,10 @@ TEST(0) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -105,9 +106,10 @@ TEST(1) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -150,9 +152,10 @@ TEST(2) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -197,9 +200,10 @@ TEST(3) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -290,9 +294,10 @@ TEST(4) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -341,9 +346,10 @@ TEST(5) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -375,9 +381,10 @@ TEST(6) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); diff --git a/deps/v8/test/cctest/test-assembler-ia32.cc b/deps/v8/test/cctest/test-assembler-ia32.cc index b60865de45..40232ef53a 100644 --- a/deps/v8/test/cctest/test-assembler-ia32.cc +++ b/deps/v8/test/cctest/test-assembler-ia32.cc @@ -71,7 +71,8 @@ TEST(AssemblerIa320) { assm.GetCode(&desc); Object* code = Heap::CreateCode(desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Handle<Object>(Heap::undefined_value()))-> + ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -108,7 +109,8 @@ TEST(AssemblerIa321) { assm.GetCode(&desc); Object* code = Heap::CreateCode(desc, Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Handle<Object>(Heap::undefined_value()))-> + ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -147,9 +149,11 @@ TEST(AssemblerIa322) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); + CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -180,10 +184,10 @@ TEST(AssemblerIa323) { CodeDesc desc; assm.GetCode(&desc); - Code* code = - Code::cast(Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))); + Code* code = Code::cast(Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); // don't print the code - our disassembler can't handle cvttss2si // instead print bytes Disassembler::Dump(stdout, @@ -214,10 +218,10 @@ TEST(AssemblerIa324) { CodeDesc desc; assm.GetCode(&desc); - Code* code = - Code::cast(Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))); + Code* code = Code::cast(Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); // don't print the code - our disassembler can't handle cvttsd2si // instead print bytes Disassembler::Dump(stdout, @@ -243,10 +247,10 @@ TEST(AssemblerIa325) { CodeDesc desc; assm.GetCode(&desc); - Code* code = - Code::cast(Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))); + Code* code = Code::cast(Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); F0 f = FUNCTION_CAST<F0>(code->entry()); int res = f(); CHECK_EQ(42, res); @@ -280,10 +284,10 @@ TEST(AssemblerIa326) { CodeDesc desc; assm.GetCode(&desc); - Code* code = - Code::cast(Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))); + Code* code = Code::cast(Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); #ifdef DEBUG ::printf("\n---\n"); // don't print the code - our disassembler can't handle SSE instructions @@ -320,10 +324,10 @@ TEST(AssemblerIa328) { __ ret(0); CodeDesc desc; assm.GetCode(&desc); - Code* code = - Code::cast(Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))); + Code* code = Code::cast(Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); @@ -375,10 +379,10 @@ TEST(AssemblerIa329) { CodeDesc desc; assm.GetCode(&desc); - Code* code = - Code::cast(Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value()))); + Code* code = Code::cast(Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked()); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc index 96549a37e7..b424b7f9e1 100644 --- a/deps/v8/test/cctest/test-compiler.cc +++ b/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); return Top::context()->global()->GetProperty(*symbol); } @@ -140,7 +140,7 @@ static double Inc(int x) { Handle<JSObject> global(Top::context()->global()); Execution::Call(fun, global, 0, NULL, &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()); Execution::Call(fun, global, 0, NULL, &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()); Execution::Call(fun, global, 0, NULL, &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()); Execution::Call(fun, global, 0, NULL, &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()); Execution::Call(fun, global, 0, NULL, &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 = Execution::Call(fun, global, 0, NULL, &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); CHECK(!has_pending_exception); - Handle<Object> fun1 = - Handle<Object>( - Top::context()->global()->GetProperty( - *Factory::LookupAsciiSymbol("foo"))); + Object* foo_symbol = Factory::LookupAsciiSymbol("foo")->ToObjectChecked(); + MaybeObject* fun1_object = + Top::context()->global()->GetProperty(String::cast(foo_symbol)); + Handle<Object> fun1(fun1_object->ToObjectChecked()); CHECK(fun1->IsJSFunction()); Object** argv[1] = { diff --git a/deps/v8/test/cctest/test-disasm-ia32.cc b/deps/v8/test/cctest/test-disasm-ia32.cc index b53eaaa217..5cd56acf05 100644 --- a/deps/v8/test/cctest/test-disasm-ia32.cc +++ b/deps/v8/test/cctest/test-disasm-ia32.cc @@ -438,9 +438,10 @@ TEST(DisasmIa320) { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); #ifdef DEBUG Code::cast(code)->Print(); diff --git a/deps/v8/test/cctest/test-heap.cc b/deps/v8/test/cctest/test-heap.cc index 126ac21ada..94d05555ec 100644 --- a/deps/v8/test/cctest/test-heap.cc +++ b/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) { - Object* obj = Heap::NumberFromDouble(value); + Object* obj = Heap::NumberFromDouble(value)->ToObjectChecked(); CHECK(obj->IsNumber()); bool exc; Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc); @@ -76,9 +76,10 @@ static void CheckFindCodeObject() { CodeDesc desc; assm.GetCode(&desc); - Object* code = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* code = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(code->IsCode()); HeapObject* obj = HeapObject::cast(code); @@ -89,9 +90,10 @@ static void CheckFindCodeObject() { CHECK_EQ(code, found); } - Object* copy = Heap::CreateCode(desc, - Code::ComputeFlags(Code::STUB), - Handle<Object>(Heap::undefined_value())); + Object* copy = Heap::CreateCode( + desc, + Code::ComputeFlags(Code::STUB), + Handle<Object>(Heap::undefined_value()))->ToObjectChecked(); CHECK(copy->IsCode()); HeapObject* obj_copy = HeapObject::cast(copy); Object* not_right = Heap::FindCodeObject(obj_copy->address() + @@ -104,40 +106,42 @@ TEST(HeapObjects) { InitializeVM(); v8::HandleScope sc; - Object* value = Heap::NumberFromDouble(1.000123); + Object* value = Heap::NumberFromDouble(1.000123)->ToObjectChecked(); CHECK(value->IsHeapNumber()); CHECK(value->IsNumber()); CHECK_EQ(1.000123, value->Number()); - value = Heap::NumberFromDouble(1.0); + value = Heap::NumberFromDouble(1.0)->ToObjectChecked(); CHECK(value->IsSmi()); CHECK(value->IsNumber()); CHECK_EQ(1.0, value->Number()); - value = Heap::NumberFromInt32(1024); + value = Heap::NumberFromInt32(1024)->ToObjectChecked(); CHECK(value->IsSmi()); CHECK(value->IsNumber()); CHECK_EQ(1024.0, value->Number()); - value = Heap::NumberFromInt32(Smi::kMinValue); + value = Heap::NumberFromInt32(Smi::kMinValue)->ToObjectChecked(); CHECK(value->IsSmi()); CHECK(value->IsNumber()); CHECK_EQ(Smi::kMinValue, Smi::cast(value)->value()); - value = Heap::NumberFromInt32(Smi::kMaxValue); + value = Heap::NumberFromInt32(Smi::kMaxValue)->ToObjectChecked(); CHECK(value->IsSmi()); CHECK(value->IsNumber()); CHECK_EQ(Smi::kMaxValue, Smi::cast(value)->value()); #ifndef V8_TARGET_ARCH_X64 // 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->IsNumber()); CHECK_EQ(static_cast<double>(Smi::kMinValue - 1), value->Number()); #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->IsNumber()); CHECK_EQ(static_cast<double>(static_cast<uint32_t>(Smi::kMaxValue) + 1), @@ -208,11 +212,13 @@ TEST(GarbageCollection) { Handle<Map> initial_map = Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 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. Handle<JSObject> obj = Factory::NewJSObject(function); - obj->SetProperty(*prop_name, Smi::FromInt(23), NONE); - obj->SetProperty(*prop_namex, Smi::FromInt(24), NONE); + obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked(); + obj->SetProperty(*prop_namex, Smi::FromInt(24), NONE)->ToObjectChecked(); CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); CHECK_EQ(Smi::FromInt(24), obj->GetProperty(*prop_namex)); @@ -223,7 +229,8 @@ TEST(GarbageCollection) { // Function should be alive. CHECK(Top::context()->global()->HasLocalProperty(*name)); // 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()); Handle<JSFunction> function(JSFunction::cast(func_value)); @@ -231,18 +238,22 @@ TEST(GarbageCollection) { HandleScope inner_scope; // Allocate another object, make it reachable from global. Handle<JSObject> obj = Factory::NewJSObject(function); - Top::context()->global()->SetProperty(*obj_name, *obj, NONE); - obj->SetProperty(*prop_name, Smi::FromInt(23), NONE); + Top::context()->global()->SetProperty(*obj_name, + *obj, + NONE)->ToObjectChecked(); + obj->SetProperty(*prop_name, Smi::FromInt(23), NONE)->ToObjectChecked(); } // After gc, it should survive. Heap::CollectGarbage(NEW_SPACE); CHECK(Top::context()->global()->HasLocalProperty(*obj_name)); - CHECK(Top::context()->global()->GetProperty(*obj_name)->IsJSObject()); - JSObject* obj = - JSObject::cast(Top::context()->global()->GetProperty(*obj_name)); - CHECK_EQ(Smi::FromInt(23), obj->GetProperty(*prop_name)); + CHECK(Top::context()->global()->GetProperty(*obj_name)->ToObjectChecked()-> + IsJSObject()); + Object* obj = + 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) { 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. - if (a->IsFailure()) continue; + if (!maybe_a->ToObject(&a)) continue; CHECK(a->IsSymbol()); - Object* b = Heap::LookupAsciiSymbol(string); - if (b->IsFailure()) continue; + Object* b; + MaybeObject* maybe_b = Heap::LookupAsciiSymbol(string); + if (!maybe_b->ToObject(&b)) continue; CHECK_EQ(b, a); CHECK(String::cast(b)->IsEqualTo(CStrVector(string))); } @@ -527,10 +540,12 @@ TEST(FunctionAllocation) { Handle<String> prop_name = Factory::LookupAsciiSymbol("theSlot"); 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 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)); } @@ -540,8 +555,9 @@ TEST(ObjectProperties) { v8::HandleScope sc; String* object_symbol = String::cast(Heap::Object_symbol()); - JSFunction* object_function = - JSFunction::cast(Top::context()->global()->GetProperty(object_symbol)); + Object* raw_object = + Top::context()->global()->GetProperty(object_symbol)->ToObjectChecked(); + JSFunction* object_function = JSFunction::cast(raw_object); Handle<JSFunction> constructor(object_function); Handle<JSObject> obj = Factory::NewJSObject(constructor); Handle<String> first = Factory::LookupAsciiSymbol("first"); @@ -551,7 +567,7 @@ TEST(ObjectProperties) { CHECK(!obj->HasLocalProperty(*first)); // add first - obj->SetProperty(*first, Smi::FromInt(1), NONE); + obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked(); CHECK(obj->HasLocalProperty(*first)); // delete first @@ -559,8 +575,8 @@ TEST(ObjectProperties) { CHECK(!obj->HasLocalProperty(*first)); // add first and then second - obj->SetProperty(*first, Smi::FromInt(1), NONE); - obj->SetProperty(*second, Smi::FromInt(2), NONE); + obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked(); + obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked(); CHECK(obj->HasLocalProperty(*first)); CHECK(obj->HasLocalProperty(*second)); @@ -572,8 +588,8 @@ TEST(ObjectProperties) { CHECK(!obj->HasLocalProperty(*second)); // add first and then second - obj->SetProperty(*first, Smi::FromInt(1), NONE); - obj->SetProperty(*second, Smi::FromInt(2), NONE); + obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked(); + obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked(); CHECK(obj->HasLocalProperty(*first)); CHECK(obj->HasLocalProperty(*second)); @@ -587,14 +603,14 @@ TEST(ObjectProperties) { // check string and symbol match static const char* string1 = "fisk"; 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); CHECK(obj->HasLocalProperty(*s1_symbol)); // check symbol and string match static const char* string2 = "fugl"; 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)); CHECK(obj->HasLocalProperty(*s2)); } @@ -615,7 +631,7 @@ TEST(JSObjectMaps) { Handle<JSObject> obj = Factory::NewJSObject(function); // 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 the map has changed @@ -628,33 +644,31 @@ TEST(JSArray) { v8::HandleScope sc; Handle<String> name = Factory::LookupAsciiSymbol("Array"); + Object* raw_object = + Top::context()->global()->GetProperty(*name)->ToObjectChecked(); Handle<JSFunction> function = Handle<JSFunction>( - JSFunction::cast(Top::context()->global()->GetProperty(*name))); + JSFunction::cast(raw_object)); // Allocate the object. Handle<JSObject> object = Factory::NewJSObject(function); Handle<JSArray> array = Handle<JSArray>::cast(object); - Object* ok = array->Initialize(0); // We just initialized the VM, no heap allocation failure yet. - CHECK(!ok->IsFailure()); + Object* ok = array->Initialize(0)->ToObjectChecked(); // Set array length to 0. - ok = array->SetElementsLength(Smi::FromInt(0)); - CHECK(!ok->IsFailure()); + ok = array->SetElementsLength(Smi::FromInt(0))->ToObjectChecked(); CHECK_EQ(Smi::FromInt(0), array->length()); CHECK(array->HasFastElements()); // Must be in fast mode. // array[length] = name. - ok = array->SetElement(0, *name); - CHECK(!ok->IsFailure()); + ok = array->SetElement(0, *name)->ToObjectChecked(); CHECK_EQ(Smi::FromInt(1), array->length()); CHECK_EQ(array->GetElement(0), *name); // Set array length with larger than smi value. Handle<Object> length = Factory::NewNumberFromUint(static_cast<uint32_t>(Smi::kMaxValue) + 1); - ok = array->SetElementsLength(*length); - CHECK(!ok->IsFailure()); + ok = array->SetElementsLength(*length)->ToObjectChecked(); uint32_t int_length = 0; CHECK(length->ToArrayIndex(&int_length)); @@ -662,8 +676,7 @@ TEST(JSArray) { CHECK(array->HasDictionaryElements()); // Must be in slow mode. // array[length] = name. - ok = array->SetElement(int_length, *name); - CHECK(!ok->IsFailure()); + ok = array->SetElement(int_length, *name)->ToObjectChecked(); uint32_t new_int_length = 0; CHECK(array->length()->ToArrayIndex(&new_int_length)); CHECK_EQ(static_cast<double>(int_length), new_int_length - 1); @@ -677,21 +690,20 @@ TEST(JSObjectCopy) { v8::HandleScope sc; String* object_symbol = String::cast(Heap::Object_symbol()); - JSFunction* object_function = - JSFunction::cast(Top::context()->global()->GetProperty(object_symbol)); + Object* raw_object = + Top::context()->global()->GetProperty(object_symbol)->ToObjectChecked(); + JSFunction* object_function = JSFunction::cast(raw_object); Handle<JSFunction> constructor(object_function); Handle<JSObject> obj = Factory::NewJSObject(constructor); Handle<String> first = Factory::LookupAsciiSymbol("first"); Handle<String> second = Factory::LookupAsciiSymbol("second"); - obj->SetProperty(*first, Smi::FromInt(1), NONE); - obj->SetProperty(*second, Smi::FromInt(2), NONE); + obj->SetProperty(*first, Smi::FromInt(1), NONE)->ToObjectChecked(); + obj->SetProperty(*second, Smi::FromInt(2), NONE)->ToObjectChecked(); - Object* ok = obj->SetElement(0, *first); - CHECK(!ok->IsFailure()); + Object* ok = obj->SetElement(0, *first)->ToObjectChecked(); - ok = obj->SetElement(1, *second); - CHECK(!ok->IsFailure()); + ok = obj->SetElement(1, *second)->ToObjectChecked(); // Make the clone. Handle<JSObject> clone = Copy(obj); @@ -704,13 +716,11 @@ TEST(JSObjectCopy) { CHECK_EQ(obj->GetProperty(*second), clone->GetProperty(*second)); // Flip the values. - clone->SetProperty(*first, Smi::FromInt(2), NONE); - clone->SetProperty(*second, Smi::FromInt(1), NONE); + clone->SetProperty(*first, Smi::FromInt(2), NONE)->ToObjectChecked(); + clone->SetProperty(*second, Smi::FromInt(1), NONE)->ToObjectChecked(); - ok = clone->SetElement(0, *second); - CHECK(!ok->IsFailure()); - ok = clone->SetElement(1, *first); - CHECK(!ok->IsFailure()); + ok = clone->SetElement(0, *second)->ToObjectChecked(); + ok = clone->SetElement(1, *first)->ToObjectChecked(); CHECK_EQ(obj->GetElement(1), clone->GetElement(0)); CHECK_EQ(obj->GetElement(0), clone->GetElement(1)); @@ -836,7 +846,7 @@ TEST(LargeObjectSpaceContains) { kPointerSize; CHECK_EQ(bytes_to_allocate, FixedArray::SizeFor(n_elements)); FixedArray* array = FixedArray::cast( - Heap::AllocateFixedArray(n_elements)); + Heap::AllocateFixedArray(n_elements)->ToObjectChecked()); int index = n_elements - 1; CHECK_EQ(flags_ptr, @@ -908,8 +918,8 @@ TEST(Regression39128) { Address* limit_addr = new_space->allocation_limit_address(); while ((*limit_addr - *top_addr) > allocation_amount) { CHECK(!Heap::always_allocate()); - Object* array = Heap::AllocateFixedArray(allocation_len); - CHECK(!array->IsFailure()); + Object* array = + Heap::AllocateFixedArray(allocation_len)->ToObjectChecked(); CHECK(new_space->Contains(array)); } @@ -919,12 +929,11 @@ TEST(Regression39128) { CHECK(fixed_array_len < FixedArray::kMaxLength); CHECK(!Heap::always_allocate()); - Object* array = Heap::AllocateFixedArray(fixed_array_len); - CHECK(!array->IsFailure()); + Object* array = + Heap::AllocateFixedArray(fixed_array_len)->ToObjectChecked(); CHECK(new_space->Contains(array)); - Object* object = Heap::AllocateJSObjectFromMap(*my_map); - CHECK(!object->IsFailure()); + Object* object = Heap::AllocateJSObjectFromMap(*my_map)->ToObjectChecked(); CHECK(new_space->Contains(object)); JSObject* jsobject = JSObject::cast(object); CHECK_EQ(0, FixedArray::cast(jsobject->elements())->length()); @@ -938,8 +947,7 @@ TEST(Regression39128) { // in old pointer space. Address old_pointer_space_top = Heap::old_pointer_space()->top(); AlwaysAllocateScope aa_scope; - Object* clone_obj = Heap::CopyJSObject(jsobject); - CHECK(!object->IsFailure()); + Object* clone_obj = Heap::CopyJSObject(jsobject)->ToObjectChecked(); JSObject* clone = JSObject::cast(clone_obj); if (clone->address() != old_pointer_space_top) { // Alas, got allocated from free list, we cannot do checks. @@ -973,7 +981,8 @@ TEST(TestCodeFlushing) { CompileRun(source); // 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()); Handle<JSFunction> function(JSFunction::cast(func_value)); CHECK(function->shared()->is_compiled()); diff --git a/deps/v8/test/cctest/test-log-stack-tracer.cc b/deps/v8/test/cctest/test-log-stack-tracer.cc index 7d7bd406bf..65be6bd85e 100644 --- a/deps/v8/test/cctest/test-log-stack-tracer.cc +++ b/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) { i::Object* obj = i::HeapObject::FromAddress(addr); 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 // 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. @@ -273,25 +256,18 @@ static void CreateTraceCallerFunction(const char* func_name, const char* trace_func_name) { i::EmbeddedVector<char, 256> trace_call_buf; i::OS::SNPrintF(trace_call_buf, - "fp = new FPGrabber(); %s(fp.low_bits, fp.high_bits);", - trace_func_name); + "function %s() {" + " 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 // when called as a constructor. CreateFramePointerGrabberConstructor("FPGrabber"); // Compile the script. - Handle<JSFunction> func = CompileFunction(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)); + CompileRun(trace_call_buf.start()); } diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc index 16d0f005c9..7168737416 100644 --- a/deps/v8/test/cctest/test-log.cc +++ b/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. -#ifdef __linux__ +// BUG(913). Need to implement support for profiling multiple VM threads. +#if 0 namespace { diff --git a/deps/v8/test/cctest/test-mark-compact.cc b/deps/v8/test/cctest/test-mark-compact.cc index 531b1f77bb..ea5afecc1e 100644 --- a/deps/v8/test/cctest/test-mark-compact.cc +++ b/deps/v8/test/cctest/test-mark-compact.cc @@ -85,8 +85,7 @@ TEST(Promotion) { int array_size = (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / (kPointerSize * 4); - Object* obj = Heap::AllocateFixedArray(array_size); - CHECK(!obj->IsFailure()); + Object* obj = Heap::AllocateFixedArray(array_size)->ToObjectChecked(); Handle<FixedArray> array(FixedArray::cast(obj)); @@ -116,7 +115,7 @@ TEST(NoPromotion) { // Allocate a big Fixed array in the new space. int size = (Heap::MaxObjectSizeInPagedSpace() - FixedArray::kHeaderSize) / kPointerSize; - Object* obj = Heap::AllocateFixedArray(size); + Object* obj = Heap::AllocateFixedArray(size)->ToObjectChecked(); Handle<FixedArray> array(FixedArray::cast(obj)); @@ -126,8 +125,10 @@ TEST(NoPromotion) { // Allocate objects in the old space until out of memory. FixedArray* host = *array; while (true) { - Object* obj = Heap::AllocateFixedArray(100, TENURED); - if (obj->IsFailure()) break; + Object* obj; + { MaybeObject* maybe_obj = Heap::AllocateFixedArray(100, TENURED); + if (!maybe_obj->ToObject(&obj)) break; + } host->set(0, obj); host = FixedArray::cast(obj); @@ -151,59 +152,75 @@ TEST(MarkCompactCollector) { // keep allocating garbage in new space until it fails const int ARRAY_SIZE = 100; Object* array; + MaybeObject* maybe_array; do { - array = Heap::AllocateFixedArray(ARRAY_SIZE); - } while (!array->IsFailure()); + maybe_array = Heap::AllocateFixedArray(ARRAY_SIZE); + } while (maybe_array->ToObject(&array)); Heap::CollectGarbage(NEW_SPACE); - array = Heap::AllocateFixedArray(ARRAY_SIZE); - CHECK(!array->IsFailure()); + array = Heap::AllocateFixedArray(ARRAY_SIZE)->ToObjectChecked(); // keep allocating maps until it fails Object* mapp; + MaybeObject* maybe_mapp; do { - mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); - } while (!mapp->IsFailure()); + maybe_mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); + } while (maybe_mapp->ToObject(&mapp)); Heap::CollectGarbage(MAP_SPACE); - mapp = Heap::AllocateMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); - CHECK(!mapp->IsFailure()); + mapp = Heap::AllocateMap(JS_OBJECT_TYPE, + JSObject::kHeaderSize)->ToObjectChecked(); // allocate a garbage - String* func_name = String::cast(Heap::LookupAsciiSymbol("theFunction")); - SharedFunctionInfo* function_share = - SharedFunctionInfo::cast(Heap::AllocateSharedFunctionInfo(func_name)); - JSFunction* function = - JSFunction::cast(Heap::AllocateFunction(*Top::function_map(), - function_share, - Heap::undefined_value())); + String* func_name = + String::cast(Heap::LookupAsciiSymbol("theFunction")->ToObjectChecked()); + SharedFunctionInfo* function_share = SharedFunctionInfo::cast( + Heap::AllocateSharedFunctionInfo(func_name)->ToObjectChecked()); + JSFunction* function = JSFunction::cast( + Heap::AllocateFunction(*Top::function_map(), + function_share, + Heap::undefined_value())->ToObjectChecked()); 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); - 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); - func_name = String::cast(Heap::LookupAsciiSymbol("theFunction")); + func_name = + String::cast(Heap::LookupAsciiSymbol("theFunction")->ToObjectChecked()); 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()); function = JSFunction::cast(func_value); - obj = JSObject::cast(Heap::AllocateJSObject(function)); - String* obj_name = String::cast(Heap::LookupAsciiSymbol("theObject")); - Top::context()->global()->SetProperty(obj_name, obj, NONE); - String* prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot")); - obj->SetProperty(prop_name, Smi::FromInt(23), NONE); + obj = JSObject::cast(Heap::AllocateJSObject(function)->ToObjectChecked()); + String* obj_name = + String::cast(Heap::LookupAsciiSymbol("theObject")->ToObjectChecked()); + Top::context()->global()->SetProperty(obj_name, + 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); - 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()->GetProperty(obj_name)->IsJSObject()); - obj = JSObject::cast(Top::context()->global()->GetProperty(obj_name)); - prop_name = String::cast(Heap::LookupAsciiSymbol("theSlot")); - CHECK(obj->GetProperty(prop_name) == Smi::FromInt(23)); + CHECK(Top::context()->global()-> + GetProperty(obj_name)->ToObjectChecked()->IsJSObject()); + obj = JSObject::cast( + 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; Handle<Object> g1s1 = - GlobalHandles::Create(Heap::AllocateFixedArray(1)); + GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked()); Handle<Object> g1s2 = - GlobalHandles::Create(Heap::AllocateFixedArray(1)); + GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked()); GlobalHandles::MakeWeak(g1s1.location(), reinterpret_cast<void*>(1234), &WeakPointerCallback); @@ -294,9 +311,9 @@ TEST(ObjectGroups) { &WeakPointerCallback); Handle<Object> g2s1 = - GlobalHandles::Create(Heap::AllocateFixedArray(1)); + GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked()); Handle<Object> g2s2 = - GlobalHandles::Create(Heap::AllocateFixedArray(1)); + GlobalHandles::Create(Heap::AllocateFixedArray(1)->ToObjectChecked()); GlobalHandles::MakeWeak(g2s1.location(), reinterpret_cast<void*>(1234), &WeakPointerCallback); diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc index 20fb2fe6c1..6a513e5fa5 100644 --- a/deps/v8/test/cctest/test-serialize.cc +++ b/deps/v8/test/cctest/test-serialize.cc @@ -576,7 +576,8 @@ TEST(LinearAllocation) { for (int i = 0; i + kSmallFixedArraySize <= new_space_size; i += kSmallFixedArraySize) { - Object* obj = Heap::AllocateFixedArray(kSmallFixedArrayLength); + Object* obj = + Heap::AllocateFixedArray(kSmallFixedArrayLength)->ToObjectChecked(); if (new_last != NULL) { CHECK(reinterpret_cast<char*>(obj) == reinterpret_cast<char*>(new_last) + kSmallFixedArraySize); @@ -588,7 +589,8 @@ TEST(LinearAllocation) { for (int i = 0; i + kSmallFixedArraySize <= size; i += kSmallFixedArraySize) { - Object* obj = Heap::AllocateFixedArray(kSmallFixedArrayLength, TENURED); + Object* obj = Heap::AllocateFixedArray(kSmallFixedArrayLength, + TENURED)->ToObjectChecked(); int old_page_fullness = i % Page::kPageSize; int page_fullness = (i + kSmallFixedArraySize) % Page::kPageSize; if (page_fullness < old_page_fullness || @@ -605,7 +607,8 @@ TEST(LinearAllocation) { Object* data_last = NULL; 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 page_fullness = (i + kSmallStringSize) % Page::kPageSize; if (page_fullness < old_page_fullness || @@ -622,7 +625,8 @@ TEST(LinearAllocation) { Object* map_last = NULL; 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 page_fullness = (i + kMapSize) % Page::kPageSize; if (page_fullness < old_page_fullness || @@ -644,7 +648,7 @@ TEST(LinearAllocation) { int large_object_array_length = (size - FixedArray::kHeaderSize) / kPointerSize; Object* obj = Heap::AllocateFixedArray(large_object_array_length, - TENURED); + TENURED)->ToObjectChecked(); CHECK(!obj->IsFailure()); } } diff --git a/deps/v8/test/cctest/test-spaces.cc b/deps/v8/test/cctest/test-spaces.cc index db8c54fa68..06f1bfaca2 100644 --- a/deps/v8/test/cctest/test-spaces.cc +++ b/deps/v8/test/cctest/test-spaces.cc @@ -160,8 +160,8 @@ TEST(NewSpace) { CHECK(new_space.HasBeenSetup()); while (new_space.Available() >= Page::kMaxHeapObjectSize) { - Object* obj = new_space.AllocateRaw(Page::kMaxHeapObjectSize); - CHECK(!obj->IsFailure()); + Object* obj = + new_space.AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked(); CHECK(new_space.Contains(HeapObject::cast(obj))); } @@ -188,8 +188,7 @@ TEST(OldSpace) { CHECK(s->Setup(start, size)); while (s->Available() > 0) { - Object* obj = s->AllocateRaw(Page::kMaxHeapObjectSize); - CHECK(!obj->IsFailure()); + s->AllocateRaw(Page::kMaxHeapObjectSize)->ToObjectUnchecked(); } s->TearDown(); @@ -207,8 +206,7 @@ TEST(LargeObjectSpace) { Map* faked_map = reinterpret_cast<Map*>(HeapObject::FromAddress(0)); int lo_size = Page::kPageSize; - Object* obj = lo->AllocateRaw(lo_size); - CHECK(!obj->IsFailure()); + Object* obj = lo->AllocateRaw(lo_size)->ToObjectUnchecked(); CHECK(obj->IsHeapObject()); HeapObject* ho = HeapObject::cast(obj); @@ -222,16 +220,16 @@ TEST(LargeObjectSpace) { while (true) { intptr_t available = lo->Available(); - obj = lo->AllocateRaw(lo_size); - if (obj->IsFailure()) break; + { MaybeObject* maybe_obj = lo->AllocateRaw(lo_size); + if (!maybe_obj->ToObject(&obj)) break; + } HeapObject::cast(obj)->set_map(faked_map); CHECK(lo->Available() < available); }; CHECK(!lo->IsEmpty()); - obj = lo->AllocateRaw(lo_size); - CHECK(obj->IsFailure()); + CHECK(lo->AllocateRaw(lo_size)->IsFailure()); lo->TearDown(); delete lo; diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc index 3a9e4da24a..3f02b32b8c 100644 --- a/deps/v8/test/cctest/test-strings.cc +++ b/deps/v8/test/cctest/test-strings.cc @@ -476,7 +476,7 @@ TEST(CachedHashOverflow) { CHECK_EQ(results[i]->IsUndefined(), result->IsUndefined()); CHECK_EQ(results[i]->IsNumber(), 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()); } } diff --git a/deps/v8/test/cctest/test-strtod.cc b/deps/v8/test/cctest/test-strtod.cc index ae1c00d36e..56b26ea1eb 100644 --- a/deps/v8/test/cctest/test-strtod.cc +++ b/deps/v8/test/cctest/test-strtod.cc @@ -198,10 +198,58 @@ TEST(Strtod) { CHECK_EQ(1234e304, StrtodChar("0000000123400000", 299)); CHECK_EQ(V8_INFINITY, StrtodChar("00000000180000000", 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 // numbers can be accurately represented with doubles. However on Linux,x86 // the floating-point stack is set to 80bits and the double-rounding // introduces an error. 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)); } diff --git a/deps/v8/test/mjsunit/bugs/bug-617.js b/deps/v8/test/mjsunit/bugs/bug-617.js new file mode 100644 index 0000000000..f69d4ad55c --- /dev/null +++ b/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); diff --git a/deps/v8/test/mjsunit/define-property-gc.js b/deps/v8/test/mjsunit/define-property-gc.js new file mode 100644 index 0000000000..b38164d0f4 --- /dev/null +++ b/deps/v8/test/mjsunit/define-property-gc.js @@ -0,0 +1,45 @@ +// 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. + +// Tests the handling of GC issues in the defineProperty method. +// Flags: --max-new-space-size=256 + +function Regular() { + this[0] = 0; + this[1] = 1; +} + + +function foo() { + var descElementNonWritable = { value: 'foofoo', writable: false }; + for (var i = 0; i < 1000; i++) { + var regular = new Regular(); + Object.defineProperty(regular, '1', descElementNonWritable); + } +} + +foo(); diff --git a/deps/v8/test/mjsunit/math-min-max.js b/deps/v8/test/mjsunit/math-min-max.js index 72d8ba30d9..13d54a35a9 100644 --- a/deps/v8/test/mjsunit/math-min-max.js +++ b/deps/v8/test/mjsunit/math-min-max.js @@ -55,7 +55,10 @@ var ZERO = (function() { assertEquals(0, ZERO); assertEquals(Infinity, 1/ZERO); assertEquals(-Infinity, 1/-ZERO); -assertFalse(%_IsSmi(ZERO)); +// Here we would like to have assertFalse(%_IsSmi(ZERO)); This is, however, +// unreliable, since a new space exhaustion at a critical moment could send +// us into the runtime system, which would quite legitimately put a Smi zero +// here. assertFalse(%_IsSmi(-ZERO)); var o = {}; diff --git a/deps/v8/test/mjsunit/string-case.js b/deps/v8/test/mjsunit/string-case.js index 13dcd3ea81..283e703fc3 100644 --- a/deps/v8/test/mjsunit/string-case.js +++ b/deps/v8/test/mjsunit/string-case.js @@ -25,4 +25,47 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Flags: --random-seed=17 + assertEquals("ΚΟΣΜΟΣ ΚΟΣΜΟΣ".toLowerCase(), "κοσμος κοσμος"); + +var A_CODE = "A".charCodeAt(0); +var Z_CODE = "Z".charCodeAt(0); +var a_CODE = "a".charCodeAt(0); +var z_CODE = "z".charCodeAt(0); + +function charCodeToLower(charCode) { + if (A_CODE <= charCode && charCode <= Z_CODE) { + return charCode + a_CODE - A_CODE; + } + return charCode; +} + +function charCodeToUpper(charCode) { + if (a_CODE <= charCode && charCode <= z_CODE) { + return charCode - (a_CODE - A_CODE); + } + return charCode; +} + +function test(length) { + var str = ""; + var strLower = ""; + var strUpper = ""; + for (var i = 0; i < length; i++) { + var c = Math.round(0x7f * Math.random()); + str += String.fromCharCode(c); + strLower += String.fromCharCode(charCodeToLower(c)); + strUpper += String.fromCharCode(charCodeToUpper(c)); + } + assertEquals(strLower, str.toLowerCase()); + assertEquals(strUpper, str.toUpperCase()); +} + +for (var i = 1; i <= 128; i <<= 1); { + for (var j = 0; j < 8; j++) { + for (var k = 0; k < 3; k++) { + test(i + j); + } + } +} diff --git a/deps/v8/tools/windows-tick-processor.bat b/deps/v8/tools/windows-tick-processor.bat index 33b1f77052..d67f0471fe 100755 --- a/deps/v8/tools/windows-tick-processor.bat +++ b/deps/v8/tools/windows-tick-processor.bat @@ -1,6 +1,7 @@ @echo off SET tools_dir=%~dp0 +IF 1%D8_PATH% == 1 (SET D8_PATH=%tools_dir%..) SET log_file=v8.log @@ -26,4 +27,4 @@ IF NOT %arg8:~0,2% == 8 (IF NOT %arg8:~0,2% == 8- SET log_file=%8) SET arg9=9%9 IF NOT %arg9:~0,2% == 9 (IF NOT %arg9:~0,2% == 9- SET log_file=%9) -type %log_file% | %tools_dir%..\d8 %tools_dir%splaytree.js %tools_dir%codemap.js %tools_dir%csvparser.js %tools_dir%consarray.js %tools_dir%profile.js %tools_dir%profile_view.js %tools_dir%logreader.js %tools_dir%tickprocessor.js %tools_dir%tickprocessor-driver.js -- --windows %* +type %log_file% | %D8_PATH%\d8 %tools_dir%splaytree.js %tools_dir%codemap.js %tools_dir%csvparser.js %tools_dir%consarray.js %tools_dir%profile.js %tools_dir%profile_view.js %tools_dir%logreader.js %tools_dir%tickprocessor.js %tools_dir%tickprocessor-driver.js -- --windows %* |