Commit 4e18d508 authored by sgjesse@chromium.org's avatar sgjesse@chromium.org

Add constant splitting for user controlled constants in the full compiler

This is IA32 only for now.

Added a random value to each assembler instance (JIT cookie) to be used for constant splitting. Added safe versions of setting a register with an immediate value and for pushing an immediate value. Used these functions where user controlled immediate values could be emitted in the code stream. I also used it for immediates which are an argument number even though the number of formal arguments is currently limited to 16k.

I found no compares directly with user controlled constants.

I am not sure whether the test is that useful, but it might catch some changes missing constant splitting.

Review URL: http://codereview.chromium.org//7005031

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7868 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 26bf1dfd
...@@ -73,6 +73,18 @@ const double DoubleConstant::nan = OS::nan_value(); ...@@ -73,6 +73,18 @@ const double DoubleConstant::nan = OS::nan_value();
const double DoubleConstant::negative_infinity = -V8_INFINITY; const double DoubleConstant::negative_infinity = -V8_INFINITY;
const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING"; const char* RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";
// -----------------------------------------------------------------------------
// Implementation of AssemblerBase
AssemblerBase::AssemblerBase(Isolate* isolate)
: isolate_(isolate),
jit_cookie_(0) {
if (FLAG_mask_constants_with_cookie && isolate != NULL) {
jit_cookie_ = V8::RandomPrivate(isolate);
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Implementation of Label // Implementation of Label
......
...@@ -49,12 +49,14 @@ const unsigned kNoASTId = -1; ...@@ -49,12 +49,14 @@ const unsigned kNoASTId = -1;
class AssemblerBase: public Malloced { class AssemblerBase: public Malloced {
public: public:
explicit AssemblerBase(Isolate* isolate) : isolate_(isolate) {} explicit AssemblerBase(Isolate* isolate);
Isolate* isolate() const { return isolate_; } Isolate* isolate() const { return isolate_; }
int jit_cookie() { return jit_cookie_; }
private: private:
Isolate* isolate_; Isolate* isolate_;
int jit_cookie_;
}; };
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
......
...@@ -279,6 +279,7 @@ class Immediate BASE_EMBEDDED { ...@@ -279,6 +279,7 @@ class Immediate BASE_EMBEDDED {
RelocInfo::Mode rmode_; RelocInfo::Mode rmode_;
friend class Assembler; friend class Assembler;
friend class MacroAssembler;
}; };
......
...@@ -201,7 +201,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { ...@@ -201,7 +201,7 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
__ lea(edx, __ lea(edx,
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset)); Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
__ push(edx); __ push(edx);
__ push(Immediate(Smi::FromInt(scope()->num_parameters()))); __ SafePush(Immediate(Smi::FromInt(scope()->num_parameters())));
// Arguments to ArgumentsAccessStub: // Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count. // function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous // The stub will rewrite receiver and parameter count if the previous
...@@ -390,13 +390,20 @@ void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const { ...@@ -390,13 +390,20 @@ void FullCodeGenerator::EffectContext::Plug(Handle<Object> lit) const {
void FullCodeGenerator::AccumulatorValueContext::Plug( void FullCodeGenerator::AccumulatorValueContext::Plug(
Handle<Object> lit) const { Handle<Object> lit) const {
if (lit->IsSmi()) {
__ SafeSet(result_register(), Immediate(lit));
} else {
__ Set(result_register(), Immediate(lit)); __ Set(result_register(), Immediate(lit));
}
} }
void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const { void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
// Immediates can be pushed directly. if (lit->IsSmi()) {
__ SafePush(Immediate(lit));
} else {
__ push(Immediate(lit)); __ push(Immediate(lit));
}
} }
...@@ -739,7 +746,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable, ...@@ -739,7 +746,7 @@ void FullCodeGenerator::EmitDeclaration(Variable* variable,
} }
ASSERT(prop->key()->AsLiteral() != NULL && ASSERT(prop->key()->AsLiteral() != NULL &&
prop->key()->AsLiteral()->handle()->IsSmi()); prop->key()->AsLiteral()->handle()->IsSmi());
__ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle()));
Handle<Code> ic = is_strict_mode() Handle<Code> ic = is_strict_mode()
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
...@@ -1193,7 +1200,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase( ...@@ -1193,7 +1200,7 @@ void FullCodeGenerator::EmitDynamicLoadFromSlotFastCase(
__ mov(edx, __ mov(edx,
ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(), ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
slow)); slow));
__ mov(eax, Immediate(key_literal->handle())); __ SafeSet(eax, Immediate(key_literal->handle()));
Handle<Code> ic = Handle<Code> ic =
isolate()->builtins()->KeyedLoadIC_Initialize(); isolate()->builtins()->KeyedLoadIC_Initialize();
EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property)); EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
...@@ -1278,7 +1285,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) { ...@@ -1278,7 +1285,7 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
ASSERT(key_literal->handle()->IsSmi()); ASSERT(key_literal->handle()->IsSmi());
// Load the key. // Load the key.
__ mov(eax, Immediate(key_literal->handle())); __ SafeSet(eax, Immediate(key_literal->handle()));
// Do a keyed property load. // Do a keyed property load.
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
...@@ -1549,7 +1556,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1549,7 +1556,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
MemOperand slot_operand = MemOperand slot_operand =
EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx); EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
__ push(slot_operand); __ push(slot_operand);
__ mov(eax, Immediate(property->key()->AsLiteral()->handle())); __ SafeSet(eax, Immediate(property->key()->AsLiteral()->handle()));
} else { } else {
VisitForStackValue(property->obj()); VisitForStackValue(property->obj());
VisitForAccumulatorValue(property->key()); VisitForAccumulatorValue(property->key());
...@@ -1562,7 +1569,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1562,7 +1569,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
MemOperand slot_operand = MemOperand slot_operand =
EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx); EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
__ push(slot_operand); __ push(slot_operand);
__ push(Immediate(property->key()->AsLiteral()->handle())); __ SafePush(Immediate(property->key()->AsLiteral()->handle()));
} else { } else {
VisitForStackValue(property->obj()); VisitForStackValue(property->obj());
VisitForStackValue(property->key()); VisitForStackValue(property->key());
...@@ -1641,6 +1648,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { ...@@ -1641,6 +1648,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) { void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position()); SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral(); Literal* key = prop->key()->AsLiteral();
ASSERT(!key->handle()->IsSmi());
__ mov(ecx, Immediate(key->handle())); __ mov(ecx, Immediate(key->handle()));
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop)); EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
...@@ -1807,7 +1815,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) { ...@@ -1807,7 +1815,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, int bailout_ast_id) {
EmitVariableLoad(prop->obj()->AsVariableProxy()->var()); EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
} }
__ mov(edx, eax); __ mov(edx, eax);
__ Set(ecx, Immediate(prop->key()->AsLiteral()->handle())); __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle()));
} else { } else {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
...@@ -2320,7 +2328,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) { ...@@ -2320,7 +2328,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
SetSourcePosition(expr->position()); SetSourcePosition(expr->position());
// Load function and argument count into edi and eax. // Load function and argument count into edi and eax.
__ Set(eax, Immediate(arg_count)); __ SafeSet(eax, Immediate(arg_count));
__ mov(edi, Operand(esp, arg_count * kPointerSize)); __ mov(edi, Operand(esp, arg_count * kPointerSize));
Handle<Code> construct_builtin = Handle<Code> construct_builtin =
...@@ -2660,7 +2668,7 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { ...@@ -2660,7 +2668,7 @@ void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) {
// parameter count in eax. // parameter count in eax.
VisitForAccumulatorValue(args->at(0)); VisitForAccumulatorValue(args->at(0));
__ mov(edx, eax); __ mov(edx, eax);
__ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); __ SafeSet(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT); ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
__ CallStub(&stub); __ CallStub(&stub);
context()->Plug(eax); context()->Plug(eax);
...@@ -2672,7 +2680,7 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) { ...@@ -2672,7 +2680,7 @@ void FullCodeGenerator::EmitArgumentsLength(ZoneList<Expression*>* args) {
Label exit; Label exit;
// Get the number of formal parameters. // Get the number of formal parameters.
__ Set(eax, Immediate(Smi::FromInt(scope()->num_parameters()))); __ SafeSet(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
// Check if the calling frame is an arguments adaptor frame. // Check if the calling frame is an arguments adaptor frame.
__ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
...@@ -3813,7 +3821,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -3813,7 +3821,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
MemOperand slot_operand = MemOperand slot_operand =
EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx); EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
__ push(slot_operand); __ push(slot_operand);
__ mov(eax, Immediate(prop->key()->AsLiteral()->handle())); __ SafeSet(eax, Immediate(prop->key()->AsLiteral()->handle()));
} else { } else {
VisitForStackValue(prop->obj()); VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key()); VisitForAccumulatorValue(prop->key());
......
...@@ -191,7 +191,7 @@ void MacroAssembler::DebugBreak() { ...@@ -191,7 +191,7 @@ void MacroAssembler::DebugBreak() {
void MacroAssembler::Set(Register dst, const Immediate& x) { void MacroAssembler::Set(Register dst, const Immediate& x) {
if (x.is_zero()) { if (x.is_zero()) {
xor_(dst, Operand(dst)); // shorter than mov xor_(dst, Operand(dst)); // Shorter than mov.
} else { } else {
mov(dst, x); mov(dst, x);
} }
...@@ -203,6 +203,33 @@ void MacroAssembler::Set(const Operand& dst, const Immediate& x) { ...@@ -203,6 +203,33 @@ void MacroAssembler::Set(const Operand& dst, const Immediate& x) {
} }
bool MacroAssembler::IsUnsafeImmediate(const Immediate& x) {
static const int kMaxImmediateBits = 17;
if (x.rmode_ != RelocInfo::NONE) return false;
return !is_intn(x.x_, kMaxImmediateBits);
}
void MacroAssembler::SafeSet(Register dst, const Immediate& x) {
if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
Set(dst, Immediate(x.x_ ^ jit_cookie()));
xor_(dst, jit_cookie());
} else {
Set(dst, x);
}
}
void MacroAssembler::SafePush(const Immediate& x) {
if (IsUnsafeImmediate(x) && jit_cookie() != 0) {
push(Immediate(x.x_ ^ jit_cookie()));
xor_(Operand(esp, 0), Immediate(jit_cookie()));
} else {
push(x);
}
}
void MacroAssembler::CmpObjectType(Register heap_object, void MacroAssembler::CmpObjectType(Register heap_object,
InstanceType type, InstanceType type,
Register map) { Register map) {
......
...@@ -193,6 +193,11 @@ class MacroAssembler: public Assembler { ...@@ -193,6 +193,11 @@ class MacroAssembler: public Assembler {
void Set(Register dst, const Immediate& x); void Set(Register dst, const Immediate& x);
void Set(const Operand& dst, const Immediate& x); void Set(const Operand& dst, const Immediate& x);
// Support for constant splitting.
bool IsUnsafeImmediate(const Immediate& x);
void SafeSet(Register dst, const Immediate& x);
void SafePush(const Immediate& x);
// Compare object type for heap object. // Compare object type for heap object.
// Incoming register is heap_object and outgoing register is map. // Incoming register is heap_object and outgoing register is map.
void CmpObjectType(Register heap_object, InstanceType type, Register map); void CmpObjectType(Register heap_object, InstanceType type, Register map);
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include "v8.h" #include "v8.h"
#include "compiler.h" #include "compiler.h"
#include "disasm.h"
#include "disassembler.h"
#include "execution.h" #include "execution.h"
#include "factory.h" #include "factory.h"
#include "platform.h" #include "platform.h"
...@@ -348,3 +350,51 @@ TEST(GetScriptLineNumber) { ...@@ -348,3 +350,51 @@ TEST(GetScriptLineNumber) {
CHECK_EQ(i, f->GetScriptLineNumber()); CHECK_EQ(i, f->GetScriptLineNumber());
} }
} }
#ifdef ENABLE_DISASSEMBLER
static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj,
const char* property_name) {
v8::Local<v8::Function> fun =
v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name)));
return v8::Utils::OpenHandle(*fun);
}
static void CheckCodeForUnsafeLiteral(Handle<JSFunction> f) {
// Create a disassembler with default name lookup.
disasm::NameConverter name_converter;
disasm::Disassembler d(name_converter);
if (f->code()->kind() == Code::FUNCTION) {
Address pc = f->code()->instruction_start();
int decode_size =
Min(f->code()->instruction_size(),
static_cast<int>(f->code()->stack_check_table_offset()));
Address end = pc + decode_size;
v8::internal::EmbeddedVector<char, 128> decode_buffer;
while (pc < end) {
pc += d.InstructionDecode(decode_buffer, pc);
CHECK(strstr(decode_buffer.start(), "mov eax,0x178c29c") == NULL);
CHECK(strstr(decode_buffer.start(), "push 0x178c29c") == NULL);
CHECK(strstr(decode_buffer.start(), "0x178c29c") == NULL);
}
}
}
TEST(SplitConstantsInFullCompiler) {
v8::HandleScope scope;
LocalContext env;
CompileRun("function f() { a = 12345678 }; f();");
CheckCodeForUnsafeLiteral(GetJSFunction(env->Global(), "f"));
CompileRun("function f(x) { a = 12345678 + x}; f(1);");
CheckCodeForUnsafeLiteral(GetJSFunction(env->Global(), "f"));
CompileRun("function f(x) { var arguments = 1; x += 12345678}; f(1);");
CheckCodeForUnsafeLiteral(GetJSFunction(env->Global(), "f"));
CompileRun("function f(x) { var arguments = 1; x = 12345678}; f(1);");
CheckCodeForUnsafeLiteral(GetJSFunction(env->Global(), "f"));
}
#endif
...@@ -97,7 +97,7 @@ class AllowNativesSyntaxNoInlining { ...@@ -97,7 +97,7 @@ class AllowNativesSyntaxNoInlining {
}; };
Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj, static Handle<JSFunction> GetJSFunction(v8::Handle<v8::Object> obj,
const char* property_name) { const char* property_name) {
v8::Local<v8::Function> fun = v8::Local<v8::Function> fun =
v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name))); v8::Local<v8::Function>::Cast(obj->Get(v8_str(property_name)));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment