__ mov(ip, Operand(pending_message_obj));
__ ldr(r1, MemOperand(ip));
__ push(r1);
+
+ ClearPendingMessage();
}
}
+void FullCodeGenerator::ClearPendingMessage() {
+ DCHECK(!result_register().is(r1));
+ ExternalReference pending_message_obj =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ __ LoadRoot(r1, Heap::kTheHoleValueRootIndex);
+ __ mov(ip, Operand(pending_message_obj));
+ __ str(r1, MemOperand(ip));
+}
+
+
#undef __
__ Mov(x10, pending_message_obj);
__ Ldr(x10, MemOperand(x10));
__ Push(x10);
+
+ ClearPendingMessage();
}
}
+void FullCodeGenerator::ClearPendingMessage() {
+ DCHECK(!result_register().is(x10));
+ ExternalReference pending_message_obj =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ __ LoadRoot(x10, Heap::kTheHoleValueRootIndex);
+ __ Mov(x13, pending_message_obj);
+ __ Str(x10, MemOperand(x13));
+}
+
+
#undef __
}
try_control.EndTry();
+ // Clear message object as we enter the catch block.
+ ExternalReference message_object =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ Node* the_hole = jsgraph()->TheHoleConstant();
+ BuildStoreExternal(message_object, kMachAnyTagged, the_hole);
+
// Create a catch scope that binds the exception.
Node* exception = try_control.GetExceptionNode();
Unique<String> name = MakeUnique(stmt->variable()->name());
environment()->Push(result);
environment()->Push(message);
+ // Clear message object as we enter the finally block.
+ Node* the_hole = jsgraph()->TheHoleConstant();
+ BuildStoreExternal(message_object, kMachAnyTagged, the_hole);
+
// Evaluate the finally-block.
Visit(stmt->finally_block());
try_control.EndFinally();
Label try_entry, handler_entry, exit;
__ jmp(&try_entry);
__ bind(&handler_entry);
+
+ ClearPendingMessage();
// Exception handler code, the exception is in the result register.
// Extend the context before executing the catch block.
{ Comment cmnt(masm_, "[ Extend catch context");
void ExitTryBlock(int handler_index);
void EnterFinallyBlock();
void ExitFinallyBlock();
+ void ClearPendingMessage();
// Loop nesting counter.
int loop_depth() { return loop_depth_; }
ExternalReference::address_of_pending_message_obj(isolate());
__ mov(edx, Operand::StaticVariable(pending_message_obj));
__ push(edx);
+
+ ClearPendingMessage();
}
}
+void FullCodeGenerator::ClearPendingMessage() {
+ DCHECK(!result_register().is(edx));
+ ExternalReference pending_message_obj =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ __ mov(edx, Immediate(isolate()->factory()->the_hole_value()));
+ __ mov(Operand::StaticVariable(pending_message_obj), edx);
+}
+
+
#undef __
__ li(at, Operand(pending_message_obj));
__ lw(a1, MemOperand(at));
__ push(a1);
+
+ ClearPendingMessage();
}
}
+void FullCodeGenerator::ClearPendingMessage() {
+ DCHECK(!result_register().is(a1));
+ ExternalReference pending_message_obj =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ __ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
+ __ li(at, Operand(pending_message_obj));
+ __ sw(a1, MemOperand(at));
+}
+
+
#undef __
__ li(at, Operand(pending_message_obj));
__ ld(a1, MemOperand(at));
__ push(a1);
+
+ ClearPendingMessage();
}
}
+void FullCodeGenerator::ClearPendingMessage() {
+ DCHECK(!result_register().is(a1));
+ ExternalReference pending_message_obj =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ __ LoadRoot(a1, Heap::kTheHoleValueRootIndex);
+ __ li(at, Operand(pending_message_obj));
+ __ sd(a1, MemOperand(at));
+}
+
+
#undef __
__ mov(ip, Operand(pending_message_obj));
__ LoadP(r4, MemOperand(ip));
__ push(r4);
+
+ ClearPendingMessage();
}
}
+void FullCodeGenerator::ClearPendingMessage() {
+ DCHECK(!result_register().is(r4));
+ ExternalReference pending_message_obj =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ __ LoadRoot(r4, Heap::kTheHoleValueRootIndex);
+ __ mov(ip, Operand(pending_message_obj));
+ __ StoreP(r4, MemOperand(ip));
+}
+
+
#undef __
ExternalReference::address_of_pending_message_obj(isolate());
__ Load(rdx, pending_message_obj);
__ Push(rdx);
+
+ ClearPendingMessage();
}
}
+void FullCodeGenerator::ClearPendingMessage() {
+ DCHECK(!result_register().is(rdx));
+ ExternalReference pending_message_obj =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ __ LoadRoot(rdx, Heap::kTheHoleValueRootIndex);
+ __ Store(pending_message_obj, rdx);
+}
+
+
#undef __
ExternalReference::address_of_pending_message_obj(isolate());
__ mov(edx, Operand::StaticVariable(pending_message_obj));
__ push(edx);
+
+ ClearPendingMessage();
}
}
+void FullCodeGenerator::ClearPendingMessage() {
+ DCHECK(!result_register().is(edx));
+ ExternalReference pending_message_obj =
+ ExternalReference::address_of_pending_message_obj(isolate());
+ __ mov(edx, Immediate(isolate()->factory()->the_hole_value()));
+ __ mov(Operand::StaticVariable(pending_message_obj), edx);
+}
+
+
#undef __
bytes = tracer->NewSpaceAllocatedBytesInLast(100);
CHECK_EQ((counter3 - counter1) * 100 / (time3 - time1), bytes);
}
+
+
+static void CheckLeak(const v8::FunctionCallbackInfo<v8::Value>& args) {
+ Isolate* isolate = CcTest::i_isolate();
+ Object* message =
+ *reinterpret_cast<Object**>(isolate->pending_message_obj_address());
+ CHECK(message->IsTheHole());
+}
+
+
+TEST(MessageObjectLeak) {
+ CcTest::InitializeVM();
+ v8::Isolate* isolate = CcTest::isolate();
+ v8::HandleScope scope(isolate);
+ v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
+ global->Set(v8::String::NewFromUtf8(isolate, "check"),
+ v8::FunctionTemplate::New(isolate, CheckLeak));
+ v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
+ v8::Context::Scope cscope(context);
+
+ const char* test =
+ "try {"
+ " throw 'message 1';"
+ "} catch (e) {"
+ "}"
+ "check();"
+ "L: try {"
+ " throw 'message 2';"
+ "} finally {"
+ " break L;"
+ "}"
+ "check();";
+ CompileRun(test);
+
+ const char* flag = "--turbo-filter=*";
+ FlagList::SetFlagsFromString(flag, StrLength(flag));
+ FLAG_always_opt = true;
+ FLAG_turbo_exceptions = true;
+
+ CompileRun(test);
+}