2019-03-07 14:43:43 +00:00
|
|
|
// Copyright 2019 the V8 project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2019-05-22 07:55:37 +00:00
|
|
|
#include "src/execution/isolate.h"
|
2019-05-22 12:44:24 +00:00
|
|
|
#include "src/handles/handles-inl.h"
|
|
|
|
#include "src/handles/handles.h"
|
2020-11-20 16:57:36 +00:00
|
|
|
#include "src/heap/local-heap.h"
|
2019-08-29 14:37:43 +00:00
|
|
|
#include "src/objects/foreign-inl.h"
|
|
|
|
#include "src/objects/managed.h"
|
2019-03-07 14:43:43 +00:00
|
|
|
#include "src/objects/maybe-object.h"
|
|
|
|
#include "src/objects/object-macros.h"
|
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
2019-08-29 14:37:43 +00:00
|
|
|
// ------- Test simple argument evaluation order problems ---------
|
|
|
|
|
2020-11-20 16:57:36 +00:00
|
|
|
void Safepoint() { LocalHeap::Current()->Safepoint(); }
|
|
|
|
|
2019-03-07 14:43:43 +00:00
|
|
|
Handle<Object> CauseGC(Handle<Object> obj, Isolate* isolate) {
|
|
|
|
isolate->heap()->CollectGarbage(OLD_SPACE, GarbageCollectionReason::kTesting);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2019-08-29 14:37:43 +00:00
|
|
|
Object CauseGCRaw(Object obj, Isolate* isolate) {
|
|
|
|
isolate->heap()->CollectGarbage(OLD_SPACE, GarbageCollectionReason::kTesting);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
Managed<Smi> CauseGCManaged(int i, Isolate* isolate) {
|
|
|
|
isolate->heap()->CollectGarbage(OLD_SPACE, GarbageCollectionReason::kTesting);
|
|
|
|
|
|
|
|
return Managed<Smi>::cast(Smi::FromInt(i));
|
|
|
|
}
|
|
|
|
|
2019-03-07 14:43:43 +00:00
|
|
|
void TwoArgumentsFunction(Object a, Object b) {
|
2019-08-29 14:37:43 +00:00
|
|
|
a.Print();
|
|
|
|
b.Print();
|
2019-03-07 14:43:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TestTwoArguments(Isolate* isolate) {
|
|
|
|
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
Handle<JSObject> obj2 = isolate->factory()->NewJSObjectWithNullProto();
|
2019-08-29 14:37:43 +00:00
|
|
|
// Should cause warning.
|
2019-03-07 14:43:43 +00:00
|
|
|
TwoArgumentsFunction(*CauseGC(obj1, isolate), *CauseGC(obj2, isolate));
|
|
|
|
}
|
|
|
|
|
|
|
|
void TwoSizeTArgumentsFunction(size_t a, size_t b) {
|
|
|
|
USE(a);
|
|
|
|
USE(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestTwoSizeTArguments(Isolate* isolate) {
|
|
|
|
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
Handle<JSObject> obj2 = isolate->factory()->NewJSObjectWithNullProto();
|
2019-08-29 14:37:43 +00:00
|
|
|
// Should cause warning.
|
2019-03-07 14:43:43 +00:00
|
|
|
TwoSizeTArgumentsFunction(sizeof(*CauseGC(obj1, isolate)),
|
|
|
|
sizeof(*CauseGC(obj2, isolate)));
|
|
|
|
}
|
|
|
|
|
2019-08-29 14:37:43 +00:00
|
|
|
// --------- Test problems with method arguments ----------
|
|
|
|
|
2019-03-07 14:43:43 +00:00
|
|
|
class SomeObject : public Object {
|
|
|
|
public:
|
2019-08-29 14:37:43 +00:00
|
|
|
void Method(Object a) { a.Print(); }
|
2019-03-07 14:43:43 +00:00
|
|
|
|
2019-03-13 09:47:24 +00:00
|
|
|
SomeObject& operator=(const Object& b) {
|
|
|
|
this->Print();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2019-03-07 14:43:43 +00:00
|
|
|
DECL_CAST(SomeObject)
|
|
|
|
|
|
|
|
OBJECT_CONSTRUCTORS(SomeObject, Object);
|
|
|
|
};
|
|
|
|
|
|
|
|
void TestMethodCall(Isolate* isolate) {
|
|
|
|
SomeObject obj;
|
|
|
|
Handle<SomeObject> so = handle(obj, isolate);
|
|
|
|
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
|
2019-08-29 14:37:43 +00:00
|
|
|
// Should cause warning.
|
2019-03-07 14:43:43 +00:00
|
|
|
so->Method(*CauseGC(obj1, isolate));
|
2019-08-29 14:37:43 +00:00
|
|
|
// Should cause warning.
|
|
|
|
so->Method(CauseGCRaw(*obj1, isolate));
|
2019-03-07 14:43:43 +00:00
|
|
|
}
|
|
|
|
|
2019-03-13 09:47:24 +00:00
|
|
|
void TestOperatorCall(Isolate* isolate) {
|
|
|
|
SomeObject obj;
|
|
|
|
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
|
2019-08-29 14:37:43 +00:00
|
|
|
// Should not cause warning.
|
2019-03-13 09:47:24 +00:00
|
|
|
obj = *CauseGC(obj1, isolate);
|
|
|
|
}
|
|
|
|
|
2019-08-29 14:37:43 +00:00
|
|
|
// --------- Test for templated sub-classes of Object ----------
|
|
|
|
|
|
|
|
void TestFollowingTemplates(Isolate* isolate) {
|
|
|
|
// Should cause warning.
|
|
|
|
CauseGCManaged(42, isolate);
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------- Test for correctly resolving virtual methods ----------
|
|
|
|
|
|
|
|
class BaseObject {
|
|
|
|
public:
|
|
|
|
virtual Handle<Object> VirtualCauseGC(Handle<Object> obj, Isolate* isolate) {
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DerivedObject : public BaseObject {
|
|
|
|
public:
|
|
|
|
Handle<Object> VirtualCauseGC(Handle<Object> obj, Isolate* isolate) override {
|
|
|
|
isolate->heap()->CollectGarbage(OLD_SPACE,
|
|
|
|
GarbageCollectionReason::kTesting);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void TestFollowingVirtualFunctions(Isolate* isolate) {
|
|
|
|
DerivedObject derived;
|
|
|
|
BaseObject* base = &derived;
|
|
|
|
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
|
|
|
|
SomeObject so;
|
|
|
|
Handle<SomeObject> so_handle = handle(so, isolate);
|
|
|
|
// Should cause warning.
|
|
|
|
so_handle->Method(*derived.VirtualCauseGC(obj1, isolate));
|
|
|
|
// Should cause warning.
|
|
|
|
so_handle->Method(*base->VirtualCauseGC(obj1, isolate));
|
|
|
|
}
|
|
|
|
|
2019-11-26 13:06:29 +00:00
|
|
|
// --------- Test for correctly resolving static methods ----------
|
|
|
|
|
|
|
|
class SomeClass {
|
|
|
|
public:
|
|
|
|
static Handle<Object> StaticCauseGC(Handle<Object> obj, Isolate* isolate) {
|
|
|
|
isolate->heap()->CollectGarbage(OLD_SPACE,
|
|
|
|
GarbageCollectionReason::kTesting);
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void TestFollowingStaticFunctions(Isolate* isolate) {
|
|
|
|
SomeObject so;
|
|
|
|
Handle<SomeObject> so_handle = handle(so, isolate);
|
|
|
|
|
|
|
|
Handle<JSObject> obj1 = isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
// Should cause warning.
|
|
|
|
so_handle->Method(*SomeClass::StaticCauseGC(obj1, isolate));
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------- Test basic dead variable analysis ----------
|
|
|
|
|
|
|
|
void TestDeadVarAnalysis(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
CauseGCRaw(raw_obj, isolate);
|
|
|
|
|
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
2020-11-20 16:57:36 +00:00
|
|
|
void TestDeadVarBecauseOfSafepointAnalysis(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
Safepoint();
|
|
|
|
|
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
2019-11-26 17:15:58 +00:00
|
|
|
void TestGuardedDeadVarAnalysis(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
// Note: having DisableGCMole with the same function as CauseGC
|
|
|
|
// normally doesn't make sense, but we want to test whether the guards
|
|
|
|
// are recognized by GCMole.
|
|
|
|
DisableGCMole no_gc_mole;
|
|
|
|
CauseGCRaw(raw_obj, isolate);
|
|
|
|
|
|
|
|
// Shouldn't cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestGuardedDeadVarAnalysis2(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
|
[asserts] Add combination assert scopes
Add a "combination" assert scope class, which combines multiple existing
assert scopes. This will allow scopes with functional overlap, e.g.
DisallowGarbageCollection and DisallowHeapAllocation, to share an assert
type rather than rather than requiring users to remember to set both. To
demonstrate this, this redefines DisallowGarbageCollection to a
combination of DisallowHeapAllocation and a new DisallowSafepoints, and
some of the DCHECKs checking both are simplified to only check one or
the other, as appropriate.
The combination classes become subclasses of the existing assert scopes,
so that they can be used in their place as e.g. a function parameter,
e.g. DisallowGarbageCollection can be passed to a function expecting
const DisallowHeapAllocation&.
As a drive-by, this also changes the per-thread assert scopes to use a
bitmask, rather than a bool array, to store their per-thread data. The
per-isolate scopes already used a bitmask, so this unifies the
behaviour between the two.
Change-Id: I209e0a56f45e124c0ccadbd9fb77f39e070612fe
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2534814
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71231}
2020-11-17 12:00:23 +00:00
|
|
|
// Note: having DisallowGarbageCollection with the same function as CauseGC
|
2021-01-12 09:35:12 +00:00
|
|
|
// normally doesn't make sense, but we want to test whether the guards
|
2019-11-26 17:15:58 +00:00
|
|
|
// are recognized by GCMole.
|
[asserts] Add combination assert scopes
Add a "combination" assert scope class, which combines multiple existing
assert scopes. This will allow scopes with functional overlap, e.g.
DisallowGarbageCollection and DisallowHeapAllocation, to share an assert
type rather than rather than requiring users to remember to set both. To
demonstrate this, this redefines DisallowGarbageCollection to a
combination of DisallowHeapAllocation and a new DisallowSafepoints, and
some of the DCHECKs checking both are simplified to only check one or
the other, as appropriate.
The combination classes become subclasses of the existing assert scopes,
so that they can be used in their place as e.g. a function parameter,
e.g. DisallowGarbageCollection can be passed to a function expecting
const DisallowHeapAllocation&.
As a drive-by, this also changes the per-thread assert scopes to use a
bitmask, rather than a bool array, to store their per-thread data. The
per-isolate scopes already used a bitmask, so this unifies the
behaviour between the two.
Change-Id: I209e0a56f45e124c0ccadbd9fb77f39e070612fe
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2534814
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71231}
2020-11-17 12:00:23 +00:00
|
|
|
DisallowGarbageCollection no_gc;
|
2019-11-26 17:15:58 +00:00
|
|
|
CauseGCRaw(raw_obj, isolate);
|
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
// Should cause warning.
|
2019-11-26 17:15:58 +00:00
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
2020-11-20 16:57:36 +00:00
|
|
|
void TestGuardedAgainstSafepointDeadVarAnalysis(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
// Note: having DisableGCMole with the same function as CauseGC
|
|
|
|
// normally doesn't make sense, but we want to test whether the guards
|
|
|
|
// are recognized by GCMole.
|
|
|
|
DisableGCMole no_gc_mole;
|
|
|
|
Safepoint();
|
|
|
|
|
|
|
|
// Shouldn't cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestGuardedAgainstSafepointDeadVarAnalysis2(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
|
2020-11-20 16:57:36 +00:00
|
|
|
// Note: having DisallowGarbageCollection with the same function as CauseGC
|
2021-01-12 09:35:12 +00:00
|
|
|
// normally doesn't make sense, but we want to test whether the guards
|
2020-11-20 16:57:36 +00:00
|
|
|
// are recognized by GCMole.
|
|
|
|
DisallowGarbageCollection no_gc;
|
|
|
|
Safepoint();
|
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
// Should cause warning.
|
2020-11-20 16:57:36 +00:00
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
void TestGuardedAgainstSafepointDeadVarAnalysis3(Isolate* isolate) {
|
2019-11-26 17:15:58 +00:00
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
2021-01-12 09:35:12 +00:00
|
|
|
// Note: having DisallowGarbageCollection with the same function as CauseGC
|
|
|
|
// normally doesn't make sense, but we want to test whether the guards
|
|
|
|
// are recognized by GCMole.
|
|
|
|
DisallowGarbageCollection no_gc;
|
|
|
|
Safepoint();
|
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
{
|
|
|
|
DisableGCMole no_gc_mole;
|
|
|
|
// Shouldn't cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
2019-11-26 17:15:58 +00:00
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
void TestOnlyHeapGuardedDeadVarAnalysisInCompound(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
2020-11-20 16:57:36 +00:00
|
|
|
// {DisallowHeapAccess} has a {DisallowHeapAllocation}, but no
|
|
|
|
// {DisallowSafepoints}, so it could see objects move due to safepoints.
|
2019-11-26 17:15:58 +00:00
|
|
|
DisallowHeapAccess no_gc;
|
|
|
|
CauseGCRaw(raw_obj, isolate);
|
2021-01-12 09:35:12 +00:00
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
2019-11-26 17:15:58 +00:00
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
void TestOnlyHeapGuardedDeadVarAnalysisInCompound2(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
// {DisallowHeapAccess} has a {DisallowHeapAllocation}, but no
|
|
|
|
// {DisallowSafepoints}, so it could see objects move due to safepoints.
|
|
|
|
DisallowHeapAccess no_gc;
|
|
|
|
CauseGCRaw(raw_obj, isolate);
|
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
DisableGCMole no_gc_mole;
|
2020-11-20 16:57:36 +00:00
|
|
|
// Should cause warning.
|
2019-11-26 17:15:58 +00:00
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestGuardedDeadVarAnalysisNested(JSObject raw_obj, Isolate* isolate) {
|
|
|
|
CauseGCRaw(raw_obj, isolate);
|
2020-06-24 08:33:59 +00:00
|
|
|
// Should cause warning.
|
2019-11-26 17:15:58 +00:00
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestGuardedDeadVarAnalysisCaller(Isolate* isolate) {
|
2021-01-12 09:35:12 +00:00
|
|
|
DisableGCMole no_gc_mole;
|
2019-11-26 17:15:58 +00:00
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
2021-01-12 09:35:12 +00:00
|
|
|
TestGuardedDeadVarAnalysisNested(raw_obj, isolate);
|
|
|
|
// Shouldn't cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TestGuardedDeadVarAnalysisCaller2(Isolate* isolate) {
|
|
|
|
DisallowGarbageCollection no_gc;
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
TestGuardedDeadVarAnalysisNested(raw_obj, isolate);
|
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
2019-11-26 17:15:58 +00:00
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
void TestGuardedDeadVarAnalysisCaller3(Isolate* isolate) {
|
|
|
|
DisallowHeapAccess no_gc;
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
2019-11-26 17:15:58 +00:00
|
|
|
TestGuardedDeadVarAnalysisNested(raw_obj, isolate);
|
2021-01-12 09:35:12 +00:00
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
2020-06-24 08:33:59 +00:00
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
void TestGuardedDeadVarAnalysisCaller4(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
TestGuardedDeadVarAnalysisNested(raw_obj, isolate);
|
|
|
|
// Should cause warning.
|
2020-06-24 08:33:59 +00:00
|
|
|
raw_obj.Print();
|
2019-11-26 17:15:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
JSObject GuardedAllocation(Isolate* isolate) {
|
2020-11-20 16:57:36 +00:00
|
|
|
DisallowGarbageCollection no_gc;
|
2019-11-26 17:15:58 +00:00
|
|
|
return *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
}
|
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
JSObject GuardedAllocation2(Isolate* isolate) {
|
|
|
|
DisableGCMole no_gc_mole;
|
|
|
|
return *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
}
|
|
|
|
|
2019-11-26 17:15:58 +00:00
|
|
|
void TestNestedDeadVarAnalysis(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = GuardedAllocation(isolate);
|
|
|
|
CauseGCRaw(raw_obj, isolate);
|
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
void TestNestedDeadVarAnalysis2(Isolate* isolate) {
|
|
|
|
DisableGCMole no_gc_mole;
|
|
|
|
JSObject raw_obj = GuardedAllocation(isolate);
|
|
|
|
CauseGCRaw(raw_obj, isolate);
|
|
|
|
// Shouldn't cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
2020-10-26 16:22:56 +00:00
|
|
|
// Test that putting a guard in the middle of the function doesn't
|
|
|
|
// mistakenly cover the whole scope of the raw variable.
|
|
|
|
void TestGuardedDeadVarAnalysisMidFunction(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
CauseGCRaw(raw_obj, isolate);
|
|
|
|
// Guarding the rest of the function from triggering a GC.
|
2020-11-20 16:57:36 +00:00
|
|
|
DisallowGarbageCollection no_gc;
|
2020-10-26 16:22:56 +00:00
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
2021-01-12 09:35:12 +00:00
|
|
|
// Test that putting a guard in the middle of the function doesn't
|
|
|
|
// mistakenly cover the whole scope of the raw variable.
|
|
|
|
void TestGuardedDeadVarAnalysisMidFunction2(Isolate* isolate) {
|
|
|
|
JSObject raw_obj = *isolate->factory()->NewJSObjectWithNullProto();
|
|
|
|
CauseGCRaw(raw_obj, isolate);
|
|
|
|
// Guarding the rest of the function from triggering a GC.
|
|
|
|
DisableGCMole no_gc_mole;
|
|
|
|
// Should cause warning.
|
|
|
|
raw_obj.Print();
|
|
|
|
}
|
|
|
|
|
2019-03-07 14:43:43 +00:00
|
|
|
} // namespace internal
|
|
|
|
} // namespace v8
|