[ic] Remove unnecessary access rights checks from the IC handlers.
The reasons are: 1) Type feedback vectors are not shared between different native contexts and therefore the IC handler created for one native context will not be reused in other native context. 2) Access rights revocation is not supported at all, therefore given (1) once we pass the access check we don't have to check access rights again. BUG=v8:5561 Review-Url: https://codereview.chromium.org/2455953002 Cr-Commit-Position: refs/heads/master@{#40627}
This commit is contained in:
parent
6ea4061b8d
commit
8ba4af44ea
@ -1830,90 +1830,6 @@ void MacroAssembler::PopStackHandler() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch,
|
||||
Label* miss) {
|
||||
Label same_contexts;
|
||||
|
||||
DCHECK(!holder_reg.is(scratch));
|
||||
DCHECK(!holder_reg.is(ip));
|
||||
DCHECK(!scratch.is(ip));
|
||||
|
||||
// Load current lexical context from the active StandardFrame, which
|
||||
// may require crawling past STUB frames.
|
||||
Label load_context;
|
||||
Label has_context;
|
||||
DCHECK(!ip.is(scratch));
|
||||
mov(ip, fp);
|
||||
bind(&load_context);
|
||||
ldr(scratch, MemOperand(ip, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
JumpIfNotSmi(scratch, &has_context);
|
||||
ldr(ip, MemOperand(ip, CommonFrameConstants::kCallerFPOffset));
|
||||
b(&load_context);
|
||||
bind(&has_context);
|
||||
|
||||
// In debug mode, make sure the lexical context is set.
|
||||
#ifdef DEBUG
|
||||
cmp(scratch, Operand::Zero());
|
||||
Check(ne, kWeShouldNotHaveAnEmptyLexicalContext);
|
||||
#endif
|
||||
|
||||
// Load the native context of the current context.
|
||||
ldr(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// Cannot use ip as a temporary in this verification code. Due to the fact
|
||||
// that ip is clobbered as part of cmp with an object Operand.
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
// Read the first word and compare to the native_context_map.
|
||||
ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
|
||||
LoadRoot(ip, Heap::kNativeContextMapRootIndex);
|
||||
cmp(holder_reg, ip);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
pop(holder_reg); // Restore holder.
|
||||
}
|
||||
|
||||
// Check if both contexts are the same.
|
||||
ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
cmp(scratch, Operand(ip));
|
||||
b(eq, &same_contexts);
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// Cannot use ip as a temporary in this verification code. Due to the fact
|
||||
// that ip is clobbered as part of cmp with an object Operand.
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
mov(holder_reg, ip); // Move ip to its holding place.
|
||||
LoadRoot(ip, Heap::kNullValueRootIndex);
|
||||
cmp(holder_reg, ip);
|
||||
Check(ne, kJSGlobalProxyContextShouldNotBeNull);
|
||||
|
||||
ldr(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
|
||||
LoadRoot(ip, Heap::kNativeContextMapRootIndex);
|
||||
cmp(holder_reg, ip);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
// Restore ip is not needed. ip is reloaded below.
|
||||
pop(holder_reg); // Restore holder.
|
||||
// Restore ip to holder's context.
|
||||
ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
}
|
||||
|
||||
// Check that the security token in the calling global object is
|
||||
// compatible with the security token in the receiving global
|
||||
// object.
|
||||
int token_offset = Context::kHeaderSize +
|
||||
Context::SECURITY_TOKEN_INDEX * kPointerSize;
|
||||
|
||||
ldr(scratch, FieldMemOperand(scratch, token_offset));
|
||||
ldr(ip, FieldMemOperand(ip, token_offset));
|
||||
cmp(scratch, Operand(ip));
|
||||
b(ne, miss);
|
||||
|
||||
bind(&same_contexts);
|
||||
}
|
||||
|
||||
|
||||
// Compute the hash code from the untagged key. This must be kept in sync with
|
||||
// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
|
||||
// code-stub-hydrogen.cc
|
||||
|
@ -728,13 +728,6 @@ class MacroAssembler: public Assembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Inline caching support
|
||||
|
||||
// Generate code for checking access rights - used for security checks
|
||||
// on access to global objects across environments. The holder register
|
||||
// is left untouched, whereas both scratch registers are clobbered.
|
||||
void CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch,
|
||||
Label* miss);
|
||||
|
||||
void GetNumberHash(Register t0, Register scratch);
|
||||
|
||||
inline void MarkCode(NopMarkerTypes type) {
|
||||
|
@ -3753,79 +3753,6 @@ void MacroAssembler::EmitSeqStringSetCharCheck(
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
Label* miss) {
|
||||
DCHECK(!AreAliased(holder_reg, scratch1, scratch2));
|
||||
Label same_contexts;
|
||||
|
||||
// Load current lexical context from the active StandardFrame, which
|
||||
// may require crawling past STUB frames.
|
||||
Label load_context;
|
||||
Label has_context;
|
||||
Mov(scratch2, fp);
|
||||
bind(&load_context);
|
||||
Ldr(scratch1,
|
||||
MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
JumpIfNotSmi(scratch1, &has_context);
|
||||
Ldr(scratch2, MemOperand(scratch2, CommonFrameConstants::kCallerFPOffset));
|
||||
B(&load_context);
|
||||
bind(&has_context);
|
||||
|
||||
// In debug mode, make sure the lexical context is set.
|
||||
#ifdef DEBUG
|
||||
Cmp(scratch1, 0);
|
||||
Check(ne, kWeShouldNotHaveAnEmptyLexicalContext);
|
||||
#endif
|
||||
|
||||
// Load the native context of the current context.
|
||||
Ldr(scratch1, ContextMemOperand(scratch1, Context::NATIVE_CONTEXT_INDEX));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// Read the first word and compare to the native_context_map.
|
||||
Ldr(scratch2, FieldMemOperand(scratch1, HeapObject::kMapOffset));
|
||||
CompareRoot(scratch2, Heap::kNativeContextMapRootIndex);
|
||||
Check(eq, kExpectedNativeContext);
|
||||
}
|
||||
|
||||
// Check if both contexts are the same.
|
||||
Ldr(scratch2, FieldMemOperand(holder_reg,
|
||||
JSGlobalProxy::kNativeContextOffset));
|
||||
Cmp(scratch1, scratch2);
|
||||
B(&same_contexts, eq);
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// We're short on scratch registers here, so use holder_reg as a scratch.
|
||||
Push(holder_reg);
|
||||
Register scratch3 = holder_reg;
|
||||
|
||||
CompareRoot(scratch2, Heap::kNullValueRootIndex);
|
||||
Check(ne, kExpectedNonNullContext);
|
||||
|
||||
Ldr(scratch3, FieldMemOperand(scratch2, HeapObject::kMapOffset));
|
||||
CompareRoot(scratch3, Heap::kNativeContextMapRootIndex);
|
||||
Check(eq, kExpectedNativeContext);
|
||||
Pop(holder_reg);
|
||||
}
|
||||
|
||||
// Check that the security token in the calling global object is
|
||||
// compatible with the security token in the receiving global
|
||||
// object.
|
||||
int token_offset = Context::kHeaderSize +
|
||||
Context::SECURITY_TOKEN_INDEX * kPointerSize;
|
||||
|
||||
Ldr(scratch1, FieldMemOperand(scratch1, token_offset));
|
||||
Ldr(scratch2, FieldMemOperand(scratch2, token_offset));
|
||||
Cmp(scratch1, scratch2);
|
||||
B(miss, ne);
|
||||
|
||||
Bind(&same_contexts);
|
||||
}
|
||||
|
||||
|
||||
// Compute the hash code from the untagged key. This must be kept in sync with
|
||||
// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
|
||||
// code-stub-hydrogen.cc
|
||||
|
@ -1590,14 +1590,6 @@ class MacroAssembler : public Assembler {
|
||||
Register scratch,
|
||||
uint32_t encoding_mask);
|
||||
|
||||
// Generate code for checking access rights - used for security checks
|
||||
// on access to global objects across environments. The holder register
|
||||
// is left untouched, whereas both scratch registers are clobbered.
|
||||
void CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
Label* miss);
|
||||
|
||||
// Hash the interger value in 'key' register.
|
||||
// It uses the same algorithm as ComputeIntegerHash in utils.h.
|
||||
void GetNumberHash(Register key, Register scratch);
|
||||
|
@ -116,10 +116,6 @@ namespace internal {
|
||||
V(kInvalidLhsInCountOperation, "Invalid lhs in count operation") \
|
||||
V(kInvalidMinLength, "Invalid min_length") \
|
||||
V(kInvalidRegisterFileInGenerator, "invalid register file in generator") \
|
||||
V(kJSGlobalObjectNativeContextShouldBeANativeContext, \
|
||||
"JSGlobalObject::native_context should be a native context") \
|
||||
V(kJSGlobalProxyContextShouldNotBeNull, \
|
||||
"JSGlobalProxy::context() should not be null") \
|
||||
V(kJSObjectWithFastElementsMapHasSlowElements, \
|
||||
"JSObject with fast elements map has slow elements") \
|
||||
V(kLetBindingReInitialization, "Let binding re-initialization") \
|
||||
@ -256,8 +252,6 @@ namespace internal {
|
||||
V(kUnsupportedTaggedImmediate, "Unsupported tagged immediate") \
|
||||
V(kUnstableConstantTypeHeapObject, "Unstable constant-type heap object") \
|
||||
V(kVariableResolvedToWithContext, "Variable resolved to with context") \
|
||||
V(kWeShouldNotHaveAnEmptyLexicalContext, \
|
||||
"We should not have an empty lexical context") \
|
||||
V(kWithStatement, "WithStatement") \
|
||||
V(kWrongFunctionContext, "Wrong context passed to function") \
|
||||
V(kWrongAddressOrValuePassedToRecordWrite, \
|
||||
|
@ -1282,79 +1282,6 @@ void MacroAssembler::PopStackHandler() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
Label* miss) {
|
||||
Label same_contexts;
|
||||
|
||||
DCHECK(!holder_reg.is(scratch1));
|
||||
DCHECK(!holder_reg.is(scratch2));
|
||||
DCHECK(!scratch1.is(scratch2));
|
||||
|
||||
// Load current lexical context from the active StandardFrame, which
|
||||
// may require crawling past STUB frames.
|
||||
Label load_context;
|
||||
Label has_context;
|
||||
mov(scratch2, ebp);
|
||||
bind(&load_context);
|
||||
mov(scratch1,
|
||||
MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
JumpIfNotSmi(scratch1, &has_context);
|
||||
mov(scratch2, MemOperand(scratch2, CommonFrameConstants::kCallerFPOffset));
|
||||
jmp(&load_context);
|
||||
bind(&has_context);
|
||||
|
||||
// When generating debug code, make sure the lexical context is set.
|
||||
if (emit_debug_code()) {
|
||||
cmp(scratch1, Immediate(0));
|
||||
Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
|
||||
}
|
||||
// Load the native context of the current context.
|
||||
mov(scratch1, ContextOperand(scratch1, Context::NATIVE_CONTEXT_INDEX));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// Read the first word and compare to native_context_map.
|
||||
cmp(FieldOperand(scratch1, HeapObject::kMapOffset),
|
||||
isolate()->factory()->native_context_map());
|
||||
Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
}
|
||||
|
||||
// Check if both contexts are the same.
|
||||
cmp(scratch1, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
j(equal, &same_contexts);
|
||||
|
||||
// Compare security tokens, save holder_reg on the stack so we can use it
|
||||
// as a temporary register.
|
||||
//
|
||||
// Check that the security token in the calling global object is
|
||||
// compatible with the security token in the receiving global
|
||||
// object.
|
||||
mov(scratch2,
|
||||
FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
cmp(scratch2, isolate()->factory()->null_value());
|
||||
Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
|
||||
|
||||
// Read the first word and compare to native_context_map(),
|
||||
cmp(FieldOperand(scratch2, HeapObject::kMapOffset),
|
||||
isolate()->factory()->native_context_map());
|
||||
Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
}
|
||||
|
||||
int token_offset = Context::kHeaderSize +
|
||||
Context::SECURITY_TOKEN_INDEX * kPointerSize;
|
||||
mov(scratch1, FieldOperand(scratch1, token_offset));
|
||||
cmp(scratch1, FieldOperand(scratch2, token_offset));
|
||||
j(not_equal, miss);
|
||||
|
||||
bind(&same_contexts);
|
||||
}
|
||||
|
||||
|
||||
// Compute the hash code from the untagged key. This must be kept in sync with
|
||||
// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
|
||||
// code-stub-hydrogen.cc
|
||||
|
@ -599,12 +599,6 @@ class MacroAssembler: public Assembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Inline caching support
|
||||
|
||||
// Generate code for checking access rights - used for security checks
|
||||
// on access to global objects across environments. The holder register
|
||||
// is left untouched, but the scratch register is clobbered.
|
||||
void CheckAccessGlobalProxy(Register holder_reg, Register scratch1,
|
||||
Register scratch2, Label* miss);
|
||||
|
||||
void GetNumberHash(Register r0, Register scratch);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -449,16 +449,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
current = isolate()->global_object();
|
||||
}
|
||||
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
// This allows us to install generated handlers for accesses to the
|
||||
// global proxy (as opposed to using slow ICs). See corresponding code
|
||||
// in LookupForRead().
|
||||
if (receiver_map->IsJSGlobalProxyMap()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch2, miss);
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = Handle<JSObject>::null();
|
||||
Handle<Map> current_map = receiver_map;
|
||||
Handle<Map> holder_map(holder()->map());
|
||||
@ -467,11 +457,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
while (!current_map.is_identical_to(holder_map)) {
|
||||
++depth;
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
DCHECK(current_map->IsJSGlobalProxyMap() ||
|
||||
!current_map->is_access_check_needed());
|
||||
|
||||
prototype = handle(JSObject::cast(current_map->prototype()));
|
||||
if (current_map->IsJSGlobalObjectMap()) {
|
||||
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
|
||||
|
@ -478,17 +478,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
current = isolate()->global_object();
|
||||
}
|
||||
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
// This allows us to install generated handlers for accesses to the
|
||||
// global proxy (as opposed to using slow ICs). See corresponding code
|
||||
// in LookupForRead().
|
||||
if (receiver_map->IsJSGlobalProxyMap()) {
|
||||
UseScratchRegisterScope temps(masm());
|
||||
__ CheckAccessGlobalProxy(reg, scratch2, temps.AcquireX(), miss);
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = Handle<JSObject>::null();
|
||||
Handle<Map> current_map = receiver_map;
|
||||
Handle<Map> holder_map(holder()->map());
|
||||
@ -497,11 +486,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
while (!current_map.is_identical_to(holder_map)) {
|
||||
++depth;
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
DCHECK(current_map->IsJSGlobalProxyMap() ||
|
||||
!current_map->is_access_check_needed());
|
||||
|
||||
prototype = handle(JSObject::cast(current_map->prototype()));
|
||||
if (current_map->IsJSGlobalObjectMap()) {
|
||||
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
|
||||
|
@ -453,16 +453,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
current = isolate()->global_object();
|
||||
}
|
||||
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
// This allows us to install generated handlers for accesses to the
|
||||
// global proxy (as opposed to using slow ICs). See corresponding code
|
||||
// in LookupForRead().
|
||||
if (receiver_map->IsJSGlobalProxyMap()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss);
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = Handle<JSObject>::null();
|
||||
Handle<Map> current_map = receiver_map;
|
||||
Handle<Map> holder_map(holder()->map());
|
||||
@ -471,11 +461,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
while (!current_map.is_identical_to(holder_map)) {
|
||||
++depth;
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
DCHECK(current_map->IsJSGlobalProxyMap() ||
|
||||
!current_map->is_access_check_needed());
|
||||
|
||||
prototype = handle(JSObject::cast(current_map->prototype()));
|
||||
if (current_map->IsJSGlobalObjectMap()) {
|
||||
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
|
||||
|
14
src/ic/ic.cc
14
src/ic/ic.cc
@ -862,10 +862,12 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
|
||||
DCHECK(holder->HasFastProperties());
|
||||
|
||||
// The following kinds of receiver maps require custom handler compilation.
|
||||
if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalProxyMap() ||
|
||||
receiver_map->IsJSGlobalObjectMap()) {
|
||||
if (receiver_map->IsPrimitiveMap() || receiver_map->IsJSGlobalObjectMap()) {
|
||||
return -1;
|
||||
}
|
||||
// We don't encode the requirement to check access rights because we already
|
||||
// passed the access check for current native context and the access
|
||||
// can't be revoked.
|
||||
|
||||
HandleScope scope(isolate);
|
||||
int checks_count = 0;
|
||||
@ -877,11 +879,6 @@ int InitPrototypeChecks(Isolate* isolate, Handle<Map> receiver_map,
|
||||
if (*current == *holder) break;
|
||||
Handle<Map> current_map(current->map(), isolate);
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
DCHECK(current_map->IsJSGlobalProxyMap() ||
|
||||
!current_map->is_access_check_needed());
|
||||
|
||||
if (current_map->IsJSGlobalObjectMap()) {
|
||||
if (fill_array) {
|
||||
Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(current);
|
||||
@ -925,8 +922,7 @@ Handle<Object> LoadIC::SimpleLoadFromPrototype(Handle<Map> receiver_map,
|
||||
int checks_count = GetPrototypeCheckCount(receiver_map, holder);
|
||||
DCHECK_LE(0, checks_count);
|
||||
|
||||
if (receiver_map->IsJSGlobalProxyMap() ||
|
||||
receiver_map->IsJSGlobalObjectMap()) {
|
||||
if (receiver_map->IsJSGlobalObjectMap()) {
|
||||
UNREACHABLE();
|
||||
} else if (receiver_map->is_dictionary_map()) {
|
||||
smi_handler =
|
||||
|
@ -435,16 +435,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
current = isolate()->global_object();
|
||||
}
|
||||
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
// This allows us to install generated handlers for accesses to the
|
||||
// global proxy (as opposed to using slow ICs). See corresponding code
|
||||
// in LookupForRead().
|
||||
if (receiver_map->IsJSGlobalProxyMap()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch2, miss);
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = Handle<JSObject>::null();
|
||||
Handle<Map> current_map = receiver_map;
|
||||
Handle<Map> holder_map(holder()->map());
|
||||
@ -453,11 +443,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
while (!current_map.is_identical_to(holder_map)) {
|
||||
++depth;
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
DCHECK(current_map->IsJSGlobalProxyMap() ||
|
||||
!current_map->is_access_check_needed());
|
||||
|
||||
prototype = handle(JSObject::cast(current_map->prototype()));
|
||||
if (current_map->IsJSGlobalObjectMap()) {
|
||||
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
|
||||
|
@ -435,16 +435,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
current = isolate()->global_object();
|
||||
}
|
||||
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
// This allows us to install generated handlers for accesses to the
|
||||
// global proxy (as opposed to using slow ICs). See corresponding code
|
||||
// in LookupForRead().
|
||||
if (receiver_map->IsJSGlobalProxyMap()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch2, miss);
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = Handle<JSObject>::null();
|
||||
Handle<Map> current_map = receiver_map;
|
||||
Handle<Map> holder_map(holder()->map());
|
||||
@ -453,11 +443,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
while (!current_map.is_identical_to(holder_map)) {
|
||||
++depth;
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
DCHECK(current_map->IsJSGlobalProxyMap() ||
|
||||
!current_map->is_access_check_needed());
|
||||
|
||||
prototype = handle(JSObject::cast(current_map->prototype()));
|
||||
if (current_map->IsJSGlobalObjectMap()) {
|
||||
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
|
||||
|
@ -443,15 +443,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
if (receiver_map->IsJSGlobalObjectMap()) {
|
||||
current = isolate()->global_object();
|
||||
}
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
// This allows us to install generated handlers for accesses to the
|
||||
// global proxy (as opposed to using slow ICs). See corresponding code
|
||||
// in LookupForRead().
|
||||
if (receiver_map->IsJSGlobalProxyMap()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch2, miss);
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = Handle<JSObject>::null();
|
||||
Handle<Map> current_map = receiver_map;
|
||||
|
@ -423,15 +423,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
if (receiver_map->IsJSGlobalObjectMap()) {
|
||||
current = isolate()->global_object();
|
||||
}
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
// This allows us to install generated handlers for accesses to the
|
||||
// global proxy (as opposed to using slow ICs). See corresponding code
|
||||
// in LookupForRead().
|
||||
if (receiver_map->IsJSGlobalProxyMap()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch2, miss);
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = Handle<JSObject>::null();
|
||||
Handle<Map> current_map = receiver_map;
|
||||
@ -441,11 +432,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
while (!current_map.is_identical_to(holder_map)) {
|
||||
++depth;
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
DCHECK(current_map->IsJSGlobalProxyMap() ||
|
||||
!current_map->is_access_check_needed());
|
||||
|
||||
prototype = handle(JSObject::cast(current_map->prototype()));
|
||||
if (current_map->IsJSGlobalObjectMap()) {
|
||||
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
|
||||
|
@ -446,16 +446,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
current = isolate()->global_object();
|
||||
}
|
||||
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
// This allows us to install generated handlers for accesses to the
|
||||
// global proxy (as opposed to using slow ICs). See corresponding code
|
||||
// in LookupForRead().
|
||||
if (receiver_map->IsJSGlobalProxyMap()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch2, miss);
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = Handle<JSObject>::null();
|
||||
Handle<Map> current_map = receiver_map;
|
||||
Handle<Map> holder_map(holder()->map());
|
||||
@ -464,11 +454,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
while (!current_map.is_identical_to(holder_map)) {
|
||||
++depth;
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
DCHECK(current_map->IsJSGlobalProxyMap() ||
|
||||
!current_map->is_access_check_needed());
|
||||
|
||||
prototype = handle(JSObject::cast(current_map->prototype()));
|
||||
if (current_map->IsJSGlobalObjectMap()) {
|
||||
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
|
||||
|
@ -453,16 +453,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
current = isolate()->global_object();
|
||||
}
|
||||
|
||||
// Check access rights to the global object. This has to happen after
|
||||
// the map check so that we know that the object is actually a global
|
||||
// object.
|
||||
// This allows us to install generated handlers for accesses to the
|
||||
// global proxy (as opposed to using slow ICs). See corresponding code
|
||||
// in LookupForRead().
|
||||
if (receiver_map->IsJSGlobalProxyMap()) {
|
||||
__ CheckAccessGlobalProxy(reg, scratch1, scratch2, miss);
|
||||
}
|
||||
|
||||
Handle<JSObject> prototype = Handle<JSObject>::null();
|
||||
Handle<Map> current_map = receiver_map;
|
||||
Handle<Map> holder_map(holder()->map());
|
||||
@ -471,11 +461,6 @@ Register PropertyHandlerCompiler::CheckPrototypes(
|
||||
while (!current_map.is_identical_to(holder_map)) {
|
||||
++depth;
|
||||
|
||||
// Only global objects and objects that do not require access
|
||||
// checks are allowed in stubs.
|
||||
DCHECK(current_map->IsJSGlobalProxyMap() ||
|
||||
!current_map->is_access_check_needed());
|
||||
|
||||
prototype = handle(JSObject::cast(current_map->prototype()));
|
||||
if (current_map->IsJSGlobalObjectMap()) {
|
||||
GenerateCheckPropertyCell(masm(), Handle<JSGlobalObject>::cast(current),
|
||||
|
@ -500,85 +500,6 @@ void MacroAssembler::RememberedSetHelper(Register object, // For debug tests.
|
||||
// Allocation support.
|
||||
|
||||
|
||||
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch,
|
||||
Label* miss) {
|
||||
Label same_contexts;
|
||||
Register temporary = t8;
|
||||
|
||||
DCHECK(!holder_reg.is(scratch));
|
||||
DCHECK(!holder_reg.is(at));
|
||||
DCHECK(!scratch.is(at));
|
||||
|
||||
// Load current lexical context from the active StandardFrame, which
|
||||
// may require crawling past STUB frames.
|
||||
Label load_context;
|
||||
Label has_context;
|
||||
mov(at, fp);
|
||||
bind(&load_context);
|
||||
lw(scratch, MemOperand(at, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
// Passing temporary register, otherwise JumpIfNotSmi modifies register at.
|
||||
JumpIfNotSmi(scratch, &has_context, temporary);
|
||||
lw(at, MemOperand(at, CommonFrameConstants::kCallerFPOffset));
|
||||
Branch(&load_context);
|
||||
bind(&has_context);
|
||||
|
||||
// In debug mode, make sure the lexical context is set.
|
||||
#ifdef DEBUG
|
||||
Check(ne, kWeShouldNotHaveAnEmptyLexicalContext,
|
||||
scratch, Operand(zero_reg));
|
||||
#endif
|
||||
|
||||
// Load the native context of the current context.
|
||||
lw(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
// Read the first word and compare to the native_context_map.
|
||||
lw(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
|
||||
LoadRoot(at, Heap::kNativeContextMapRootIndex);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
|
||||
holder_reg, Operand(at));
|
||||
pop(holder_reg); // Restore holder.
|
||||
}
|
||||
|
||||
// Check if both contexts are the same.
|
||||
lw(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
Branch(&same_contexts, eq, scratch, Operand(at));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
mov(holder_reg, at); // Move at to its holding place.
|
||||
LoadRoot(at, Heap::kNullValueRootIndex);
|
||||
Check(ne, kJSGlobalProxyContextShouldNotBeNull,
|
||||
holder_reg, Operand(at));
|
||||
|
||||
lw(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
|
||||
LoadRoot(at, Heap::kNativeContextMapRootIndex);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
|
||||
holder_reg, Operand(at));
|
||||
// Restore at is not needed. at is reloaded below.
|
||||
pop(holder_reg); // Restore holder.
|
||||
// Restore at to holder's context.
|
||||
lw(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
}
|
||||
|
||||
// Check that the security token in the calling global object is
|
||||
// compatible with the security token in the receiving global
|
||||
// object.
|
||||
int token_offset = Context::kHeaderSize +
|
||||
Context::SECURITY_TOKEN_INDEX * kPointerSize;
|
||||
|
||||
lw(scratch, FieldMemOperand(scratch, token_offset));
|
||||
lw(at, FieldMemOperand(at, token_offset));
|
||||
Branch(miss, ne, scratch, Operand(at));
|
||||
|
||||
bind(&same_contexts);
|
||||
}
|
||||
|
||||
|
||||
// Compute the hash code from the untagged key. This must be kept in sync with
|
||||
// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
|
||||
// code-stub-hydrogen.cc
|
||||
|
@ -495,13 +495,6 @@ class MacroAssembler: public Assembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Inline caching support.
|
||||
|
||||
// Generate code for checking access rights - used for security checks
|
||||
// on access to global objects across environments. The holder register
|
||||
// is left untouched, whereas both scratch registers are clobbered.
|
||||
void CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch,
|
||||
Label* miss);
|
||||
|
||||
void GetNumberHash(Register reg0, Register scratch);
|
||||
|
||||
inline void MarkCode(NopMarkerTypes type) {
|
||||
|
@ -517,85 +517,6 @@ void MacroAssembler::RememberedSetHelper(Register object, // For debug tests.
|
||||
// Allocation support.
|
||||
|
||||
|
||||
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch,
|
||||
Label* miss) {
|
||||
Label same_contexts;
|
||||
Register temporary = t8;
|
||||
|
||||
DCHECK(!holder_reg.is(scratch));
|
||||
DCHECK(!holder_reg.is(at));
|
||||
DCHECK(!scratch.is(at));
|
||||
|
||||
// Load current lexical context from the active StandardFrame, which
|
||||
// may require crawling past STUB frames.
|
||||
Label load_context;
|
||||
Label has_context;
|
||||
mov(at, fp);
|
||||
bind(&load_context);
|
||||
ld(scratch, MemOperand(at, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
// Passing temporary register, otherwise JumpIfNotSmi modifies register at.
|
||||
JumpIfNotSmi(scratch, &has_context, temporary);
|
||||
ld(at, MemOperand(at, CommonFrameConstants::kCallerFPOffset));
|
||||
Branch(&load_context);
|
||||
bind(&has_context);
|
||||
|
||||
// In debug mode, make sure the lexical context is set.
|
||||
#ifdef DEBUG
|
||||
Check(ne, kWeShouldNotHaveAnEmptyLexicalContext,
|
||||
scratch, Operand(zero_reg));
|
||||
#endif
|
||||
|
||||
// Load the native context of the current context.
|
||||
ld(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
// Read the first word and compare to the native_context_map.
|
||||
ld(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
|
||||
LoadRoot(at, Heap::kNativeContextMapRootIndex);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
|
||||
holder_reg, Operand(at));
|
||||
pop(holder_reg); // Restore holder.
|
||||
}
|
||||
|
||||
// Check if both contexts are the same.
|
||||
ld(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
Branch(&same_contexts, eq, scratch, Operand(at));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
mov(holder_reg, at); // Move at to its holding place.
|
||||
LoadRoot(at, Heap::kNullValueRootIndex);
|
||||
Check(ne, kJSGlobalProxyContextShouldNotBeNull,
|
||||
holder_reg, Operand(at));
|
||||
|
||||
ld(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
|
||||
LoadRoot(at, Heap::kNativeContextMapRootIndex);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext,
|
||||
holder_reg, Operand(at));
|
||||
// Restore at is not needed. at is reloaded below.
|
||||
pop(holder_reg); // Restore holder.
|
||||
// Restore at to holder's context.
|
||||
ld(at, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
}
|
||||
|
||||
// Check that the security token in the calling global object is
|
||||
// compatible with the security token in the receiving global
|
||||
// object.
|
||||
int token_offset = Context::kHeaderSize +
|
||||
Context::SECURITY_TOKEN_INDEX * kPointerSize;
|
||||
|
||||
ld(scratch, FieldMemOperand(scratch, token_offset));
|
||||
ld(at, FieldMemOperand(at, token_offset));
|
||||
Branch(miss, ne, scratch, Operand(at));
|
||||
|
||||
bind(&same_contexts);
|
||||
}
|
||||
|
||||
|
||||
// Compute the hash code from the untagged key. This must be kept in sync with
|
||||
// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
|
||||
// code-stub-hydrogen.cc
|
||||
|
@ -527,13 +527,6 @@ class MacroAssembler: public Assembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Inline caching support.
|
||||
|
||||
// Generate code for checking access rights - used for security checks
|
||||
// on access to global objects across environments. The holder register
|
||||
// is left untouched, whereas both scratch registers are clobbered.
|
||||
void CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch,
|
||||
Label* miss);
|
||||
|
||||
void GetNumberHash(Register reg0, Register scratch);
|
||||
|
||||
inline void MarkCode(NopMarkerTypes type) {
|
||||
|
@ -1605,90 +1605,6 @@ void MacroAssembler::PopStackHandler() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch, Label* miss) {
|
||||
Label same_contexts;
|
||||
|
||||
DCHECK(!holder_reg.is(scratch));
|
||||
DCHECK(!holder_reg.is(ip));
|
||||
DCHECK(!scratch.is(ip));
|
||||
|
||||
// Load current lexical context from the active StandardFrame, which
|
||||
// may require crawling past STUB frames.
|
||||
Label load_context;
|
||||
Label has_context;
|
||||
DCHECK(!ip.is(scratch));
|
||||
mr(ip, fp);
|
||||
bind(&load_context);
|
||||
LoadP(scratch,
|
||||
MemOperand(ip, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
JumpIfNotSmi(scratch, &has_context);
|
||||
LoadP(ip, MemOperand(ip, CommonFrameConstants::kCallerFPOffset));
|
||||
b(&load_context);
|
||||
bind(&has_context);
|
||||
|
||||
// In debug mode, make sure the lexical context is set.
|
||||
#ifdef DEBUG
|
||||
cmpi(scratch, Operand::Zero());
|
||||
Check(ne, kWeShouldNotHaveAnEmptyLexicalContext);
|
||||
#endif
|
||||
|
||||
// Load the native context of the current context.
|
||||
LoadP(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// Cannot use ip as a temporary in this verification code. Due to the fact
|
||||
// that ip is clobbered as part of cmp with an object Operand.
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
// Read the first word and compare to the native_context_map.
|
||||
LoadP(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
|
||||
LoadRoot(ip, Heap::kNativeContextMapRootIndex);
|
||||
cmp(holder_reg, ip);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
pop(holder_reg); // Restore holder.
|
||||
}
|
||||
|
||||
// Check if both contexts are the same.
|
||||
LoadP(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
cmp(scratch, ip);
|
||||
beq(&same_contexts);
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// Cannot use ip as a temporary in this verification code. Due to the fact
|
||||
// that ip is clobbered as part of cmp with an object Operand.
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
mr(holder_reg, ip); // Move ip to its holding place.
|
||||
LoadRoot(ip, Heap::kNullValueRootIndex);
|
||||
cmp(holder_reg, ip);
|
||||
Check(ne, kJSGlobalProxyContextShouldNotBeNull);
|
||||
|
||||
LoadP(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
|
||||
LoadRoot(ip, Heap::kNativeContextMapRootIndex);
|
||||
cmp(holder_reg, ip);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
// Restore ip is not needed. ip is reloaded below.
|
||||
pop(holder_reg); // Restore holder.
|
||||
// Restore ip to holder's context.
|
||||
LoadP(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
}
|
||||
|
||||
// Check that the security token in the calling global object is
|
||||
// compatible with the security token in the receiving global
|
||||
// object.
|
||||
int token_offset =
|
||||
Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
|
||||
|
||||
LoadP(scratch, FieldMemOperand(scratch, token_offset));
|
||||
LoadP(ip, FieldMemOperand(ip, token_offset));
|
||||
cmp(scratch, ip);
|
||||
bne(miss);
|
||||
|
||||
bind(&same_contexts);
|
||||
}
|
||||
|
||||
|
||||
// Compute the hash code from the untagged key. This must be kept in sync with
|
||||
// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
|
||||
// code-stub-hydrogen.cc
|
||||
|
@ -662,12 +662,6 @@ class MacroAssembler : public Assembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Inline caching support
|
||||
|
||||
// Generate code for checking access rights - used for security checks
|
||||
// on access to global objects across environments. The holder register
|
||||
// is left untouched, whereas both scratch registers are clobbered.
|
||||
void CheckAccessGlobalProxy(Register holder_reg, Register scratch,
|
||||
Label* miss);
|
||||
|
||||
void GetNumberHash(Register t0, Register scratch);
|
||||
|
||||
inline void MarkCode(NopMarkerTypes type) { nop(type); }
|
||||
|
@ -1502,87 +1502,6 @@ void MacroAssembler::PopStackHandler() {
|
||||
StoreP(r3, MemOperand(ip));
|
||||
}
|
||||
|
||||
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch, Label* miss) {
|
||||
Label same_contexts;
|
||||
|
||||
DCHECK(!holder_reg.is(scratch));
|
||||
DCHECK(!holder_reg.is(ip));
|
||||
DCHECK(!scratch.is(ip));
|
||||
|
||||
// Load current lexical context from the active StandardFrame, which
|
||||
// may require crawling past STUB frames.
|
||||
Label load_context;
|
||||
Label has_context;
|
||||
DCHECK(!ip.is(scratch));
|
||||
LoadRR(ip, fp);
|
||||
bind(&load_context);
|
||||
LoadP(scratch,
|
||||
MemOperand(ip, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
JumpIfNotSmi(scratch, &has_context);
|
||||
LoadP(ip, MemOperand(ip, CommonFrameConstants::kCallerFPOffset));
|
||||
b(&load_context);
|
||||
bind(&has_context);
|
||||
|
||||
// In debug mode, make sure the lexical context is set.
|
||||
#ifdef DEBUG
|
||||
CmpP(scratch, Operand::Zero());
|
||||
Check(ne, kWeShouldNotHaveAnEmptyLexicalContext);
|
||||
#endif
|
||||
|
||||
// Load the native context of the current context.
|
||||
LoadP(scratch, ContextMemOperand(scratch, Context::NATIVE_CONTEXT_INDEX));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// Cannot use ip as a temporary in this verification code. Due to the fact
|
||||
// that ip is clobbered as part of cmp with an object Operand.
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
// Read the first word and compare to the native_context_map.
|
||||
LoadP(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
|
||||
CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
pop(holder_reg); // Restore holder.
|
||||
}
|
||||
|
||||
// Check if both contexts are the same.
|
||||
LoadP(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
CmpP(scratch, ip);
|
||||
beq(&same_contexts, Label::kNear);
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// TODO(119): avoid push(holder_reg)/pop(holder_reg)
|
||||
// Cannot use ip as a temporary in this verification code. Due to the fact
|
||||
// that ip is clobbered as part of cmp with an object Operand.
|
||||
push(holder_reg); // Temporarily save holder on the stack.
|
||||
LoadRR(holder_reg, ip); // Move ip to its holding place.
|
||||
CompareRoot(holder_reg, Heap::kNullValueRootIndex);
|
||||
Check(ne, kJSGlobalProxyContextShouldNotBeNull);
|
||||
|
||||
LoadP(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
|
||||
CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex);
|
||||
Check(eq, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
// Restore ip is not needed. ip is reloaded below.
|
||||
pop(holder_reg); // Restore holder.
|
||||
// Restore ip to holder's context.
|
||||
LoadP(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
}
|
||||
|
||||
// Check that the security token in the calling global object is
|
||||
// compatible with the security token in the receiving global
|
||||
// object.
|
||||
int token_offset =
|
||||
Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
|
||||
|
||||
LoadP(scratch, FieldMemOperand(scratch, token_offset));
|
||||
LoadP(ip, FieldMemOperand(ip, token_offset));
|
||||
CmpP(scratch, ip);
|
||||
bne(miss);
|
||||
|
||||
bind(&same_contexts);
|
||||
}
|
||||
|
||||
// Compute the hash code from the untagged key. This must be kept in sync with
|
||||
// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
|
||||
// code-stub-hydrogen.cc
|
||||
|
@ -932,12 +932,6 @@ class MacroAssembler : public Assembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Inline caching support
|
||||
|
||||
// Generate code for checking access rights - used for security checks
|
||||
// on access to global objects across environments. The holder register
|
||||
// is left untouched, whereas both scratch registers are clobbered.
|
||||
void CheckAccessGlobalProxy(Register holder_reg, Register scratch,
|
||||
Label* miss);
|
||||
|
||||
void GetNumberHash(Register t0, Register scratch);
|
||||
|
||||
inline void MarkCode(NopMarkerTypes type) { nop(type); }
|
||||
|
@ -4658,82 +4658,6 @@ void MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch,
|
||||
Label* miss) {
|
||||
Label same_contexts;
|
||||
|
||||
DCHECK(!holder_reg.is(scratch));
|
||||
DCHECK(!scratch.is(kScratchRegister));
|
||||
// Load current lexical context from the active StandardFrame, which
|
||||
// may require crawling past STUB frames.
|
||||
Label load_context;
|
||||
Label has_context;
|
||||
movp(scratch, rbp);
|
||||
bind(&load_context);
|
||||
DCHECK(SmiValuesAre32Bits());
|
||||
// This is "JumpIfNotSmi" but without loading the value into a register.
|
||||
cmpl(MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset),
|
||||
Immediate(0));
|
||||
j(not_equal, &has_context);
|
||||
movp(scratch, MemOperand(scratch, CommonFrameConstants::kCallerFPOffset));
|
||||
jmp(&load_context);
|
||||
bind(&has_context);
|
||||
movp(scratch,
|
||||
MemOperand(scratch, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
|
||||
// When generating debug code, make sure the lexical context is set.
|
||||
if (emit_debug_code()) {
|
||||
cmpp(scratch, Immediate(0));
|
||||
Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
|
||||
}
|
||||
// Load the native context of the current context.
|
||||
movp(scratch, ContextOperand(scratch, Context::NATIVE_CONTEXT_INDEX));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
Cmp(FieldOperand(scratch, HeapObject::kMapOffset),
|
||||
isolate()->factory()->native_context_map());
|
||||
Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
}
|
||||
|
||||
// Check if both contexts are the same.
|
||||
cmpp(scratch, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
j(equal, &same_contexts);
|
||||
|
||||
// Compare security tokens.
|
||||
// Check that the security token in the calling global object is
|
||||
// compatible with the security token in the receiving global
|
||||
// object.
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// Preserve original value of holder_reg.
|
||||
Push(holder_reg);
|
||||
movp(holder_reg,
|
||||
FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
CompareRoot(holder_reg, Heap::kNullValueRootIndex);
|
||||
Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
|
||||
|
||||
// Read the first word and compare to native_context_map(),
|
||||
movp(holder_reg, FieldOperand(holder_reg, HeapObject::kMapOffset));
|
||||
CompareRoot(holder_reg, Heap::kNativeContextMapRootIndex);
|
||||
Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
Pop(holder_reg);
|
||||
}
|
||||
|
||||
movp(kScratchRegister,
|
||||
FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
int token_offset =
|
||||
Context::kHeaderSize + Context::SECURITY_TOKEN_INDEX * kPointerSize;
|
||||
movp(scratch, FieldOperand(scratch, token_offset));
|
||||
cmpp(scratch, FieldOperand(kScratchRegister, token_offset));
|
||||
j(not_equal, miss);
|
||||
|
||||
bind(&same_contexts);
|
||||
}
|
||||
|
||||
|
||||
// Compute the hash code from the untagged key. This must be kept in sync with
|
||||
// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
|
||||
// code-stub-hydrogen.cc
|
||||
|
@ -1289,14 +1289,6 @@ class MacroAssembler: public Assembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Inline caching support
|
||||
|
||||
// Generate code for checking access rights - used for security checks
|
||||
// on access to global objects across environments. The holder register
|
||||
// is left untouched, but the scratch register and kScratchRegister,
|
||||
// which must be different, are clobbered.
|
||||
void CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch,
|
||||
Label* miss);
|
||||
|
||||
void GetNumberHash(Register r0, Register scratch);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -1224,79 +1224,6 @@ void MacroAssembler::PopStackHandler() {
|
||||
}
|
||||
|
||||
|
||||
void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
|
||||
Register scratch1,
|
||||
Register scratch2,
|
||||
Label* miss) {
|
||||
Label same_contexts;
|
||||
|
||||
DCHECK(!holder_reg.is(scratch1));
|
||||
DCHECK(!holder_reg.is(scratch2));
|
||||
DCHECK(!scratch1.is(scratch2));
|
||||
|
||||
// Load current lexical context from the active StandardFrame, which
|
||||
// may require crawling past STUB frames.
|
||||
Label load_context;
|
||||
Label has_context;
|
||||
mov(scratch2, ebp);
|
||||
bind(&load_context);
|
||||
mov(scratch1,
|
||||
MemOperand(scratch2, CommonFrameConstants::kContextOrFrameTypeOffset));
|
||||
JumpIfNotSmi(scratch1, &has_context);
|
||||
mov(scratch2, MemOperand(scratch2, CommonFrameConstants::kCallerFPOffset));
|
||||
jmp(&load_context);
|
||||
bind(&has_context);
|
||||
|
||||
// When generating debug code, make sure the lexical context is set.
|
||||
if (emit_debug_code()) {
|
||||
cmp(scratch1, Immediate(0));
|
||||
Check(not_equal, kWeShouldNotHaveAnEmptyLexicalContext);
|
||||
}
|
||||
// Load the native context of the current context.
|
||||
mov(scratch1, ContextOperand(scratch1, Context::NATIVE_CONTEXT_INDEX));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
// Read the first word and compare to native_context_map.
|
||||
cmp(FieldOperand(scratch1, HeapObject::kMapOffset),
|
||||
isolate()->factory()->native_context_map());
|
||||
Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
}
|
||||
|
||||
// Check if both contexts are the same.
|
||||
cmp(scratch1, FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
j(equal, &same_contexts);
|
||||
|
||||
// Compare security tokens, save holder_reg on the stack so we can use it
|
||||
// as a temporary register.
|
||||
//
|
||||
// Check that the security token in the calling global object is
|
||||
// compatible with the security token in the receiving global
|
||||
// object.
|
||||
mov(scratch2,
|
||||
FieldOperand(holder_reg, JSGlobalProxy::kNativeContextOffset));
|
||||
|
||||
// Check the context is a native context.
|
||||
if (emit_debug_code()) {
|
||||
cmp(scratch2, isolate()->factory()->null_value());
|
||||
Check(not_equal, kJSGlobalProxyContextShouldNotBeNull);
|
||||
|
||||
// Read the first word and compare to native_context_map(),
|
||||
cmp(FieldOperand(scratch2, HeapObject::kMapOffset),
|
||||
isolate()->factory()->native_context_map());
|
||||
Check(equal, kJSGlobalObjectNativeContextShouldBeANativeContext);
|
||||
}
|
||||
|
||||
int token_offset = Context::kHeaderSize +
|
||||
Context::SECURITY_TOKEN_INDEX * kPointerSize;
|
||||
mov(scratch1, FieldOperand(scratch1, token_offset));
|
||||
cmp(scratch1, FieldOperand(scratch2, token_offset));
|
||||
j(not_equal, miss);
|
||||
|
||||
bind(&same_contexts);
|
||||
}
|
||||
|
||||
|
||||
// Compute the hash code from the untagged key. This must be kept in sync with
|
||||
// ComputeIntegerHash in utils.h and KeyedLoadGenericStub in
|
||||
// code-stub-hydrogen.cc
|
||||
|
@ -588,12 +588,6 @@ class MacroAssembler: public Assembler {
|
||||
// ---------------------------------------------------------------------------
|
||||
// Inline caching support
|
||||
|
||||
// Generate code for checking access rights - used for security checks
|
||||
// on access to global objects across environments. The holder register
|
||||
// is left untouched, but the scratch register is clobbered.
|
||||
void CheckAccessGlobalProxy(Register holder_reg, Register scratch1,
|
||||
Register scratch2, Label* miss);
|
||||
|
||||
void GetNumberHash(Register r0, Register scratch);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -9704,15 +9704,6 @@ TEST(DetachGlobal) {
|
||||
result = CompileRun("other.p");
|
||||
CHECK(result->IsInt32());
|
||||
CHECK_EQ(24, result->Int32Value(env3).FromJust());
|
||||
|
||||
// Change security token for env3 to something different from env1 and env2.
|
||||
env3->SetSecurityToken(v8_str("bar"));
|
||||
|
||||
// Check that we do not have access to other.p in env1. |other| is now
|
||||
// the global object for env3 which has a different security token,
|
||||
// so access should be blocked.
|
||||
result = CompileRun("other.p");
|
||||
CHECK(result.IsEmpty());
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user