__ lea(edx,
Operand(ebp, StandardFrameConstants::kCallerSPOffset + offset));
__ push(edx);
- __ push(Immediate(Smi::FromInt(scope()->num_parameters())));
+ __ SafePush(Immediate(Smi::FromInt(scope()->num_parameters())));
// Arguments to ArgumentsAccessStub:
// function, receiver address, parameter count.
// The stub will rewrite receiver and parameter count if the previous
void FullCodeGenerator::AccumulatorValueContext::Plug(
Handle<Object> lit) const {
- __ Set(result_register(), Immediate(lit));
+ if (lit->IsSmi()) {
+ __ SafeSet(result_register(), Immediate(lit));
+ } else {
+ __ Set(result_register(), Immediate(lit));
+ }
}
void FullCodeGenerator::StackValueContext::Plug(Handle<Object> lit) const {
- // Immediates can be pushed directly.
- __ push(Immediate(lit));
+ if (lit->IsSmi()) {
+ __ SafePush(Immediate(lit));
+ } else {
+ __ push(Immediate(lit));
+ }
}
}
ASSERT(prop->key()->AsLiteral() != NULL &&
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()
? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
__ mov(edx,
ContextSlotOperandCheckExtensions(obj_proxy->var()->AsSlot(),
slow));
- __ mov(eax, Immediate(key_literal->handle()));
+ __ SafeSet(eax, Immediate(key_literal->handle()));
Handle<Code> ic =
isolate()->builtins()->KeyedLoadIC_Initialize();
EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(property));
ASSERT(key_literal->handle()->IsSmi());
// Load the key.
- __ mov(eax, Immediate(key_literal->handle()));
+ __ SafeSet(eax, Immediate(key_literal->handle()));
// Do a keyed property load.
Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
MemOperand slot_operand =
EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
__ push(slot_operand);
- __ mov(eax, Immediate(property->key()->AsLiteral()->handle()));
+ __ SafeSet(eax, Immediate(property->key()->AsLiteral()->handle()));
} else {
VisitForStackValue(property->obj());
VisitForAccumulatorValue(property->key());
MemOperand slot_operand =
EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
__ push(slot_operand);
- __ push(Immediate(property->key()->AsLiteral()->handle()));
+ __ SafePush(Immediate(property->key()->AsLiteral()->handle()));
} else {
VisitForStackValue(property->obj());
VisitForStackValue(property->key());
void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
SetSourcePosition(prop->position());
Literal* key = prop->key()->AsLiteral();
+ ASSERT(!key->handle()->IsSmi());
__ mov(ecx, Immediate(key->handle()));
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
EmitCallIC(ic, RelocInfo::CODE_TARGET, GetPropertyId(prop));
EmitVariableLoad(prop->obj()->AsVariableProxy()->var());
}
__ mov(edx, eax);
- __ Set(ecx, Immediate(prop->key()->AsLiteral()->handle()));
+ __ SafeSet(ecx, Immediate(prop->key()->AsLiteral()->handle()));
} else {
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
SetSourcePosition(expr->position());
// 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));
Handle<Code> construct_builtin =
// parameter count in eax.
VisitForAccumulatorValue(args->at(0));
__ mov(edx, eax);
- __ mov(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
+ __ SafeSet(eax, Immediate(Smi::FromInt(scope()->num_parameters())));
ArgumentsAccessStub stub(ArgumentsAccessStub::READ_ELEMENT);
__ CallStub(&stub);
context()->Plug(eax);
Label exit;
// 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.
__ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
MemOperand slot_operand =
EmitSlotSearch(obj_proxy->var()->AsSlot(), ecx);
__ push(slot_operand);
- __ mov(eax, Immediate(prop->key()->AsLiteral()->handle()));
+ __ SafeSet(eax, Immediate(prop->key()->AsLiteral()->handle()));
} else {
VisitForStackValue(prop->obj());
VisitForAccumulatorValue(prop->key());
void MacroAssembler::Set(Register dst, const Immediate& x) {
if (x.is_zero()) {
- xor_(dst, Operand(dst)); // shorter than mov
+ xor_(dst, Operand(dst)); // Shorter than mov.
} else {
mov(dst, 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,
InstanceType type,
Register map) {
#include "v8.h"
#include "compiler.h"
+#include "disasm.h"
+#include "disassembler.h"
#include "execution.h"
#include "factory.h"
#include "platform.h"
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