Update V8 to r5716 as required by WebKit r70949
Change-Id: I0d5cd05bb0427af33e5c9f6efdc209366a32bde3
diff --git a/ChangeLog b/ChangeLog
index 36ed4fc..0785959 100644
--- a/ChangeLog
+++ b/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/SConstruct b/SConstruct
index a36a96f..820c1a1 100644
--- a/SConstruct
+++ b/SConstruct
@@ -207,7 +207,6 @@
'simulator:arm': {
'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32'],
- 'CPPDEFINES': ['USE_SIMULATOR']
},
'arch:mips': {
'CPPDEFINES': ['V8_TARGET_ARCH_MIPS'],
@@ -219,7 +218,6 @@
'simulator:mips': {
'CCFLAGS': ['-m32'],
'LINKFLAGS': ['-m32'],
- 'CPPDEFINES': ['USE_SIMULATOR']
},
'arch:x64': {
'CPPDEFINES': ['V8_TARGET_ARCH_X64'],
diff --git a/V8_MERGE_REVISION b/V8_MERGE_REVISION
index ef76b1b..bf2944f 100644
--- a/V8_MERGE_REVISION
+++ b/V8_MERGE_REVISION
@@ -1,4 +1,4 @@
We use a V8 revision that has been used for a Chromium release.
-http://src.chromium.org/svn/releases/8.0.561.0/DEPS
-http://v8.googlecode.com/svn/trunk@5675
+http://src.chromium.org/svn/releases/9.0.569.0/DEPS
+http://v8.googlecode.com/svn/trunk@5716
diff --git a/include/v8.h b/include/v8.h
index ef9a411..89502cb 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -467,16 +467,21 @@
// 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/src/accessors.cc b/src/accessors.cc
index 3c49846..7c21659 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -50,7 +50,7 @@
// 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::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::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::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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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 @@
//
-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::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/src/accessors.h b/src/accessors.h
index eeab2ac..96d742e 100644
--- a/src/accessors.h
+++ b/src/accessors.h
@@ -75,40 +75,44 @@
};
// 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/src/api.cc b/src/api.cc
index 962723d..2df31df 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -457,19 +457,37 @@
// --- 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 @@
result = *value;
}
is_closed_ = true;
- i::HandleScope::Leave(&previous_);
+ Leave();
if (value == NULL) {
return NULL;
@@ -1489,7 +1507,8 @@
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 @@
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 @@
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 @@
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/src/api.h b/src/api.h
index e179e35..e36160c 100644
--- a/src/api.h
+++ b/src/api.h
@@ -353,7 +353,7 @@
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 @@
}
-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/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 684106c..0c060f0 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -1180,20 +1180,23 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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/src/arm/cpu-arm.cc b/src/arm/cpu-arm.cc
index 3d3e6ae..a3bf483 100644
--- a/src/arm/cpu-arm.cc
+++ b/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::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/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index 7f83d14..c460f9c 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -1410,9 +1410,12 @@
__ 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/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index 0e2c49e..7f6090b 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -908,6 +908,17 @@
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 @@
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/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index 37bb1f0..fbcc9f7 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -1030,7 +1030,7 @@
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/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index 84d9d01..534e394 100644
--- a/src/arm/simulator-arm.cc
+++ b/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 @@
} } // namespace assembler::arm
-#endif // !__arm__ || USE_SIMULATOR
+#endif // USE_SIMULATOR
#endif // V8_TARGET_ARCH_ARM
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index d4c8250..e0658fc 100644
--- a/src/arm/simulator-arm.h
+++ b/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 @@
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 @@
} } // 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 @@
}
};
+} } // namespace v8::internal
-#endif // !defined(__arm__) || defined(USE_SIMULATOR)
-
+#endif // !defined(USE_SIMULATOR)
#endif // V8_ARM_SIMULATOR_ARM_H_
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 97f9495..fbad669 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -834,13 +834,16 @@
// 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 @@
!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 @@
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 @@
}
-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 @@
// 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 @@
// 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 @@
// 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
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 @@
}
__ 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 @@
// 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 @@
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 @@
// 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::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::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::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* 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 @@
// 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::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::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::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::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::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* 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::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::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::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::CompileLoadArrayLength(String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
// ----------- S t a t e -------------
// -- lr : return address
// -- r0 : key
@@ -2479,7 +2511,7 @@
}
-Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
// ----------- S t a t e -------------
// -- lr : return address
// -- r0 : key
@@ -2503,7 +2535,7 @@
// 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* 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* ConstructStubCompiler::CompileConstructStub(
+MaybeObject* ConstructStubCompiler::CompileConstructStub(
SharedFunctionInfo* shared) {
// ----------- S t a t e -------------
// -- r0 : argc
diff --git a/src/assembler.cc b/src/assembler.cc
index b6efdb9..ce90dce 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -583,6 +583,12 @@
}
+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::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/src/assembler.h b/src/assembler.h
index d28bf43..6681177 100644
--- a/src/assembler.h
+++ b/src/assembler.h
@@ -482,6 +482,7 @@
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 @@
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/src/bootstrapper.cc b/src/bootstrapper.cc
index d7491e1..0e49966 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1009,11 +1009,10 @@
}
-#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 @@
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 @@
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/src/builtins.cc b/src/builtins.cc
index b4f4a06..52d5530 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -121,18 +121,21 @@
#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 @@
// 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 @@
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 @@
// 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 @@
}
-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 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 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 @@
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 @@
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(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 @@
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(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(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 @@
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(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 @@
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(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 @@
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 @@
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 @@
}
// 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 @@
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 @@
// 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 @@
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 @@
return NULL;
}
-
} } // namespace v8::internal
diff --git a/src/cached-powers.cc b/src/cached-powers.cc
index 8f82286..43dbc78 100644
--- a/src/cached-powers.cc
+++ b/src/cached-powers.cc
@@ -42,6 +42,11 @@
};
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 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/src/cached-powers.h b/src/cached-powers.h
index 0c78343..2ae5619 100644
--- a/src/cached-powers.h
+++ b/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/src/code-stubs.cc b/src/code-stubs.cc
index 78062b4..787ec2a 100644
--- a/src/code-stubs.cc
+++ b/src/code-stubs.cc
@@ -123,7 +123,7 @@
}
-Object* CodeStub::TryGetCode() {
+MaybeObject* CodeStub::TryGetCode() {
Code* code;
if (!FindCodeInCache(&code)) {
// Generate the new code.
@@ -139,8 +139,11 @@
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 @@
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/src/code-stubs.h b/src/code-stubs.h
index 912d43d..c0a8d30 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -106,7 +106,7 @@
// 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 @@
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/src/compilation-cache.cc b/src/compilation-cache.cc
index b0449c4..6e4e4bf 100644
--- a/src/compilation-cache.cc
+++ b/src/compilation-cache.cc
@@ -110,7 +110,7 @@
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 @@
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 @@
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 @@
}
-Object* CompilationCacheScript::TryTablePut(
+MaybeObject* CompilationCacheScript::TryTablePut(
Handle<String> source,
Handle<SharedFunctionInfo> function_info) {
Handle<CompilationCacheTable> table = GetFirstTable();
@@ -386,7 +386,7 @@
}
-Object* CompilationCacheEval::TryTablePut(
+MaybeObject* CompilationCacheEval::TryTablePut(
Handle<String> source,
Handle<Context> context,
Handle<SharedFunctionInfo> function_info) {
@@ -442,7 +442,7 @@
}
-Object* CompilationCacheRegExp::TryTablePut(
+MaybeObject* CompilationCacheRegExp::TryTablePut(
Handle<String> source,
JSRegExp::Flags flags,
Handle<FixedArray> data) {
diff --git a/src/debug.cc b/src/debug.cc
index 53773ac..5c6ddbe 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1038,7 +1038,7 @@
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 @@
// 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 @@
// 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 @@
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/src/double.h b/src/double.h
index 65f8c94..e805173 100644
--- a/src/double.h
+++ b/src/double.h
@@ -45,10 +45,14 @@
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 @@
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 @@
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 @@
double value() const { return uint64_to_double(d64_); }
- private:
- static const int kSignificandSize = 52; // Excludes the hidden bit.
- static const int kExponentBias = 0x3FF + kSignificandSize;
- static const int kDenormalExponent = -kExponentBias + 1;
+ // 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;
+ }
- uint64_t d64_;
+ private:
+ 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);
+
+ 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/src/execution.cc b/src/execution.cc
index 6862324..3bbac0f 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -50,7 +50,7 @@
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 @@
Top::clear_pending_message();
}
- return Handle<Object>(value);
+ return Handle<Object>(value->ToObjectUnchecked());
}
@@ -172,7 +172,17 @@
// 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<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 @@
#endif
-Object* Execution::HandleStackGuardInterrupt() {
+MaybeObject* Execution::HandleStackGuardInterrupt() {
#ifdef ENABLE_DEBUGGER_SUPPORT
if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
DebugBreakHelper();
diff --git a/src/execution.h b/src/execution.h
index 15d85ef..5547803 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -132,7 +132,7 @@
// 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/src/factory.cc b/src/factory.cc
index 7c8c934..a05ff6c 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -431,7 +431,8 @@
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<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 @@
}
-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 @@
}
-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/src/fast-dtoa.cc b/src/fast-dtoa.cc
index ce825f9..c7f6aa1 100644
--- a/src/fast-dtoa.cc
+++ b/src/fast-dtoa.cc
@@ -613,9 +613,10 @@
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 @@
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/src/global-handles.cc b/src/global-handles.cc
index 0207322..9ede908 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -372,14 +372,13 @@
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 @@
// restart the processing).
break;
}
- weak_callback_invoked = true;
}
if ((*p)->state_ == Node::DESTROYED) {
// Delete the link.
@@ -409,7 +407,6 @@
if (first_deallocated()) {
first_deallocated()->set_next(head());
}
- return weak_callback_invoked;
}
diff --git a/src/global-handles.h b/src/global-handles.h
index c4c59fd..659f86e 100644
--- a/src/global-handles.h
+++ b/src/global-handles.h
@@ -95,9 +95,8 @@
// 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/src/globals.h b/src/globals.h
index fbc749d..c218f80 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -93,6 +93,18 @@
#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 @@
#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 NewSpace;
class NodeVisitor;
class Object;
+class MaybeObject;
class OldSpace;
class Property;
class Proxy;
@@ -542,8 +557,8 @@
// 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/src/handles-inl.h b/src/handles-inl.h
index bf19f5f..b313512 100644
--- a/src/handles-inl.h
+++ b/src/handles-inl.h
@@ -55,18 +55,22 @@
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/src/handles.cc b/src/handles.cc
index 8fe29bb..7a46bc3 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -44,7 +44,7 @@
v8::ImplementationUtilities::HandleScopeData HandleScope::current_ =
- { -1, NULL, NULL };
+ { NULL, NULL, 0 };
int HandleScope::NumberOfHandles() {
@@ -61,7 +61,7 @@
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** limit = &impl->blocks()->last()[kHandleBlockSize];
if (current_.limit != limit) {
current_.limit = limit;
+ ASSERT(limit - current_.next < kHandleBlockSize);
}
}
@@ -84,7 +85,6 @@
// 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 @@
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 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/src/handles.h b/src/handles.h
index 69170ff..2e18ab3 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -107,12 +107,20 @@
// 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 @@
// 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 @@
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 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 @@
inline NoHandleAllocation();
inline ~NoHandleAllocation();
private:
- int extensions_;
+ int level_;
#endif
};
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 104292d..15feb9d 100644
--- a/src/heap-inl.h
+++ b/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 @@
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::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 @@
}
-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::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 @@
}
-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 @@
// 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/src/heap.cc b/src/heap.cc
index 675639a..fc90866 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -56,6 +56,7 @@
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 @@
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::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 @@
? &Counters::gc_scavenger
: &Counters::gc_compactor;
rate->Start();
- PerformGarbageCollection(collector, &tracer, collectionPolicy);
+ PerformGarbageCollection(collector, &tracer);
rate->Stop();
GarbageCollectionEpilogue();
@@ -476,7 +472,7 @@
void Heap::PerformScavenge() {
GCTracer tracer;
- PerformGarbageCollection(SCAVENGER, &tracer, NORMAL);
+ PerformGarbageCollection(SCAVENGER, &tracer);
}
@@ -661,8 +657,7 @@
}
void Heap::PerformGarbageCollection(GarbageCollector collector,
- GCTracer* tracer,
- CollectionPolicy collectionPolicy) {
+ GCTracer* tracer) {
if (collector != SCAVENGER) {
PROFILE(CodeMovingGCEvent());
}
@@ -696,45 +691,25 @@
UpdateSurvivalRateTrend(start_new_space_size);
- 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);
- // 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;
- }
+ 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 @@
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 @@
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 @@
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 @@
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 @@
}
-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::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::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 @@
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 @@
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 @@
}
-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) {
+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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
}
-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 @@
}
-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 @@
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 @@
}
-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::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 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 @@
// 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 @@
}
-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 @@
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 @@
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 @@
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 @@
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::AllocateSubString(String* buffer,
+MaybeObject* Heap::AllocateSubString(String* buffer,
int start,
int end,
PretenureFlag pretenure) {
@@ -2290,10 +2385,12 @@
// 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::AllocateExternalStringFromAscii(
+MaybeObject* Heap::AllocateExternalStringFromAscii(
ExternalAsciiString::Resource* resource) {
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
@@ -2319,8 +2416,10 @@
}
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::AllocateExternalStringFromTwoByte(
+MaybeObject* Heap::AllocateExternalStringFromTwoByte(
ExternalTwoByteString::Resource* resource) {
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
@@ -2356,8 +2455,10 @@
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::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 @@
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) {
+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 @@
}
-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::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::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::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, 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 @@
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::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::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::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 @@
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 @@
}
-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 @@
// 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 @@
}
-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 @@
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::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 @@
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 @@
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::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 @@
// 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 @@
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 @@
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::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 @@
// 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::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::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 @@
// 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::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 @@
}
-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 @@
}
// 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::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 @@
} 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::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 @@
} 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::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::AllocateRawFixedArray(int length) {
+MaybeObject* Heap::AllocateRawFixedArray(int length) {
if (length < 0 || length > FixedArray::kMaxLength) {
return Failure::OutOfMemoryException();
}
@@ -3254,10 +3436,12 @@
}
-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::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 @@
}
-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 @@
}
-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::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::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::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::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 @@
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 @@
#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(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/src/heap.h b/src/heap.h
index 6d32a4b..8ff2f5f 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -316,32 +316,33 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index e201179..019f478 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -120,10 +120,15 @@
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/src/ia32/assembler-ia32.h b/src/ia32/assembler-ia32.h
index d8051c8..5286788 100644
--- a/src/ia32/assembler-ia32.h
+++ b/src/ia32/assembler-ia32.h
@@ -695,7 +695,6 @@
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/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 348bb14..b2b7392 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -3058,74 +3058,12 @@
}
-// 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/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index a62f74b..b72f4df 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -584,6 +584,20 @@
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 @@
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 @@
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 @@
}
-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 @@
}
-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 @@
}
-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 @@
}
-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::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.
+// 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);
+}
+
+
+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 {
+ // We allocate two additional slots: return value and pointer to it.
+ EnterApiExitFrame(stack_space, argc + 2);
+ }
+}
+
+
+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();
- push(Operand::StaticVariable(next_address));
ExternalReference limit_address =
ExternalReference::handle_scope_limit_address();
- push(Operand::StaticVariable(limit_address));
-}
+ ExternalReference level_address =
+ ExternalReference::handle_scope_level_address();
+ // 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));
-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);
- } else {
- result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
- if (result->IsFailure()) return result;
+ // 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));
}
- 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);
+ Label empty_handle;
+ Label prologue;
+ Label promote_scheduled_exception;
+ Label delete_allocated_handles;
+ Label leave_exit_frame;
- return result;
-}
+ // 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);
-void MacroAssembler::PopHandleScope(Register saved, Register scratch) {
- PopHandleScopeHelper(saved, scratch, true);
-}
-
-
-Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) {
- return PopHandleScopeHelper(saved, scratch, false);
+ // 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/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index fe3267c..7b9b843 100644
--- a/src/ia32/macro-assembler-ia32.h
+++ b/src/ia32/macro-assembler-ia32.h
@@ -421,7 +421,7 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
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/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index e2853e8..d435a70 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -1067,7 +1067,7 @@
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/src/ia32/simulator-ia32.h b/src/ia32/simulator-ia32.h
index 94ef7bf..88d0b61 100644
--- a/src/ia32/simulator-ia32.h
+++ b/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 @@
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/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index bb0a46c..90dabed 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -807,13 +807,16 @@
// 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 @@
// 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 @@
!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 @@
// 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 @@
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 @@
// 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 @@
}
-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 @@
// 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 @@
__ 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 @@
}
__ 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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
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 @@
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 @@
// 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 @@
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 @@
// 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::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::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::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* 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* 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 @@
// 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::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::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::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::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::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* 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::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::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::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::CompileLoadArrayLength(String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
// ----------- S t a t e -------------
// -- eax : key
// -- edx : receiver
@@ -2881,7 +2909,7 @@
}
-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::CompileLoadFunctionPrototype(String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
// ----------- S t a t e -------------
// -- eax : key
// -- edx : receiver
@@ -2931,7 +2959,7 @@
// 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/src/ic.cc b/src/ic.cc
index adf365a..58acebc 100644
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -476,9 +476,9 @@
}
-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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
}
-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 @@
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 @@
#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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
-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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
-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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
}
-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 @@
// 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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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_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 @@
// 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 @@
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 @@
// 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 @@
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/src/ic.h b/src/ic.h
index 437e45a..7b8b1bf 100644
--- a/src/ic.h
+++ b/src/ic.h
@@ -191,7 +191,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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/src/liveedit.cc b/src/liveedit.cc
index 3cbd244..49f221a 100644
--- a/src/liveedit.cc
+++ b/src/liveedit.cc
@@ -463,7 +463,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
-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 @@
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 @@
}
-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 @@
}
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/src/liveedit.h b/src/liveedit.h
index d8e2a13..c9bf96d 100644
--- a/src/liveedit.h
+++ b/src/liveedit.h
@@ -83,14 +83,15 @@
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/src/log.cc b/src/log.cc
index 1b0fdeb..2cc2b8f 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -559,7 +559,12 @@
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::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/src/mark-compact.cc b/src/mark-compact.cc
index ad928ea..484497f 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -1264,8 +1264,9 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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/src/mark-compact.h b/src/mark-compact.h
index 72a6fa3..7444c5b 100644
--- a/src/mark-compact.h
+++ b/src/mark-compact.h
@@ -53,7 +53,8 @@
// 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/src/messages.cc b/src/messages.cc
index ec91cc8..42fc3c9 100644
--- a/src/messages.cc
+++ b/src/messages.cc
@@ -152,8 +152,8 @@
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/src/objects-debug.cc b/src/objects-debug.cc
index 5883f8b..c0e5610 100644
--- a/src/objects-debug.cc
+++ b/src/objects-debug.cc
@@ -40,31 +40,37 @@
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/src/objects-inl.h b/src/objects-inl.h
index 11f9d34..4d21017 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -396,28 +396,39 @@
}
-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::IsTheHole() {
- return this == Heap::the_hole_value();
-}
-
-
bool Object::IsNull() {
return this == Heap::null_value();
}
@@ -706,7 +712,7 @@
-Object* Object::ToSmi() {
+MaybeObject* Object::ToSmi() {
if (IsSmi()) return this;
if (IsHeapNumber()) {
double value = HeapNumber::cast(this)->value();
@@ -724,18 +730,27 @@
}
-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 @@
}
-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(ExternalTwoByteString)
CAST_ACCESSOR(JSObject)
CAST_ACCESSOR(Smi)
-CAST_ACCESSOR(Failure)
CAST_ACCESSOR(HeapObject)
CAST_ACCESSOR(HeapNumber)
CAST_ACCESSOR(Oddball)
@@ -1754,7 +1770,7 @@
}
-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 @@
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 @@
}
-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::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 @@
}
-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 @@
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 @@
}
-Object* FixedArray::Copy() {
+MaybeObject* FixedArray::Copy() {
if (length() == 0) return this;
return Heap::CopyFixedArray(this);
}
diff --git a/src/objects.cc b/src/objects.cc
index ac20b2e..c1cb922 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -54,16 +54,18 @@
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() {
+MaybeObject* Object::ToObject() {
Context* global_context = Top::context()->global_context();
if (IsJSObject()) {
return this;
@@ -130,28 +132,28 @@
}
-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::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 @@
// 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(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 = property_dictionary()->Add(name, store_value, details);
- if (dict->IsFailure()) return dict;
+ Object* dict;
+ { MaybeObject* maybe_dict =
+ property_dictionary()->Add(name, store_value, details);
+ if (!maybe_dict->ToObject(&dict)) return maybe_dict;
+ }
set_properties(StringDictionary::cast(dict));
return value;
}
@@ -398,7 +407,7 @@
}
-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 @@
// 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 @@
}
-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::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 @@
}
-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* 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 @@
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 @@
}
-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::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 @@
// 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 @@
(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::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 @@
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 @@
// 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 @@
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 @@
} 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::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::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 @@
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 @@
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::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 @@
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 @@
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::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 @@
// 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::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 @@
// 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 @@
// 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 @@
}
-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 @@
#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 @@
}
-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::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 @@
} 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 @@
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 @@
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 @@
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 @@
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::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::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 @@
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::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 @@
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::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 @@
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 @@
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::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 @@
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 @@
}
-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 @@
}
-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 @@
}
// 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 @@
}
-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::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 @@
< 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 @@
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 @@
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 @@
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* 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 @@
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::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::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 @@
}
-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 @@
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::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 @@
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::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 @@
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::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 @@
}
-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 @@
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::UnionOfKeys(FixedArray* other) {
+MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) {
int len0 = length();
#ifdef DEBUG
if (FLAG_enable_slow_asserts) {
@@ -3606,8 +3775,10 @@
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::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 @@
#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 @@
}
-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 @@
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 @@
++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::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 @@
}
// 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 @@
}
-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::SetPrototype(Object* value) {
+MaybeObject* JSFunction::SetPrototype(Object* value) {
ASSERT(should_have_prototype());
Object* construct_prototype = value;
@@ -5178,8 +5360,10 @@
// 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 @@
}
-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 @@
#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::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 @@
// 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* 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 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 @@
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 @@
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 @@
// 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 @@
// 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::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 @@
}
// 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 @@
}
-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 @@
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::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 @@
// 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 @@
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::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 @@
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 @@
// 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 @@
} 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* 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::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 @@
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 @@
}
-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::GetLocalPropertyPostInterceptor(
+MaybeObject* JSObject::GetLocalPropertyPostInterceptor(
JSObject* receiver,
String* name,
PropertyAttributes* attributes) {
@@ -6894,7 +7123,7 @@
}
-Object* JSObject::GetPropertyWithInterceptor(
+MaybeObject* JSObject::GetPropertyWithInterceptor(
JSObject* receiver,
String* name,
PropertyAttributes* attributes) {
@@ -6923,7 +7152,7 @@
}
}
- Object* result = holder_handle->GetPropertyPostInterceptor(
+ MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
*receiver_handle,
*name_handle,
attributes);
@@ -7278,7 +7507,7 @@
}
-Object* NumberDictionaryShape::AsObject(uint32_t key) {
+MaybeObject* NumberDictionaryShape::AsObject(uint32_t key) {
return Heap::NumberFromUint32(key);
}
@@ -7301,7 +7530,7 @@
}
-Object* StringDictionaryShape::AsObject(String* key) {
+MaybeObject* StringDictionaryShape::AsObject(String* key) {
return key;
}
@@ -7375,9 +7604,11 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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<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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
}
// 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 @@
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 @@
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 @@
}
-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* 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::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* SymbolTable::LookupString(String* string, Object** s) {
+MaybeObject* SymbolTable::LookupString(String* string, Object** s) {
SymbolKey key(string);
return LookupKey(&key, s);
}
@@ -8174,13 +8436,13 @@
}
-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 @@
}
// 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::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::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::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::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 @@
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 @@
}
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 @@
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 @@
}
// 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 @@
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 @@
// 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 @@
}
-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* 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 @@
(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 @@
}
// 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 @@
}
// 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 @@
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 @@
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/src/objects.h b/src/objects.h
index d917a57..87234ea 100644
--- a/src/objects.h
+++ b/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 @@
// 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 @@
// 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 @@
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 @@
// Oddball testing.
INLINE(bool IsUndefined());
- INLINE(bool IsTheHole());
INLINE(bool IsNull());
INLINE(bool IsTrue());
INLINE(bool IsFalse());
@@ -679,38 +704,43 @@
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);
+ 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 Object* GetElement(uint32_t index);
- Object* GetElementWithReceiver(Object* receiver, uint32_t index);
+ 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 @@
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 @@
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 @@
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 @@
// 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 @@
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);
+ MUST_USE_RESULT MaybeObject* 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* 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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
};
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);
+ 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);
- Object* GetElementPostInterceptor(JSObject* receiver, uint32_t index);
+ MaybeObject* 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 MaybeObject* DeletePropertyPostInterceptor(String* name,
+ DeleteMode mode);
+ MUST_USE_RESULT MaybeObject* 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* DeleteElementPostInterceptor(uint32_t index,
+ DeleteMode mode);
+ MUST_USE_RESULT MaybeObject* DeleteElementWithInterceptor(uint32_t index);
PropertyAttributes GetPropertyAttributePostInterceptor(JSObject* receiver,
String* name,
@@ -1711,14 +1749,17 @@
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 @@
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 @@
// 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 @@
// 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 @@
}
// 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 @@
}
// 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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// [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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
//
// 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 @@
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 @@
// 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 @@
#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 @@
// 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/src/parser.cc b/src/parser.cc
index 7690e92..180d0d2 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -4266,11 +4266,9 @@
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/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 1003de1..6b8f2c0 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -617,7 +617,10 @@
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/src/platform-linux.cc b/src/platform-linux.cc
index c01c0d2..eefaec9 100644
--- a/src/platform-linux.cc
+++ b/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 @@
#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 @@
#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 @@
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 @@
// platforms.
if (active_sampler_ != NULL) return;
- vm_thread_ = pthread_self();
-
// Request profiling signals.
struct sigaction sa;
sa.sa_sigaction = ProfilerSignalHandler;
@@ -858,31 +860,38 @@
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/src/platform-macos.cc b/src/platform-macos.cc
index 3e4daf3..5e0e78d 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -206,7 +206,11 @@
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/src/profile-generator.cc b/src/profile-generator.cc
index 977c67c..a4d9a82 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -1319,11 +1319,9 @@
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/src/property.h b/src/property.h
index 01c58de..4715a72 100644
--- a/src/property.h
+++ b/src/property.h
@@ -45,10 +45,12 @@
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/src/runtime.cc b/src/runtime.cc
index 9a604a0..f701c03 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -99,12 +99,14 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
}
-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 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_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_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_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_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_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_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 @@
// 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 @@
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_IsConstructCall(Arguments args) {
+static MaybeObject* Runtime_IsConstructCall(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 0);
JavaScriptFrameIterator it;
@@ -632,7 +654,7 @@
// [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 @@
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_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_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_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_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_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_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_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* 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* 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_DeclareContextSlot(Arguments args) {
+static MaybeObject* Runtime_DeclareContextSlot(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 4);
@@ -1046,7 +1074,7 @@
}
-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_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 @@
// 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_InitializeConstContextSlot(Arguments args) {
+static MaybeObject* Runtime_InitializeConstContextSlot(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 3);
@@ -1326,7 +1355,7 @@
}
-static Object* Runtime_OptimizeObjectForAddingMultipleProperties(
+static MaybeObject* Runtime_OptimizeObjectForAddingMultipleProperties(
Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
@@ -1339,7 +1368,7 @@
}
-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_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_RegExpCloneResult(Arguments args) {
+static MaybeObject* Runtime_RegExpCloneResult(Arguments args) {
ASSERT(args.length() == 1);
Map* regexp_result_map;
{
@@ -1414,10 +1447,13 @@
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_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 @@
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 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_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_FunctionGetName(Arguments args) {
+static MaybeObject* Runtime_FunctionGetName(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -1594,7 +1641,7 @@
}
-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_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_FunctionGetSourceCode(Arguments args) {
+static MaybeObject* Runtime_FunctionGetSourceCode(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -1638,7 +1687,7 @@
}
-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_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_FunctionSetInstanceClassName(Arguments args) {
+static MaybeObject* Runtime_FunctionSetInstanceClassName(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -1674,7 +1723,7 @@
}
-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_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 @@
: 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_SetCode(Arguments args) {
+static MaybeObject* Runtime_SetCode(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
@@ -1772,7 +1824,7 @@
}
-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* 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* Runtime_StringCharCodeAt(Arguments args) {
+static MaybeObject* Runtime_StringCharCodeAt(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -1816,8 +1868,10 @@
// 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_CharFromCode(Arguments args) {
+static MaybeObject* Runtime_CharFromCode(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
return CharFromCode(args[0]);
@@ -2317,10 +2371,11 @@
-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 @@
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* 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 @@
}
-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 @@
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_StringLocaleCompare(Arguments args) {
+static MaybeObject* Runtime_StringLocaleCompare(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -2790,7 +2850,7 @@
}
-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_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 Object* Runtime_RegExpExecMultiple(Arguments args) {
+static MaybeObject* Runtime_RegExpExecMultiple(Arguments args) {
ASSERT(args.length() == 4);
HandleScope handles;
@@ -3221,7 +3281,7 @@
}
-static Object* Runtime_NumberToRadixString(Arguments args) {
+static MaybeObject* Runtime_NumberToRadixString(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -3252,13 +3312,13 @@
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 @@
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 @@
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 @@
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 @@
}
-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::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 @@
}
-static Object* Runtime_GetProperty(Arguments args) {
+static MaybeObject* Runtime_GetProperty(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -3423,7 +3485,7 @@
// 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_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 @@
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 @@
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 @@
// 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 @@
}
-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::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::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 @@
}
-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 @@
// 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_DeleteProperty(Arguments args) {
+static MaybeObject* Runtime_DeleteProperty(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -3789,7 +3854,7 @@
}
-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_HasProperty(Arguments args) {
+static MaybeObject* Runtime_HasProperty(Arguments args) {
NoHandleAllocation na;
ASSERT(args.length() == 2);
@@ -3832,7 +3897,7 @@
}
-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_IsPropertyEnumerable(Arguments args) {
+static MaybeObject* Runtime_IsPropertyEnumerable(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -3864,7 +3929,7 @@
}
-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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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_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_GetArgumentsProperty(Arguments args) {
+static MaybeObject* Runtime_GetArgumentsProperty(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -4132,7 +4197,7 @@
}
-static Object* Runtime_ToFastProperties(Arguments args) {
+static MaybeObject* Runtime_ToFastProperties(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
@@ -4140,27 +4205,28 @@
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 @@
// 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 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_StringFromCharCodeArray(Arguments args) {
+static MaybeObject* Runtime_StringFromCharCodeArray(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -4291,23 +4357,32 @@
// 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 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 @@
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 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 @@
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_StringParseInt(Arguments args) {
+static MaybeObject* Runtime_StringParseInt(Arguments args) {
NoHandleAllocation ha;
CONVERT_CHECKED(String, s, args[0]);
@@ -4519,7 +4598,7 @@
}
-static Object* Runtime_StringParseFloat(Arguments args) {
+static MaybeObject* Runtime_StringParseFloat(Arguments args) {
NoHandleAllocation ha;
CONVERT_CHECKED(String, str, args[0]);
@@ -4536,10 +4615,11 @@
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 @@
// 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 @@
namespace {
+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
+};
+
+
+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;
+ 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;
+ }
+ *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;
- 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_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 @@
// 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 Object* Runtime_StringTrim(Arguments args) {
+static MaybeObject* Runtime_StringTrim(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 3);
@@ -4774,7 +4952,7 @@
}
-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 @@
// 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 @@
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_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 @@
}
-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_NumberToStringSkipCache(Arguments args) {
+static MaybeObject* Runtime_NumberToStringSkipCache(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -4980,7 +5160,7 @@
}
-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_NumberToIntegerMapMinusZero(Arguments args) {
+static MaybeObject* Runtime_NumberToIntegerMapMinusZero(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -5013,7 +5193,7 @@
}
-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_NumberToJSInt32(Arguments args) {
+static MaybeObject* Runtime_NumberToJSInt32(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -5038,7 +5218,7 @@
// 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_NumberAdd(Arguments args) {
+static MaybeObject* Runtime_NumberAdd(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -5067,7 +5247,7 @@
}
-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_NumberMul(Arguments args) {
+static MaybeObject* Runtime_NumberMul(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -5087,7 +5267,7 @@
}
-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_NumberAlloc(Arguments args) {
+static MaybeObject* Runtime_NumberAlloc(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 0);
@@ -5104,7 +5284,7 @@
}
-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_NumberMod(Arguments args) {
+static MaybeObject* Runtime_NumberMod(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -5127,7 +5307,7 @@
}
-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 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 @@
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 @@
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_NumberOr(Arguments args) {
+static MaybeObject* Runtime_NumberOr(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -5295,7 +5477,7 @@
}
-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_NumberXor(Arguments args) {
+static MaybeObject* Runtime_NumberXor(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -5315,7 +5497,7 @@
}
-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_NumberShl(Arguments args) {
+static MaybeObject* Runtime_NumberShl(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -5334,7 +5516,7 @@
}
-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_NumberSar(Arguments args) {
+static MaybeObject* Runtime_NumberSar(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -5354,7 +5536,7 @@
}
-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_StringEquals(Arguments args) {
+static MaybeObject* Runtime_StringEquals(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -5391,7 +5573,7 @@
}
-static Object* Runtime_NumberCompare(Arguments args) {
+static MaybeObject* Runtime_NumberCompare(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 3);
@@ -5406,7 +5588,7 @@
// 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* Runtime_StringCompare(Arguments args) {
+static MaybeObject* Runtime_StringCompare(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -5546,17 +5728,20 @@
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_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_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_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_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_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_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_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_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 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 @@
// 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_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_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_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_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 Object* Runtime_DateMakeDay(Arguments args) {
+static MaybeObject* Runtime_DateMakeDay(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 3);
@@ -6156,7 +6341,7 @@
}
-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_NewArgumentsFast(Arguments args) {
+static MaybeObject* Runtime_NewArgumentsFast(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 3);
@@ -6186,13 +6371,17 @@
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_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 @@
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 @@
}
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_FinalizeInstanceSize(Arguments args) {
+static MaybeObject* Runtime_FinalizeInstanceSize(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
@@ -6353,7 +6543,7 @@
}
-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_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_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_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 @@
}
}
- 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* 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 @@
// 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 @@
}
#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 @@
// 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 @@
}
// 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 Object* Runtime_StoreContextSlot(Arguments args) {
+static MaybeObject* Runtime_StoreContextSlot(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 3);
@@ -6624,10 +6823,8 @@
}
} 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_Throw(Arguments args) {
+static MaybeObject* Runtime_Throw(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
@@ -6671,7 +6868,7 @@
}
-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_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_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 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_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_DebugTrace(Arguments args) {
+static MaybeObject* Runtime_DebugTrace(Arguments args) {
ASSERT(args.length() == 0);
NoHandleAllocation ha;
Top::PrintStack();
@@ -6854,7 +7051,7 @@
}
-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_DateParseString(Arguments args) {
+static MaybeObject* Runtime_DateParseString(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
@@ -6897,7 +7094,7 @@
}
-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_DateLocalTimeOffset(Arguments args) {
+static MaybeObject* Runtime_DateLocalTimeOffset(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 0);
@@ -6915,7 +7112,7 @@
}
-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_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_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 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_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 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 @@
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 @@
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 @@
* 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 @@
{ 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;
+ 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;
}
- if (JSObject::kMaxElementCount - result_length < length_estimate) {
- result_length = JSObject::kMaxElementCount;
- break;
- }
- result_length += length_estimate;
}
}
@@ -7516,7 +7728,7 @@
// 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 @@
// 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 @@
// 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_SwapElements(Arguments args) {
+static MaybeObject* Runtime_SwapElements(Arguments args) {
HandleScope handle_scope;
ASSERT_EQ(3, args.length());
@@ -7612,7 +7827,7 @@
// 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 @@
// 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_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 @@
#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 @@
// 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_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 @@
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 @@
// 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 @@
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 @@
// 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_DebugGetProperty(Arguments args) {
+static MaybeObject* Runtime_DebugGetProperty(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 2);
@@ -7896,7 +8121,7 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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_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_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 @@
// 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 @@
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 @@
};
-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 @@
// 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_DebugPrintScopes(Arguments args) {
+static MaybeObject* Runtime_DebugPrintScopes(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 0);
@@ -8644,60 +8881,21 @@
}
-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 @@
// 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 @@
// 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_GetBreakLocations(Arguments args) {
+static MaybeObject* Runtime_GetBreakLocations(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 1);
@@ -8793,7 +8993,7 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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_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_DebugGetLoadedScripts(Arguments args) {
+static MaybeObject* Runtime_DebugGetLoadedScripts(Arguments args) {
HandleScope scope;
ASSERT(args.length() == 0);
@@ -9350,7 +9560,7 @@
// 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 @@
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 @@
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 @@
// 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 @@
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_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_DebugDisassembleConstructor(Arguments args) {
+static MaybeObject* Runtime_DebugDisassembleConstructor(Arguments args) {
#ifdef DEBUG
HandleScope scope;
ASSERT(args.length() == 1);
@@ -9509,7 +9727,7 @@
}
-static Object* Runtime_FunctionGetInferredName(Arguments args) {
+static MaybeObject* Runtime_FunctionGetInferredName(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
@@ -9545,7 +9763,7 @@
// 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 @@
// 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 @@
// 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 @@
}
// 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 @@
}
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
#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_ProfilerPause(Arguments args) {
+static MaybeObject* Runtime_ProfilerPause(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 2);
@@ -9834,7 +10052,7 @@
// 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 @@
// 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 @@
// 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_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_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* 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 @@
#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 @@
#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_IS_VAR(Arguments args) {
+static MaybeObject* Runtime_IS_VAR(Arguments args) {
UNREACHABLE(); // implemented as macro in the parser
return NULL;
}
@@ -10115,18 +10328,26 @@
};
-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/src/runtime.h b/src/runtime.h
index 2cd95c4..8057d8b 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -297,8 +297,6 @@
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 @@
// 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 @@
// 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);
+ MUST_USE_RESULT static MaybeObject* GetElementOrCharAt(Handle<Object> object,
+ uint32_t index);
+ MUST_USE_RESULT static MaybeObject* GetElement(Handle<Object> object,
+ uint32_t index);
- static Object* SetObjectProperty(Handle<Object> object,
- Handle<Object> key,
- Handle<Object> value,
- PropertyAttributes attr);
+ MUST_USE_RESULT static MaybeObject* 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);
+ MUST_USE_RESULT static MaybeObject* ForceSetObjectProperty(
+ Handle<JSObject> object,
+ Handle<Object> key,
+ Handle<Object> value,
+ PropertyAttributes attr);
- static Object* ForceDeleteObjectProperty(Handle<JSObject> object,
- Handle<Object> key);
+ MUST_USE_RESULT static MaybeObject* ForceDeleteObjectProperty(
+ Handle<JSObject> object,
+ Handle<Object> key);
- static Object* GetObjectProperty(Handle<Object> 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/src/serialize.cc b/src/serialize.cc
index ccba737..763c12f 100644
--- a/src/serialize.cc
+++ b/src/serialize.cc
@@ -337,6 +337,11 @@
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 @@
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 @@
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 @@
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/src/spaces-inl.h b/src/spaces-inl.h
index 8a0dd07..7806223 100644
--- a/src/spaces-inl.h
+++ b/src/spaces-inl.h
@@ -430,7 +430,7 @@
// 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 @@
// 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 @@
// -----------------------------------------------------------------------------
// 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/src/spaces.cc b/src/spaces.cc
index 5bdbcc7..e3fb923 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -873,7 +873,7 @@
}
-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 @@
}
-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 @@
}
-Object* FixedSizeFreeList::Allocate() {
+MaybeObject* FixedSizeFreeList::Allocate() {
if (head_ == NULL) {
return Failure::RetryAfterGC(owner_);
}
@@ -2187,9 +2187,10 @@
// 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 @@
// 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 @@
#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::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::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::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 @@
// 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/src/spaces.h b/src/spaces.h
index 0e6a91e..3ed2fe8 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -425,7 +425,8 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
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 @@
#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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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 @@
// 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/src/strtod.cc b/src/strtod.cc
index ae278bd..0ed1b0d 100644
--- a/src/strtod.cc
+++ b/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 @@
// 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 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 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> 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 @@
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 @@
// 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 @@
// 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 @@
}
+// 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 @@
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/src/stub-cache.cc b/src/stub-cache.cc
index e6df1b4..e794f09 100644
--- a/src/stub-cache.cc
+++ b/src/stub-cache.cc
@@ -93,7 +93,8 @@
}
-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* 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 @@
#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 @@
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* 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* 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 @@
// 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* 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::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 @@
}
-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 @@
#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 @@
// 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* 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 @@
* 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 @@
}
-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* 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 @@
}
}
- Object* result = holder_handle->GetPropertyPostInterceptor(
+ MaybeObject* result = holder_handle->GetPropertyPostInterceptor(
*receiver_handle,
*name_handle,
attrs);
@@ -953,10 +1088,12 @@
* 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* 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* 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* 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 @@
} 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 @@
} 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 @@
} 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 @@
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 @@
} 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 @@
} 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 @@
-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 @@
}
-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::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(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* 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/src/stub-cache.h b/src/stub-cache.h
index e4a9e95..07d2197 100644
--- a/src/stub-cache.h
+++ b/src/stub-cache.h
@@ -56,155 +56,169 @@
// 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 MaybeObject* 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 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,
+ JSObject* receiver,
+ GlobalObject* holder,
+ JSGlobalPropertyCell* cell,
+ bool is_dont_delete);
+
+
+ // ---
+
+ 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 MaybeObject* ComputeKeyedLoadInterceptor(
+ String* name,
+ JSObject* receiver,
+ JSObject* holder);
+
+ MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadArrayLength(
+ String* name,
+ JSArray* receiver);
+
+ MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadStringLength(
+ String* name,
+ String* receiver);
+
+ MUST_USE_RESULT static MaybeObject* ComputeKeyedLoadFunctionPrototype(
String* name,
JSFunction* receiver);
// ---
- MUST_USE_RESULT static Object* ComputeStoreField(String* name,
- JSObject* receiver,
- int field_index,
- Map* transition = NULL);
-
- MUST_USE_RESULT static Object* ComputeStoreNormal();
-
- MUST_USE_RESULT static Object* ComputeStoreGlobal(String* name,
- GlobalObject* receiver,
- JSGlobalPropertyCell* cell);
-
- MUST_USE_RESULT static Object* ComputeStoreCallback(String* name,
- JSObject* receiver,
- AccessorInfo* callback);
-
- MUST_USE_RESULT static Object* ComputeStoreInterceptor(String* name,
- JSObject* 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 MaybeObject* ComputeKeyedStoreField(
+ String* name,
+ JSObject* receiver,
+ int field_index,
+ Map* transition = NULL);
- 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* ComputeCallField(int argc,
+ InLoopFlag in_loop,
+ Code::Kind,
+ String* name,
+ Object* object,
+ JSObject* holder,
+ int index);
- MUST_USE_RESULT static Object* ComputeCallInterceptor(int argc,
+ 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 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 MaybeObject* 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* ComputeCallPreMonomorphic(
+ 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 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 @@
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 @@
// 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 @@
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 @@
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 LoadStubCompiler: public StubCompiler {
public:
- Object* CompileLoadNonexistent(String* name,
- JSObject* object,
- JSObject* last);
+ MUST_USE_RESULT MaybeObject* CompileLoadNonexistent(String* name,
+ JSObject* object,
+ JSObject* last);
- Object* CompileLoadField(JSObject* object,
- JSObject* holder,
- int index,
- String* name);
+ MUST_USE_RESULT MaybeObject* CompileLoadField(JSObject* object,
+ JSObject* holder,
+ int index,
+ String* name);
- 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(JSObject* object,
- JSObject* holder,
- Object* value,
- String* name);
+ MUST_USE_RESULT MaybeObject* CompileLoadConstant(JSObject* object,
+ JSObject* holder,
+ Object* value,
+ String* name);
- Object* CompileLoadInterceptor(JSObject* object,
- JSObject* holder,
- String* name);
+ MUST_USE_RESULT MaybeObject* 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* 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 @@
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);
+ 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) \
- Object* Compile##name##Call(Object* object, \
- JSObject* holder, \
- JSGlobalPropertyCell* cell, \
- JSFunction* function, \
- String* fname);
+#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 @@
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 @@
// 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 @@
public:
explicit ConstructStubCompiler() {}
- Object* CompileConstructStub(SharedFunctionInfo* shared);
+ MUST_USE_RESULT MaybeObject* CompileConstructStub(SharedFunctionInfo* shared);
private:
- Object* GetCode();
+ MaybeObject* GetCode();
};
diff --git a/src/top.cc b/src/top.cc
index 9ce6542..1f0d159 100644
--- a/src/top.cc
+++ b/src/top.cc
@@ -66,6 +66,13 @@
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::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::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 @@
}
-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 @@
}
-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 @@
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 @@
// 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 @@
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 @@
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::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/src/top.h b/src/top.h
index a2ba3dd..e97289f 100644
--- a/src/top.h
+++ b/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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
// 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/src/v8.cc b/src/v8.cc
index b30564a..0623400 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -68,8 +68,12 @@
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/src/version.cc b/src/version.cc
index 6d98b04..4017ae5 100644
--- a/src/version.cc
+++ b/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/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index 6e29b7a..bf5ee5b 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -118,9 +118,11 @@
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/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 2d87667..c179769 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -2484,11 +2484,7 @@
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 @@
// 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/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index 2c946f5..293d8a5 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -315,11 +315,12 @@
}
-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 @@
}
-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 @@
}
-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 @@
}
-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 @@
}
-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);
+ 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();
- return result;
-}
+ // 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);
-void MacroAssembler::PopHandleScope(Register saved, Register scratch) {
- PopHandleScopeHelper(saved, scratch, true);
-}
+ // 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);
-Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) {
- return PopHandleScopeHelper(saved, scratch, false);
+ 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);
+
+ // 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 @@
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 @@
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 @@
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/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index cb91067..2f6e956 100644
--- a/src/x64/macro-assembler-x64.h
+++ b/src/x64/macro-assembler-x64.h
@@ -773,7 +773,7 @@
// 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 @@
// 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 @@
// 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 @@
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/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index 47c19c7..2cf85f1 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -1169,7 +1169,7 @@
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/src/x64/simulator-x64.h b/src/x64/simulator-x64.h
index a0fc3cb..e607c8b 100644
--- a/src/x64/simulator-x64.h
+++ b/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 @@
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/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index eb48da9..3891e1d 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -796,13 +796,16 @@
// 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 @@
}
-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 @@
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 @@
// 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 @@
// 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 @@
__ 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 @@
}
__ 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 @@
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 @@
__ 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 @@
__ 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 @@
__ 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 @@
__ 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 @@
// 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 @@
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 @@
// 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::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::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 @@
// 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::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::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::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* 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::CompileLoadArrayLength(String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
@@ -2042,10 +2079,10 @@
}
-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::CompileLoadFunctionPrototype(String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
@@ -2094,9 +2131,9 @@
}
-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::CompileLoadStringLength(String* name) {
+MaybeObject* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
// ----------- S t a t e -------------
// -- rax : key
// -- rdx : receiver
@@ -2155,9 +2192,9 @@
}
-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::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::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::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* 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* 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 @@
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 @@
// 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 @@
// 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 @@
!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 @@
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 @@
// 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/test/cctest/test-alloc.cc b/test/cctest/test-alloc.cc
index 2936d6e..fcf2ce4 100644
--- a/test/cctest/test-alloc.cc
+++ b/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 @@
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 @@
}
-static Object* TestAccessorGet(Object* object, void*) {
+static MaybeObject* TestAccessorGet(Object* object, void*) {
return AllocateAfterFailures();
}
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index fd44aec..6eb15d8 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -9278,7 +9278,9 @@
// 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 @@
// 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 @@
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 @@
"}"
"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 @@
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 @@
"}"
"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 @@
"}"
"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 @@
"}"
"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 @@
"}"
"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/test/cctest/test-assembler-arm.cc b/test/cctest/test-assembler-arm.cc
index 7c669d3..4f90b61 100644
--- a/test/cctest/test-assembler-arm.cc
+++ b/test/cctest/test-assembler-arm.cc
@@ -69,9 +69,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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/test/cctest/test-assembler-ia32.cc b/test/cctest/test-assembler-ia32.cc
index b60865d..40232ef 100644
--- a/test/cctest/test-assembler-ia32.cc
+++ b/test/cctest/test-assembler-ia32.cc
@@ -71,7 +71,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
__ 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 @@
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/test/cctest/test-compiler.cc b/test/cctest/test-compiler.cc
index 96549a3..b424b7f 100644
--- a/test/cctest/test-compiler.cc
+++ b/test/cctest/test-compiler.cc
@@ -98,7 +98,7 @@
}
-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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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/test/cctest/test-disasm-ia32.cc b/test/cctest/test-disasm-ia32.cc
index b53eaaa..5cd56ac 100644
--- a/test/cctest/test-disasm-ia32.cc
+++ b/test/cctest/test-disasm-ia32.cc
@@ -438,9 +438,10 @@
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/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 126ac21..94d0555 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -58,7 +58,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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/test/cctest/test-log-stack-tracer.cc b/test/cctest/test-log-stack-tracer.cc
index 7d7bd40..65be6bd 100644
--- a/test/cctest/test-log-stack-tracer.cc
+++ b/test/cctest/test-log-stack-tracer.cc
@@ -199,13 +199,6 @@
}
-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 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 @@
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/test/cctest/test-log.cc b/test/cctest/test-log.cc
index 16d0f00..7168737 100644
--- a/test/cctest/test-log.cc
+++ b/test/cctest/test-log.cc
@@ -337,8 +337,8 @@
}
-// 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/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index 531b1f7..ea5afec 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -85,8 +85,7 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
&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/test/cctest/test-serialize.cc b/test/cctest/test-serialize.cc
index 20fb2fe..6a513e5 100644
--- a/test/cctest/test-serialize.cc
+++ b/test/cctest/test-serialize.cc
@@ -576,7 +576,8 @@
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 @@
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 @@
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 @@
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 @@
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/test/cctest/test-spaces.cc b/test/cctest/test-spaces.cc
index db8c54f..06f1bfa 100644
--- a/test/cctest/test-spaces.cc
+++ b/test/cctest/test-spaces.cc
@@ -160,8 +160,8 @@
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 @@
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 @@
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 @@
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/test/cctest/test-strings.cc b/test/cctest/test-strings.cc
index 3a9e4da..3f02b32 100644
--- a/test/cctest/test-strings.cc
+++ b/test/cctest/test-strings.cc
@@ -476,7 +476,7 @@
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/test/cctest/test-strtod.cc b/test/cctest/test-strtod.cc
index ae1c00d..56b26ea 100644
--- a/test/cctest/test-strtod.cc
+++ b/test/cctest/test-strtod.cc
@@ -198,10 +198,58 @@
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/test/mjsunit/bugs/bug-617.js b/test/mjsunit/bugs/bug-617.js
new file mode 100644
index 0000000..f69d4ad
--- /dev/null
+++ b/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/test/mjsunit/define-property-gc.js b/test/mjsunit/define-property-gc.js
new file mode 100644
index 0000000..b38164d
--- /dev/null
+++ b/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/test/mjsunit/math-min-max.js b/test/mjsunit/math-min-max.js
index 72d8ba3..13d54a3 100644
--- a/test/mjsunit/math-min-max.js
+++ b/test/mjsunit/math-min-max.js
@@ -55,7 +55,10 @@
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/test/mjsunit/string-case.js b/test/mjsunit/string-case.js
index 13dcd3e..283e703 100644
--- a/test/mjsunit/string-case.js
+++ b/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/tools/windows-tick-processor.bat b/tools/windows-tick-processor.bat
index 33b1f77..d67f047 100755
--- a/tools/windows-tick-processor.bat
+++ b/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 @@
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 %*