| Index: src/mips/stub-cache-mips.cc
|
| diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
|
| index 296f186e940c69c4ee5bd33649c29c71fa2ea3ba..cb1f0929ffbb1c24debe709eb765753b5649fd95 100644
|
| --- a/src/mips/stub-cache-mips.cc
|
| +++ b/src/mips/stub-cache-mips.cc
|
| @@ -151,66 +151,6 @@ static void GenerateDictionaryNegativeLookup(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
| -// handlified.
|
| -MUST_USE_RESULT static MaybeObject* TryGenerateDictionaryNegativeLookup(
|
| - MacroAssembler* masm,
|
| - Label* miss_label,
|
| - Register receiver,
|
| - String* name,
|
| - Register scratch0,
|
| - Register scratch1) {
|
| - ASSERT(name->IsSymbol());
|
| - Counters* counters = masm->isolate()->counters();
|
| - __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1);
|
| - __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
| -
|
| - Label done;
|
| -
|
| - const int kInterceptorOrAccessCheckNeededMask =
|
| - (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
|
| -
|
| - // Bail out if the receiver has a named interceptor or requires access checks.
|
| - Register map = scratch1;
|
| - __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| - __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
|
| - __ And(at, scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
|
| - __ Branch(miss_label, ne, at, Operand(zero_reg));
|
| -
|
| -
|
| - // Check that receiver is a JSObject.
|
| - __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
|
| - __ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
|
| -
|
| - // Load properties array.
|
| - Register properties = scratch0;
|
| - __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
| - // Check that the properties array is a dictionary.
|
| - __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset));
|
| - Register tmp = properties;
|
| - __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
|
| - __ Branch(miss_label, ne, map, Operand(tmp));
|
| -
|
| - // Restore the temporarily used register.
|
| - __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
|
| -
|
| - MaybeObject* result = StringDictionaryLookupStub::TryGenerateNegativeLookup(
|
| - masm,
|
| - miss_label,
|
| - &done,
|
| - receiver,
|
| - properties,
|
| - name,
|
| - scratch1);
|
| - if (result->IsFailure()) return result;
|
| -
|
| - __ bind(&done);
|
| - __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1);
|
| -
|
| - return result;
|
| -}
|
| -
|
| -
|
| void StubCache::GenerateProbe(MacroAssembler* masm,
|
| Code::Flags flags,
|
| Register receiver,
|
| @@ -294,7 +234,10 @@ void StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm,
|
|
|
|
|
| void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
| - MacroAssembler* masm, int index, Register prototype, Label* miss) {
|
| + MacroAssembler* masm,
|
| + int index,
|
| + Register prototype,
|
| + Label* miss) {
|
| Isolate* isolate = masm->isolate();
|
| // Check we're still in the same context.
|
| __ lw(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
|
| @@ -302,8 +245,8 @@ void StubCompiler::GenerateDirectLoadGlobalFunctionPrototype(
|
| __ li(at, isolate->global());
|
| __ Branch(miss, ne, prototype, Operand(at));
|
| // Get the global function with the given index.
|
| - JSFunction* function =
|
| - JSFunction::cast(isolate->global_context()->get(index));
|
| + Handle<JSFunction> function(
|
| + JSFunction::cast(isolate->global_context()->get(index)));
|
| // Load its initial map. The global functions all have initial maps.
|
| __ li(prototype, Handle<Map>(function->initial_map()));
|
| // Load the prototype from the initial map.
|
| @@ -565,23 +508,24 @@ static void PushInterceptorArguments(MacroAssembler* masm,
|
| Register receiver,
|
| Register holder,
|
| Register name,
|
| - JSObject* holder_obj) {
|
| + Handle<JSObject> holder_obj) {
|
| __ push(name);
|
| - InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
|
| - ASSERT(!masm->isolate()->heap()->InNewSpace(interceptor));
|
| + Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
|
| + ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor));
|
| Register scratch = name;
|
| - __ li(scratch, Operand(Handle<Object>(interceptor)));
|
| + __ li(scratch, Operand(interceptor));
|
| __ Push(scratch, receiver, holder);
|
| __ lw(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset));
|
| __ push(scratch);
|
| }
|
|
|
|
|
| -static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
|
| - Register receiver,
|
| - Register holder,
|
| - Register name,
|
| - JSObject* holder_obj) {
|
| +static void CompileCallLoadPropertyWithInterceptor(
|
| + MacroAssembler* masm,
|
| + Register receiver,
|
| + Register holder,
|
| + Register name,
|
| + Handle<JSObject> holder_obj) {
|
| PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
|
|
|
| ExternalReference ref =
|
| @@ -617,10 +561,9 @@ static void FreeSpaceForFastApiCall(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| -static MaybeObject* GenerateFastApiDirectCall(
|
| - MacroAssembler* masm,
|
| - const CallOptimization& optimization,
|
| - int argc) {
|
| +static void GenerateFastApiDirectCall(MacroAssembler* masm,
|
| + const CallOptimization& optimization,
|
| + int argc) {
|
| // ----------- S t a t e -------------
|
| // -- sp[0] : holder (set by CheckPrototypes)
|
| // -- sp[4] : callee js function
|
| @@ -631,18 +574,18 @@ static MaybeObject* GenerateFastApiDirectCall(
|
| // -- sp[(argc + 4) * 4] : receiver
|
| // -----------------------------------
|
| // Get the function and setup the context.
|
| - JSFunction* function = optimization.constant_function();
|
| - __ li(t1, Operand(Handle<JSFunction>(function)));
|
| + Handle<JSFunction> function = optimization.constant_function();
|
| + __ li(t1, Operand(function));
|
| __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset));
|
|
|
| // Pass the additional arguments FastHandleApiCall expects.
|
| - Object* call_data = optimization.api_call_info()->data();
|
| - Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
|
| - if (masm->isolate()->heap()->InNewSpace(call_data)) {
|
| - __ li(a0, api_call_info_handle);
|
| + Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
|
| + Handle<Object> call_data(api_call_info->data());
|
| + if (masm->isolate()->heap()->InNewSpace(*call_data)) {
|
| + __ li(a0, api_call_info);
|
| __ lw(t2, FieldMemOperand(a0, CallHandlerInfo::kDataOffset));
|
| } else {
|
| - __ li(t2, Operand(Handle<Object>(call_data)));
|
| + __ li(t2, call_data);
|
| }
|
|
|
| // Store js function and call data.
|
| @@ -653,10 +596,6 @@ static MaybeObject* GenerateFastApiDirectCall(
|
| // (refer to layout above).
|
| __ Addu(a2, sp, Operand(2 * kPointerSize));
|
|
|
| - Object* callback = optimization.api_call_info()->callback();
|
| - Address api_function_address = v8::ToCData<Address>(callback);
|
| - ApiFunction fun(api_function_address);
|
| -
|
| const int kApiStackSpace = 4;
|
|
|
| FrameScope frame_scope(masm, StackFrame::MANUAL);
|
| @@ -682,17 +621,15 @@ static MaybeObject* GenerateFastApiDirectCall(
|
| // v8::Arguments::is_construct_call = 0
|
| __ sw(zero_reg, MemOperand(a1, 3 * kPointerSize));
|
|
|
| - // Emitting a stub call may try to allocate (if the code is not
|
| - // already generated). Do not allow the assembler to perform a
|
| - // garbage collection but instead return the allocation failure
|
| - // object.
|
| const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
|
| + Address function_address = v8::ToCData<Address>(api_call_info->callback());
|
| + ApiFunction fun(function_address);
|
| ExternalReference ref =
|
| ExternalReference(&fun,
|
| ExternalReference::DIRECT_API_CALL,
|
| masm->isolate());
|
| AllowExternalCallThatCantCauseGC scope(masm);
|
| - return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
|
| + __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
|
| }
|
|
|
| class CallInterceptorCompiler BASE_EMBEDDED {
|
| @@ -706,86 +643,63 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
| name_(name),
|
| extra_ic_state_(extra_ic_state) {}
|
|
|
| - MaybeObject* Compile(MacroAssembler* masm,
|
| - JSObject* object,
|
| - JSObject* holder,
|
| - String* name,
|
| - LookupResult* lookup,
|
| - Register receiver,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - Register scratch3,
|
| - Label* miss) {
|
| + void Compile(MacroAssembler* masm,
|
| + Handle<JSObject> object,
|
| + Handle<JSObject> holder,
|
| + Handle<String> name,
|
| + LookupResult* lookup,
|
| + Register receiver,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + Register scratch3,
|
| + Label* miss) {
|
| ASSERT(holder->HasNamedInterceptor());
|
| ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
|
|
|
| // Check that the receiver isn't a smi.
|
| __ JumpIfSmi(receiver, miss);
|
| -
|
| CallOptimization optimization(lookup);
|
| -
|
| if (optimization.is_constant_call()) {
|
| - return CompileCacheable(masm,
|
| - object,
|
| - receiver,
|
| - scratch1,
|
| - scratch2,
|
| - scratch3,
|
| - holder,
|
| - lookup,
|
| - name,
|
| - optimization,
|
| - miss);
|
| + CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
|
| + holder, lookup, name, optimization, miss);
|
| } else {
|
| - CompileRegular(masm,
|
| - object,
|
| - receiver,
|
| - scratch1,
|
| - scratch2,
|
| - scratch3,
|
| - name,
|
| - holder,
|
| - miss);
|
| - return masm->isolate()->heap()->undefined_value();
|
| + CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
|
| + name, holder, miss);
|
| }
|
| }
|
|
|
| private:
|
| - MaybeObject* CompileCacheable(MacroAssembler* masm,
|
| - JSObject* object,
|
| - Register receiver,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - Register scratch3,
|
| - JSObject* interceptor_holder,
|
| - LookupResult* lookup,
|
| - String* name,
|
| - const CallOptimization& optimization,
|
| - Label* miss_label) {
|
| + void CompileCacheable(MacroAssembler* masm,
|
| + Handle<JSObject> object,
|
| + Register receiver,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + Register scratch3,
|
| + Handle<JSObject> interceptor_holder,
|
| + LookupResult* lookup,
|
| + Handle<String> name,
|
| + const CallOptimization& optimization,
|
| + Label* miss_label) {
|
| ASSERT(optimization.is_constant_call());
|
| ASSERT(!lookup->holder()->IsGlobalObject());
|
| -
|
| Counters* counters = masm->isolate()->counters();
|
| -
|
| int depth1 = kInvalidProtoDepth;
|
| int depth2 = kInvalidProtoDepth;
|
| bool can_do_fast_api_call = false;
|
| if (optimization.is_simple_api_call() &&
|
| - !lookup->holder()->IsGlobalObject()) {
|
| - depth1 =
|
| - optimization.GetPrototypeDepthOfExpectedType(object,
|
| - interceptor_holder);
|
| + !lookup->holder()->IsGlobalObject()) {
|
| + depth1 = optimization.GetPrototypeDepthOfExpectedType(
|
| + object, interceptor_holder);
|
| if (depth1 == kInvalidProtoDepth) {
|
| - depth2 =
|
| - optimization.GetPrototypeDepthOfExpectedType(interceptor_holder,
|
| - lookup->holder());
|
| + depth2 = optimization.GetPrototypeDepthOfExpectedType(
|
| + interceptor_holder, Handle<JSObject>(lookup->holder()));
|
| }
|
| - can_do_fast_api_call = (depth1 != kInvalidProtoDepth) ||
|
| - (depth2 != kInvalidProtoDepth);
|
| + can_do_fast_api_call =
|
| + depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth;
|
| }
|
|
|
| __ IncrementCounter(counters->call_const_interceptor(), 1,
|
| - scratch1, scratch2);
|
| + scratch1, scratch2);
|
|
|
| if (can_do_fast_api_call) {
|
| __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1,
|
| @@ -798,9 +712,9 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
| Label miss_cleanup;
|
| Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label;
|
| Register holder =
|
| - stub_compiler_->CheckPrototypes(object, receiver,
|
| - interceptor_holder, scratch1,
|
| - scratch2, scratch3, name, depth1, miss);
|
| + stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
|
| + scratch1, scratch2, scratch3,
|
| + name, depth1, miss);
|
|
|
| // Invoke an interceptor and if it provides a value,
|
| // branch to |regular_invoke|.
|
| @@ -813,10 +727,11 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
|
|
| // Check that the maps from interceptor's holder to constant function's
|
| // holder haven't changed and thus we can use cached constant function.
|
| - if (interceptor_holder != lookup->holder()) {
|
| + if (*interceptor_holder != lookup->holder()) {
|
| stub_compiler_->CheckPrototypes(interceptor_holder, receiver,
|
| - lookup->holder(), scratch1,
|
| - scratch2, scratch3, name, depth2, miss);
|
| + Handle<JSObject>(lookup->holder()),
|
| + scratch1, scratch2, scratch3,
|
| + name, depth2, miss);
|
| } else {
|
| // CheckPrototypes has a side effect of fetching a 'holder'
|
| // for API (object which is instanceof for the signature). It's
|
| @@ -827,10 +742,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
|
|
| // Invoke function.
|
| if (can_do_fast_api_call) {
|
| - MaybeObject* result = GenerateFastApiDirectCall(masm,
|
| - optimization,
|
| - arguments_.immediate());
|
| - if (result->IsFailure()) return result;
|
| + GenerateFastApiDirectCall(masm, optimization, arguments_.immediate());
|
| } else {
|
| CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| ? CALL_AS_FUNCTION
|
| @@ -851,68 +763,57 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
| if (can_do_fast_api_call) {
|
| FreeSpaceForFastApiCall(masm);
|
| }
|
| -
|
| - return masm->isolate()->heap()->undefined_value();
|
| }
|
|
|
| void CompileRegular(MacroAssembler* masm,
|
| - JSObject* object,
|
| + Handle<JSObject> object,
|
| Register receiver,
|
| Register scratch1,
|
| Register scratch2,
|
| Register scratch3,
|
| - String* name,
|
| - JSObject* interceptor_holder,
|
| + Handle<String> name,
|
| + Handle<JSObject> interceptor_holder,
|
| Label* miss_label) {
|
| Register holder =
|
| stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
|
| - scratch1, scratch2, scratch3, name,
|
| - miss_label);
|
| + scratch1, scratch2, scratch3,
|
| + name, miss_label);
|
|
|
| // Call a runtime function to load the interceptor property.
|
| FrameScope scope(masm, StackFrame::INTERNAL);
|
| // Save the name_ register across the call.
|
| __ push(name_);
|
|
|
| - PushInterceptorArguments(masm,
|
| - receiver,
|
| - holder,
|
| - name_,
|
| - interceptor_holder);
|
| + PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder);
|
|
|
| __ CallExternalReference(
|
| ExternalReference(
|
| IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
|
| masm->isolate()),
|
| 5);
|
| -
|
| // Restore the name_ register.
|
| __ pop(name_);
|
| -
|
| // Leave the internal frame.
|
| }
|
|
|
| void LoadWithInterceptor(MacroAssembler* masm,
|
| Register receiver,
|
| Register holder,
|
| - JSObject* holder_obj,
|
| + Handle<JSObject> holder_obj,
|
| Register scratch,
|
| Label* interceptor_succeeded) {
|
| {
|
| FrameScope scope(masm, StackFrame::INTERNAL);
|
|
|
| __ Push(holder, name_);
|
| -
|
| CompileCallLoadPropertyWithInterceptor(masm,
|
| receiver,
|
| holder,
|
| name_,
|
| holder_obj);
|
| -
|
| __ pop(name_); // Restore the name.
|
| __ pop(receiver); // Restore the holder.
|
| }
|
| -
|
| // If interceptor returns no-result sentinel, call the constant function.
|
| __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
|
| __ Branch(interceptor_succeeded, ne, v0, Operand(scratch));
|
| @@ -945,29 +846,6 @@ static void GenerateCheckPropertyCell(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
| -// handlified.
|
| -MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCell(
|
| - MacroAssembler* masm,
|
| - GlobalObject* global,
|
| - String* name,
|
| - Register scratch,
|
| - Label* miss) {
|
| - Object* probe;
|
| - { MaybeObject* maybe_probe = global->EnsurePropertyCell(name);
|
| - if (!maybe_probe->ToObject(&probe)) return maybe_probe;
|
| - }
|
| - JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
|
| - ASSERT(cell->value()->IsTheHole());
|
| - __ li(scratch, Operand(Handle<Object>(cell)));
|
| - __ lw(scratch,
|
| - FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
|
| - __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
|
| - __ Branch(miss, ne, scratch, Operand(at));
|
| - return cell;
|
| -}
|
| -
|
| -
|
| // Calls GenerateCheckPropertyCell for each global object in the prototype chain
|
| // from object to (but not including) holder.
|
| static void GenerateCheckPropertyCells(MacroAssembler* masm,
|
| @@ -990,34 +868,6 @@ static void GenerateCheckPropertyCells(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
| -// handlified.
|
| -MUST_USE_RESULT static MaybeObject* TryGenerateCheckPropertyCells(
|
| - MacroAssembler* masm,
|
| - JSObject* object,
|
| - JSObject* holder,
|
| - String* name,
|
| - Register scratch,
|
| - Label* miss) {
|
| - JSObject* current = object;
|
| - while (current != holder) {
|
| - if (current->IsGlobalObject()) {
|
| - // Returns a cell or a failure.
|
| - MaybeObject* result = TryGenerateCheckPropertyCell(
|
| - masm,
|
| - GlobalObject::cast(current),
|
| - name,
|
| - scratch,
|
| - miss);
|
| - if (result->IsFailure()) return result;
|
| - }
|
| - ASSERT(current->IsJSObject());
|
| - current = JSObject::cast(current->GetPrototype());
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -
|
| // Convert and store int passed in register ival to IEEE 754 single precision
|
| // floating point value at memory location (dst + 4 * wordoffset)
|
| // If FPU is available use it for conversion.
|
| @@ -1240,146 +1090,6 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
|
| }
|
|
|
|
|
| -Register StubCompiler::CheckPrototypes(JSObject* object,
|
| - Register object_reg,
|
| - JSObject* holder,
|
| - Register holder_reg,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - String* name,
|
| - int save_at_depth,
|
| - Label* miss) {
|
| - // Make sure there's no overlap between holder and object registers.
|
| - ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
|
| - ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg)
|
| - && !scratch2.is(scratch1));
|
| -
|
| - // Keep track of the current object in register reg.
|
| - Register reg = object_reg;
|
| - int depth = 0;
|
| -
|
| - if (save_at_depth == depth) {
|
| - __ sw(reg, MemOperand(sp));
|
| - }
|
| -
|
| - // Check the maps in the prototype chain.
|
| - // Traverse the prototype chain from the object and do map checks.
|
| - JSObject* current = object;
|
| - while (current != holder) {
|
| - depth++;
|
| -
|
| - // Only global objects and objects that do not require access
|
| - // checks are allowed in stubs.
|
| - ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded());
|
| -
|
| - ASSERT(current->GetPrototype()->IsJSObject());
|
| - JSObject* prototype = JSObject::cast(current->GetPrototype());
|
| - if (!current->HasFastProperties() &&
|
| - !current->IsJSGlobalObject() &&
|
| - !current->IsJSGlobalProxy()) {
|
| - if (!name->IsSymbol()) {
|
| - MaybeObject* maybe_lookup_result = heap()->LookupSymbol(name);
|
| - Object* lookup_result = NULL; // Initialization to please compiler.
|
| - if (!maybe_lookup_result->ToObject(&lookup_result)) {
|
| - set_failure(Failure::cast(maybe_lookup_result));
|
| - return reg;
|
| - }
|
| - name = String::cast(lookup_result);
|
| - }
|
| - ASSERT(current->property_dictionary()->FindEntry(name) ==
|
| - StringDictionary::kNotFound);
|
| -
|
| - MaybeObject* negative_lookup =
|
| - TryGenerateDictionaryNegativeLookup(masm(),
|
| - miss,
|
| - reg,
|
| - name,
|
| - scratch1,
|
| - scratch2);
|
| -
|
| - if (negative_lookup->IsFailure()) {
|
| - set_failure(Failure::cast(negative_lookup));
|
| - return reg;
|
| - }
|
| -
|
| - __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
|
| - reg = holder_reg; // From now the object is in holder_reg.
|
| - __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
|
| - } else if (heap()->InNewSpace(prototype)) {
|
| - // Get the map of the current object.
|
| - __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
|
| -
|
| - // Branch on the result of the map check.
|
| - __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map())));
|
| -
|
| - // 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.
|
| - if (current->IsJSGlobalProxy()) {
|
| - __ CheckAccessGlobalProxy(reg, scratch1, miss);
|
| - // Restore scratch register to be the map of the object. In the
|
| - // new space case below, we load the prototype from the map in
|
| - // the scratch register.
|
| - __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
|
| - }
|
| -
|
| - reg = holder_reg; // From now the object is in holder_reg.
|
| - // The prototype is in new space; we cannot store a reference
|
| - // to it in the code. Load it from the map.
|
| - __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset));
|
| - } else {
|
| - // Check the map of the current object.
|
| - __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
|
| - // Branch on the result of the map check.
|
| - __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map())));
|
| - // 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.
|
| - if (current->IsJSGlobalProxy()) {
|
| - __ CheckAccessGlobalProxy(reg, scratch1, miss);
|
| - }
|
| - // The prototype is in old space; load it directly.
|
| - reg = holder_reg; // From now the object is in holder_reg.
|
| - __ li(reg, Operand(Handle<JSObject>(prototype)));
|
| - }
|
| -
|
| - if (save_at_depth == depth) {
|
| - __ sw(reg, MemOperand(sp));
|
| - }
|
| -
|
| - // Go to the next object in the prototype chain.
|
| - current = prototype;
|
| - }
|
| -
|
| - // Check the holder map.
|
| - __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset));
|
| - __ Branch(miss, ne, scratch1, Operand(Handle<Map>(current->map())));
|
| -
|
| - // Log the check depth.
|
| - LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1));
|
| - // Perform security check for access to the global object.
|
| - ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
|
| - if (holder->IsJSGlobalProxy()) {
|
| - __ CheckAccessGlobalProxy(reg, scratch1, miss);
|
| - }
|
| -
|
| - // If we've skipped any global objects, it's not enough to verify
|
| - // that their maps haven't changed. We also need to check that the
|
| - // property cell for the property is still empty.
|
| -
|
| - MaybeObject* result = TryGenerateCheckPropertyCells(masm(),
|
| - object,
|
| - holder,
|
| - name,
|
| - scratch1,
|
| - miss);
|
| - if (result->IsFailure()) set_failure(Failure::cast(result));
|
| -
|
| - // Return the register containing the holder.
|
| - return reg;
|
| -}
|
| -
|
| -
|
| void StubCompiler::GenerateLoadField(Handle<JSObject> object,
|
| Handle<JSObject> holder,
|
| Register receiver,
|
| @@ -1424,49 +1134,43 @@ void StubCompiler::GenerateLoadConstant(Handle<JSObject> object,
|
| }
|
|
|
|
|
| -MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
|
| - JSObject* holder,
|
| - Register receiver,
|
| - Register name_reg,
|
| - Register scratch1,
|
| - Register scratch2,
|
| - Register scratch3,
|
| - AccessorInfo* callback,
|
| - String* name,
|
| - Label* miss) {
|
| +void StubCompiler::GenerateLoadCallback(Handle<JSObject> object,
|
| + Handle<JSObject> holder,
|
| + Register receiver,
|
| + Register name_reg,
|
| + Register scratch1,
|
| + Register scratch2,
|
| + Register scratch3,
|
| + Handle<AccessorInfo> callback,
|
| + Handle<String> name,
|
| + Label* miss) {
|
| // Check that the receiver isn't a smi.
|
| __ JumpIfSmi(receiver, miss, scratch1);
|
|
|
| // Check that the maps haven't changed.
|
| - Register reg =
|
| - CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
|
| - name, miss);
|
| + Register reg = CheckPrototypes(object, receiver, holder, scratch1,
|
| + scratch2, scratch3, name, miss);
|
|
|
| // Build AccessorInfo::args_ list on the stack and push property name below
|
| // the exit frame to make GC aware of them and store pointers to them.
|
| __ push(receiver);
|
| __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_
|
| - Handle<AccessorInfo> callback_handle(callback);
|
| - if (heap()->InNewSpace(callback_handle->data())) {
|
| - __ li(scratch3, callback_handle);
|
| + if (heap()->InNewSpace(callback->data())) {
|
| + __ li(scratch3, callback);
|
| __ lw(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
|
| } else {
|
| - __ li(scratch3, Handle<Object>(callback_handle->data()));
|
| + __ li(scratch3, Handle<Object>(callback->data()));
|
| }
|
| __ Push(reg, scratch3, name_reg);
|
| __ mov(a2, scratch2); // Saved in case scratch2 == a1.
|
| __ mov(a1, sp); // a1 (first argument - see note below) = Handle<String>
|
|
|
| - Address getter_address = v8::ToCData<Address>(callback->getter());
|
| - ApiFunction fun(getter_address);
|
| -
|
| // NOTE: the O32 abi requires a0 to hold a special pointer when returning a
|
| // struct from the function (which is currently the case). This means we pass
|
| // the arguments in a1-a2 instead of a0-a1. TryCallApiFunctionAndReturn
|
| // will handle setting up a0.
|
|
|
| const int kApiStackSpace = 1;
|
| -
|
| FrameScope frame_scope(masm(), StackFrame::MANUAL);
|
| __ EnterExitFrame(false, kApiStackSpace);
|
|
|
| @@ -1476,28 +1180,26 @@ MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
|
| // a2 (second argument - see note above) = AccessorInfo&
|
| __ Addu(a2, sp, kPointerSize);
|
|
|
| - // Emitting a stub call may try to allocate (if the code is not
|
| - // already generated). Do not allow the assembler to perform a
|
| - // garbage collection but instead return the allocation failure
|
| - // object.
|
| + const int kStackUnwindSpace = 4;
|
| + Address getter_address = v8::ToCData<Address>(callback->getter());
|
| + ApiFunction fun(getter_address);
|
| ExternalReference ref =
|
| ExternalReference(&fun,
|
| ExternalReference::DIRECT_GETTER_CALL,
|
| masm()->isolate());
|
| - // 4 args - will be freed later by LeaveExitFrame.
|
| - return masm()->TryCallApiFunctionAndReturn(ref, 4);
|
| + __ CallApiFunctionAndReturn(ref, kStackUnwindSpace);
|
| }
|
|
|
|
|
| -void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
| - JSObject* interceptor_holder,
|
| +void StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object,
|
| + Handle<JSObject> interceptor_holder,
|
| LookupResult* lookup,
|
| Register receiver,
|
| Register name_reg,
|
| Register scratch1,
|
| Register scratch2,
|
| Register scratch3,
|
| - String* name,
|
| + Handle<String> name,
|
| Label* miss) {
|
| ASSERT(interceptor_holder->HasNamedInterceptor());
|
| ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
|
| @@ -1513,9 +1215,9 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
| if (lookup->type() == FIELD) {
|
| compile_followup_inline = true;
|
| } else if (lookup->type() == CALLBACKS &&
|
| - lookup->GetCallbackObject()->IsAccessorInfo() &&
|
| - AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL) {
|
| - compile_followup_inline = true;
|
| + lookup->GetCallbackObject()->IsAccessorInfo()) {
|
| + compile_followup_inline =
|
| + AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL;
|
| }
|
| }
|
|
|
| @@ -1532,14 +1234,12 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
| // Requires a frame to make GC aware of pushed pointers.
|
| {
|
| FrameScope frame_scope(masm(), StackFrame::INTERNAL);
|
| -
|
| if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
|
| // CALLBACKS case needs a receiver to be passed into C++ callback.
|
| __ Push(receiver, holder_reg, name_reg);
|
| } else {
|
| __ Push(holder_reg, name_reg);
|
| }
|
| -
|
| // Invoke an interceptor. Note: map checks from receiver to
|
| // interceptor's holder has been compiled before (see a caller
|
| // of this method).
|
| @@ -1548,7 +1248,6 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
| holder_reg,
|
| name_reg,
|
| interceptor_holder);
|
| -
|
| // Check if interceptor provided a value for property. If it's
|
| // the case, return immediately.
|
| Label interceptor_failed;
|
| @@ -1563,16 +1262,14 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
| if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
|
| __ pop(receiver);
|
| }
|
| -
|
| // Leave the internal frame.
|
| }
|
| -
|
| // Check that the maps from interceptor's holder to lookup's holder
|
| // haven't changed. And load lookup's holder into |holder| register.
|
| - if (interceptor_holder != lookup->holder()) {
|
| + if (*interceptor_holder != lookup->holder()) {
|
| holder_reg = CheckPrototypes(interceptor_holder,
|
| holder_reg,
|
| - lookup->holder(),
|
| + Handle<JSObject>(lookup->holder()),
|
| scratch1,
|
| scratch2,
|
| scratch3,
|
| @@ -1591,15 +1288,14 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
|
| // We found CALLBACKS property in prototype chain of interceptor's
|
| // holder.
|
| ASSERT(lookup->type() == CALLBACKS);
|
| - ASSERT(lookup->GetCallbackObject()->IsAccessorInfo());
|
| - AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
|
| - ASSERT(callback != NULL);
|
| + Handle<AccessorInfo> callback(
|
| + AccessorInfo::cast(lookup->GetCallbackObject()));
|
| ASSERT(callback->getter() != NULL);
|
|
|
| // Tail call to runtime.
|
| // Important invariant in CALLBACKS case: the code above must be
|
| // structured to never clobber |receiver| register.
|
| - __ li(scratch2, Handle<AccessorInfo>(callback));
|
| + __ li(scratch2, callback);
|
| // holder_reg is either receiver or scratch1.
|
| if (!receiver.is(holder_reg)) {
|
| ASSERT(scratch1.is(holder_reg));
|
| @@ -1642,9 +1338,9 @@ void CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) {
|
| }
|
|
|
|
|
| -void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object,
|
| - JSObject* holder,
|
| - String* name,
|
| +void CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object,
|
| + Handle<JSObject> holder,
|
| + Handle<String> name,
|
| Label* miss) {
|
| ASSERT(holder->IsGlobalObject());
|
|
|
| @@ -1657,7 +1353,7 @@ void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object,
|
| // If the object is the holder then we know that it's a global
|
| // object which can only happen for contextual calls. In this case,
|
| // the receiver cannot be a smi.
|
| - if (object != holder) {
|
| + if (!object.is_identical_to(holder)) {
|
| __ JumpIfSmi(a0, miss);
|
| }
|
|
|
| @@ -1666,15 +1362,16 @@ void CallStubCompiler::GenerateGlobalReceiverCheck(JSObject* object,
|
| }
|
|
|
|
|
| -void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - Label* miss) {
|
| +void CallStubCompiler::GenerateLoadFunctionFromCell(
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Label* miss) {
|
| // Get the value from the cell.
|
| - __ li(a3, Operand(Handle<JSGlobalPropertyCell>(cell)));
|
| + __ li(a3, Operand(cell));
|
| __ lw(a1, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset));
|
|
|
| // Check that the cell contains the same function.
|
| - if (heap()->InNewSpace(function)) {
|
| + if (heap()->InNewSpace(*function)) {
|
| // We can't embed a pointer to a function in new space so we have
|
| // to verify that the shared function info is unchanged. This has
|
| // the nice side effect that multiple closures based on the same
|
| @@ -1689,7 +1386,7 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
|
| __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
|
| __ Branch(miss, ne, t0, Operand(a3));
|
| } else {
|
| - __ Branch(miss, ne, a1, Operand(Handle<JSFunction>(function)));
|
| + __ Branch(miss, ne, a1, Operand(function));
|
| }
|
| }
|
|
|
| @@ -1703,20 +1400,6 @@ void CallStubCompiler::GenerateMissBranch() {
|
| }
|
|
|
|
|
| -// TODO(kmillikin): Eliminate this function when the stub cache is fully
|
| -// handlified.
|
| -MaybeObject* CallStubCompiler::TryGenerateMissBranch() {
|
| - MaybeObject* maybe_obj =
|
| - isolate()->stub_cache()->TryComputeCallMiss(arguments().immediate(),
|
| - kind_,
|
| - extra_state_);
|
| - Object* obj;
|
| - if (!maybe_obj->ToObject(&obj)) return maybe_obj;
|
| - __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
|
| - return obj;
|
| -}
|
| -
|
| -
|
| Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
|
| Handle<JSObject> holder,
|
| int index,
|
| @@ -1751,11 +1434,12 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
| - JSObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name) {
|
| +Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
| + Handle<Object> object,
|
| + Handle<JSObject> holder,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : name
|
| // -- ra : return address
|
| @@ -1765,11 +1449,11 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
| // -----------------------------------
|
|
|
| // If object is not an array, bail out to regular call.
|
| - if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value();
|
| + if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
|
|
|
| Label miss;
|
|
|
| - GenerateNameCheck(Handle<String>(name), &miss);
|
| + GenerateNameCheck(name, &miss);
|
|
|
| Register receiver = a1;
|
|
|
| @@ -1781,8 +1465,8 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
| __ JumpIfSmi(receiver, &miss);
|
|
|
| // Check that the maps haven't changed.
|
| - CheckPrototypes(JSObject::cast(object), receiver,
|
| - holder, a3, v0, t0, name, &miss);
|
| + CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, a3, v0, t0,
|
| + name, &miss);
|
|
|
| if (argc == 0) {
|
| // Nothing to do, just return the length.
|
| @@ -1791,10 +1475,8 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
| __ Ret();
|
| } else {
|
| Label call_builtin;
|
| -
|
| Register elements = a3;
|
| Register end_elements = t1;
|
| -
|
| // Get the elements array of the object.
|
| __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
|
|
|
| @@ -1935,19 +1617,19 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
|
|
|
| // Handle call cache miss.
|
| __ bind(&miss);
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return TryGetCode(function);
|
| + return GetCode(function);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
|
| - JSObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name) {
|
| +Handle<Code> CallStubCompiler::CompileArrayPopCall(
|
| + Handle<Object> object,
|
| + Handle<JSObject> holder,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : name
|
| // -- ra : return address
|
| @@ -1957,25 +1639,22 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
|
| // -----------------------------------
|
|
|
| // If object is not an array, bail out to regular call.
|
| - if (!object->IsJSArray() || cell != NULL) return heap()->undefined_value();
|
| + if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null();
|
|
|
| Label miss, return_undefined, call_builtin;
|
| -
|
| Register receiver = a1;
|
| Register elements = a3;
|
| -
|
| - GenerateNameCheck(Handle<String>(name), &miss);
|
| + GenerateNameCheck(name, &miss);
|
|
|
| // Get the receiver from the stack.
|
| const int argc = arguments().immediate();
|
| __ lw(receiver, MemOperand(sp, argc * kPointerSize));
|
| -
|
| // Check that the receiver isn't a smi.
|
| __ JumpIfSmi(receiver, &miss);
|
|
|
| // Check that the maps haven't changed.
|
| - CheckPrototypes(JSObject::cast(object),
|
| - receiver, holder, elements, t0, v0, name, &miss);
|
| + CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements,
|
| + t0, v0, name, &miss);
|
|
|
| // Get the elements array of the object.
|
| __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset));
|
| @@ -2024,20 +1703,19 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object,
|
|
|
| // Handle call cache miss.
|
| __ bind(&miss);
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return TryGetCode(function);
|
| + return GetCode(function);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
| - Object* object,
|
| - JSObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name) {
|
| +Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
|
| + Handle<Object> object,
|
| + Handle<JSObject> holder,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : function name
|
| // -- ra : return address
|
| @@ -2047,10 +1725,9 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
| // -----------------------------------
|
|
|
| // If object is not a string, bail out to regular call.
|
| - if (!object->IsString() || cell != NULL) return heap()->undefined_value();
|
| + if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
|
|
|
| const int argc = arguments().immediate();
|
| -
|
| Label miss;
|
| Label name_miss;
|
| Label index_out_of_range;
|
| @@ -2063,16 +1740,16 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
| index_out_of_range_label = &miss;
|
| }
|
|
|
| - GenerateNameCheck(Handle<String>(name), &name_miss);
|
| + GenerateNameCheck(name, &name_miss);
|
|
|
| // Check that the maps starting from the prototype haven't changed.
|
| GenerateDirectLoadGlobalFunctionPrototype(masm(),
|
| Context::STRING_FUNCTION_INDEX,
|
| v0,
|
| &miss);
|
| - ASSERT(object != holder);
|
| - CheckPrototypes(JSObject::cast(object->GetPrototype()), v0, holder,
|
| - a1, a3, t0, name, &miss);
|
| + ASSERT(!object.is_identical_to(holder));
|
| + CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
|
| + v0, holder, a1, a3, t0, name, &miss);
|
|
|
| Register receiver = a1;
|
| Register index = t1;
|
| @@ -2085,20 +1762,20 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
| __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
|
| }
|
|
|
| - StringCharCodeAtGenerator char_code_at_generator(receiver,
|
| - index,
|
| - scratch,
|
| - result,
|
| - &miss, // When not a string.
|
| - &miss, // When not a number.
|
| - index_out_of_range_label,
|
| - STRING_INDEX_IS_NUMBER);
|
| - char_code_at_generator.GenerateFast(masm());
|
| + StringCharCodeAtGenerator generator(receiver,
|
| + index,
|
| + scratch,
|
| + result,
|
| + &miss, // When not a string.
|
| + &miss, // When not a number.
|
| + index_out_of_range_label,
|
| + STRING_INDEX_IS_NUMBER);
|
| + generator.GenerateFast(masm());
|
| __ Drop(argc + 1);
|
| __ Ret();
|
|
|
| StubRuntimeCallHelper call_helper;
|
| - char_code_at_generator.GenerateSlow(masm(), call_helper);
|
| + generator.GenerateSlow(masm(), call_helper);
|
|
|
| if (index_out_of_range.is_linked()) {
|
| __ bind(&index_out_of_range);
|
| @@ -2109,22 +1786,21 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
|
|
|
| __ bind(&miss);
|
| // Restore function name in a2.
|
| - __ li(a2, Handle<String>(name));
|
| + __ li(a2, name);
|
| __ bind(&name_miss);
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return TryGetCode(function);
|
| + return GetCode(function);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileStringCharAtCall(
|
| - Object* object,
|
| - JSObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name) {
|
| +Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
| + Handle<Object> object,
|
| + Handle<JSObject> holder,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : function name
|
| // -- ra : return address
|
| @@ -2134,31 +1810,28 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
|
| // -----------------------------------
|
|
|
| // If object is not a string, bail out to regular call.
|
| - if (!object->IsString() || cell != NULL) return heap()->undefined_value();
|
| + if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
|
|
|
| const int argc = arguments().immediate();
|
| -
|
| Label miss;
|
| Label name_miss;
|
| Label index_out_of_range;
|
| Label* index_out_of_range_label = &index_out_of_range;
|
| -
|
| if (kind_ == Code::CALL_IC &&
|
| (CallICBase::StringStubState::decode(extra_state_) ==
|
| DEFAULT_STRING_STUB)) {
|
| index_out_of_range_label = &miss;
|
| }
|
| -
|
| - GenerateNameCheck(Handle<String>(name), &name_miss);
|
| + GenerateNameCheck(name, &name_miss);
|
|
|
| // Check that the maps starting from the prototype haven't changed.
|
| GenerateDirectLoadGlobalFunctionPrototype(masm(),
|
| Context::STRING_FUNCTION_INDEX,
|
| v0,
|
| &miss);
|
| - ASSERT(object != holder);
|
| - CheckPrototypes(JSObject::cast(object->GetPrototype()), v0, holder,
|
| - a1, a3, t0, name, &miss);
|
| + ASSERT(!object.is_identical_to(holder));
|
| + CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())),
|
| + v0, holder, a1, a3, t0, name, &miss);
|
|
|
| Register receiver = v0;
|
| Register index = t1;
|
| @@ -2172,21 +1845,21 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
|
| __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
|
| }
|
|
|
| - StringCharAtGenerator char_at_generator(receiver,
|
| - index,
|
| - scratch1,
|
| - scratch2,
|
| - result,
|
| - &miss, // When not a string.
|
| - &miss, // When not a number.
|
| - index_out_of_range_label,
|
| - STRING_INDEX_IS_NUMBER);
|
| - char_at_generator.GenerateFast(masm());
|
| + StringCharAtGenerator generator(receiver,
|
| + index,
|
| + scratch1,
|
| + scratch2,
|
| + result,
|
| + &miss, // When not a string.
|
| + &miss, // When not a number.
|
| + index_out_of_range_label,
|
| + STRING_INDEX_IS_NUMBER);
|
| + generator.GenerateFast(masm());
|
| __ Drop(argc + 1);
|
| __ Ret();
|
|
|
| StubRuntimeCallHelper call_helper;
|
| - char_at_generator.GenerateSlow(masm(), call_helper);
|
| + generator.GenerateSlow(masm(), call_helper);
|
|
|
| if (index_out_of_range.is_linked()) {
|
| __ bind(&index_out_of_range);
|
| @@ -2197,22 +1870,21 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
|
|
|
| __ bind(&miss);
|
| // Restore function name in a2.
|
| - __ li(a2, Handle<String>(name));
|
| + __ li(a2, name);
|
| __ bind(&name_miss);
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return TryGetCode(function);
|
| + return GetCode(function);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
|
| - Object* object,
|
| - JSObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name) {
|
| +Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
|
| + Handle<Object> object,
|
| + Handle<JSObject> holder,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : function name
|
| // -- ra : return address
|
| @@ -2225,22 +1897,23 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
|
|
|
| // If the object is not a JSObject or we got an unexpected number of
|
| // arguments, bail out to the regular call.
|
| - if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
|
| + if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
|
|
|
| Label miss;
|
| - GenerateNameCheck(Handle<String>(name), &miss);
|
| + GenerateNameCheck(name, &miss);
|
|
|
| - if (cell == NULL) {
|
| + if (cell.is_null()) {
|
| __ lw(a1, MemOperand(sp, 1 * kPointerSize));
|
|
|
| STATIC_ASSERT(kSmiTag == 0);
|
| __ JumpIfSmi(a1, &miss);
|
|
|
| - CheckPrototypes(JSObject::cast(object), a1, holder, v0, a3, t0, name,
|
| - &miss);
|
| + CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0,
|
| + name, &miss);
|
| } else {
|
| - ASSERT(cell->value() == function);
|
| - GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
|
| + ASSERT(cell->value() == *function);
|
| + GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
|
| + &miss);
|
| GenerateLoadFunctionFromCell(cell, function, &miss);
|
| }
|
|
|
| @@ -2256,13 +1929,13 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
|
| // Convert the smi code to uint16.
|
| __ And(code, code, Operand(Smi::FromInt(0xffff)));
|
|
|
| - StringCharFromCodeGenerator char_from_code_generator(code, v0);
|
| - char_from_code_generator.GenerateFast(masm());
|
| + StringCharFromCodeGenerator generator(code, v0);
|
| + generator.GenerateFast(masm());
|
| __ Drop(argc + 1);
|
| __ Ret();
|
|
|
| StubRuntimeCallHelper call_helper;
|
| - char_from_code_generator.GenerateSlow(masm(), call_helper);
|
| + generator.GenerateSlow(masm(), call_helper);
|
|
|
| // Tail call the full function. We do not have to patch the receiver
|
| // because the function makes no use of it.
|
| @@ -2271,19 +1944,19 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
|
|
|
| __ bind(&miss);
|
| // a2: function name.
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name);
|
| + return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
|
| - JSObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name) {
|
| +Handle<Code> CallStubCompiler::CompileMathFloorCall(
|
| + Handle<Object> object,
|
| + Handle<JSObject> holder,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : function name
|
| // -- ra : return address
|
| @@ -2292,30 +1965,29 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
|
| // -- sp[argc * 4] : receiver
|
| // -----------------------------------
|
|
|
| - if (!CpuFeatures::IsSupported(FPU))
|
| - return heap()->undefined_value();
|
| - CpuFeatures::Scope scope_fpu(FPU);
|
| + if (!CpuFeatures::IsSupported(FPU)) {
|
| + return Handle<Code>::null();
|
| + }
|
|
|
| + CpuFeatures::Scope scope_fpu(FPU);
|
| const int argc = arguments().immediate();
|
| -
|
| // If the object is not a JSObject or we got an unexpected number of
|
| // arguments, bail out to the regular call.
|
| - if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
|
| + if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
|
|
|
| Label miss, slow;
|
| - GenerateNameCheck(Handle<String>(name), &miss);
|
| + GenerateNameCheck(name, &miss);
|
|
|
| - if (cell == NULL) {
|
| + if (cell.is_null()) {
|
| __ lw(a1, MemOperand(sp, 1 * kPointerSize));
|
| -
|
| STATIC_ASSERT(kSmiTag == 0);
|
| __ JumpIfSmi(a1, &miss);
|
| -
|
| - CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name,
|
| - &miss);
|
| + CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0,
|
| + name, &miss);
|
| } else {
|
| - ASSERT(cell->value() == function);
|
| - GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
|
| + ASSERT(cell->value() == *function);
|
| + GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
|
| + &miss);
|
| GenerateLoadFunctionFromCell(cell, function, &miss);
|
| }
|
|
|
| @@ -2405,19 +2077,19 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
|
|
|
| __ bind(&miss);
|
| // a2: function name.
|
| - MaybeObject* obj = TryGenerateMissBranch();
|
| - if (obj->IsFailure()) return obj;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name);
|
| + return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
|
| - JSObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name) {
|
| +Handle<Code> CallStubCompiler::CompileMathAbsCall(
|
| + Handle<Object> object,
|
| + Handle<JSObject> holder,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : function name
|
| // -- ra : return address
|
| @@ -2427,25 +2099,23 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
|
| // -----------------------------------
|
|
|
| const int argc = arguments().immediate();
|
| -
|
| // If the object is not a JSObject or we got an unexpected number of
|
| // arguments, bail out to the regular call.
|
| - if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
|
| + if (!object->IsJSObject() || argc != 1) return Handle<Code>::null();
|
|
|
| Label miss;
|
| - GenerateNameCheck(Handle<String>(name), &miss);
|
|
|
| - if (cell == NULL) {
|
| + GenerateNameCheck(name, &miss);
|
| + if (cell.is_null()) {
|
| __ lw(a1, MemOperand(sp, 1 * kPointerSize));
|
| -
|
| STATIC_ASSERT(kSmiTag == 0);
|
| __ JumpIfSmi(a1, &miss);
|
| -
|
| - CheckPrototypes(JSObject::cast(object), a1, holder, v0, a3, t0, name,
|
| - &miss);
|
| + CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0,
|
| + name, &miss);
|
| } else {
|
| - ASSERT(cell->value() == function);
|
| - GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
|
| + ASSERT(cell->value() == *function);
|
| + GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name,
|
| + &miss);
|
| GenerateLoadFunctionFromCell(cell, function, &miss);
|
| }
|
|
|
| @@ -2507,37 +2177,36 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
|
|
|
| __ bind(&miss);
|
| // a2: function name.
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return (cell == NULL) ? TryGetCode(function) : TryGetCode(NORMAL, name);
|
| + return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileFastApiCall(
|
| +Handle<Code> CallStubCompiler::CompileFastApiCall(
|
| const CallOptimization& optimization,
|
| - Object* object,
|
| - JSObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name) {
|
| + Handle<Object> object,
|
| + Handle<JSObject> holder,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name) {
|
|
|
| Counters* counters = isolate()->counters();
|
|
|
| ASSERT(optimization.is_simple_api_call());
|
| // Bail out if object is a global object as we don't want to
|
| // repatch it to global receiver.
|
| - if (object->IsGlobalObject()) return heap()->undefined_value();
|
| - if (cell != NULL) return heap()->undefined_value();
|
| - if (!object->IsJSObject()) return heap()->undefined_value();
|
| + if (object->IsGlobalObject()) return Handle<Code>::null();
|
| + if (!cell.is_null()) return Handle<Code>::null();
|
| + if (!object->IsJSObject()) return Handle<Code>::null();
|
| int depth = optimization.GetPrototypeDepthOfExpectedType(
|
| - JSObject::cast(object), holder);
|
| - if (depth == kInvalidProtoDepth) return heap()->undefined_value();
|
| + Handle<JSObject>::cast(object), holder);
|
| + if (depth == kInvalidProtoDepth) return Handle<Code>::null();
|
|
|
| Label miss, miss_before_stack_reserved;
|
|
|
| - GenerateNameCheck(Handle<String>(name), &miss_before_stack_reserved);
|
| + GenerateNameCheck(name, &miss_before_stack_reserved);
|
|
|
| // Get the receiver from the stack.
|
| const int argc = arguments().immediate();
|
| @@ -2552,45 +2221,42 @@ MaybeObject* CallStubCompiler::CompileFastApiCall(
|
| ReserveSpaceForFastApiCall(masm(), a0);
|
|
|
| // Check that the maps haven't changed and find a Holder as a side effect.
|
| - CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name,
|
| + CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, name,
|
| depth, &miss);
|
|
|
| - MaybeObject* result = GenerateFastApiDirectCall(masm(), optimization, argc);
|
| - if (result->IsFailure()) return result;
|
| + GenerateFastApiDirectCall(masm(), optimization, argc);
|
|
|
| __ bind(&miss);
|
| FreeSpaceForFastApiCall(masm());
|
|
|
| __ bind(&miss_before_stack_reserved);
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return TryGetCode(function);
|
| + return GetCode(function);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
| - JSObject* holder,
|
| - JSFunction* function,
|
| - String* name,
|
| +Handle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object,
|
| + Handle<JSObject> holder,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name,
|
| CheckType check) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : name
|
| // -- ra : return address
|
| // -----------------------------------
|
| if (HasCustomCallGenerator(function)) {
|
| - MaybeObject* maybe_result = CompileCustomCall(
|
| - object, holder, NULL, function, name);
|
| - Object* result;
|
| - if (!maybe_result->ToObject(&result)) return maybe_result;
|
| - // Undefined means bail out to regular compiler.
|
| - if (!result->IsUndefined()) return result;
|
| + Handle<Code> code = CompileCustomCall(object, holder,
|
| + Handle<JSGlobalPropertyCell>::null(),
|
| + function, name);
|
| + // A null handle means bail out to the regular compiler code below.
|
| + if (!code.is_null()) return code;
|
| }
|
|
|
| Label miss;
|
|
|
| - GenerateNameCheck(Handle<String>(name), &miss);
|
| + GenerateNameCheck(name, &miss);
|
|
|
| // Get the receiver from the stack.
|
| const int argc = arguments().immediate();
|
| @@ -2605,16 +2271,14 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
| // Make sure that it's okay not to patch the on stack receiver
|
| // unless we're doing a receiver map check.
|
| ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
|
| -
|
| - SharedFunctionInfo* function_info = function->shared();
|
| switch (check) {
|
| case RECEIVER_MAP_CHECK:
|
| __ IncrementCounter(masm()->isolate()->counters()->call_const(),
|
| 1, a0, a3);
|
|
|
| // Check that the maps haven't changed.
|
| - CheckPrototypes(JSObject::cast(object), a1, holder, a0, a3, t0, name,
|
| - &miss);
|
| + CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0,
|
| + name, &miss);
|
|
|
| // Patch the receiver on the stack with the global proxy if
|
| // necessary.
|
| @@ -2625,28 +2289,25 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
| break;
|
|
|
| case STRING_CHECK:
|
| - if (!function->IsBuiltin() && !function_info->strict_mode()) {
|
| - // Calling non-strict non-builtins with a value as the receiver
|
| - // requires boxing.
|
| - __ jmp(&miss);
|
| - } else {
|
| + if (function->IsBuiltin() || function->shared()->strict_mode()) {
|
| // Check that the object is a two-byte string or a symbol.
|
| __ GetObjectType(a1, a3, a3);
|
| __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE));
|
| // Check that the maps starting from the prototype haven't changed.
|
| GenerateDirectLoadGlobalFunctionPrototype(
|
| masm(), Context::STRING_FUNCTION_INDEX, a0, &miss);
|
| - CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3,
|
| - a1, t0, name, &miss);
|
| - }
|
| - break;
|
| -
|
| - case NUMBER_CHECK: {
|
| - if (!function->IsBuiltin() && !function_info->strict_mode()) {
|
| + CheckPrototypes(
|
| + Handle<JSObject>(JSObject::cast(object->GetPrototype())),
|
| + a0, holder, a3, a1, t0, name, &miss);
|
| + } else {
|
| // Calling non-strict non-builtins with a value as the receiver
|
| // requires boxing.
|
| __ jmp(&miss);
|
| - } else {
|
| + }
|
| + break;
|
| +
|
| + case NUMBER_CHECK:
|
| + if (function->IsBuiltin() || function->shared()->strict_mode()) {
|
| Label fast;
|
| // Check that the object is a smi or a heap number.
|
| __ And(t1, a1, Operand(kSmiTagMask));
|
| @@ -2657,18 +2318,18 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
| // Check that the maps starting from the prototype haven't changed.
|
| GenerateDirectLoadGlobalFunctionPrototype(
|
| masm(), Context::NUMBER_FUNCTION_INDEX, a0, &miss);
|
| - CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3,
|
| - a1, t0, name, &miss);
|
| - }
|
| - break;
|
| - }
|
| -
|
| - case BOOLEAN_CHECK: {
|
| - if (!function->IsBuiltin() && !function_info->strict_mode()) {
|
| + CheckPrototypes(
|
| + Handle<JSObject>(JSObject::cast(object->GetPrototype())),
|
| + a0, holder, a3, a1, t0, name, &miss);
|
| + } else {
|
| // Calling non-strict non-builtins with a value as the receiver
|
| // requires boxing.
|
| __ jmp(&miss);
|
| - } else {
|
| + }
|
| + break;
|
| +
|
| + case BOOLEAN_CHECK:
|
| + if (function->IsBuiltin() || function->shared()->strict_mode()) {
|
| Label fast;
|
| // Check that the object is a boolean.
|
| __ LoadRoot(t0, Heap::kTrueValueRootIndex);
|
| @@ -2679,16 +2340,17 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
| // Check that the maps starting from the prototype haven't changed.
|
| GenerateDirectLoadGlobalFunctionPrototype(
|
| masm(), Context::BOOLEAN_FUNCTION_INDEX, a0, &miss);
|
| - CheckPrototypes(JSObject::cast(object->GetPrototype()), a0, holder, a3,
|
| - a1, t0, name, &miss);
|
| + CheckPrototypes(
|
| + Handle<JSObject>(JSObject::cast(object->GetPrototype())),
|
| + a0, holder, a3, a1, t0, name, &miss);
|
| + } else {
|
| + // Calling non-strict non-builtins with a value as the receiver
|
| + // requires boxing.
|
| + __ jmp(&miss);
|
| }
|
| break;
|
| }
|
|
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| -
|
| CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
| ? CALL_AS_FUNCTION
|
| : CALL_AS_METHOD;
|
| @@ -2697,17 +2359,16 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
|
| // Handle call cache miss.
|
| __ bind(&miss);
|
|
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return TryGetCode(function);
|
| + return GetCode(function);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
| - JSObject* holder,
|
| - String* name) {
|
| +Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
|
| + Handle<JSObject> holder,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : name
|
| // -- ra : return address
|
| @@ -2715,11 +2376,10 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
|
|
| Label miss;
|
|
|
| - GenerateNameCheck(Handle<String>(name), &miss);
|
| + GenerateNameCheck(name, &miss);
|
|
|
| // Get the number of arguments.
|
| const int argc = arguments().immediate();
|
| -
|
| LookupResult lookup(isolate());
|
| LookupPostInterceptor(holder, name, &lookup);
|
|
|
| @@ -2727,64 +2387,47 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
|
| __ lw(a1, MemOperand(sp, argc * kPointerSize));
|
|
|
| CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_);
|
| - MaybeObject* result = compiler.Compile(masm(),
|
| - object,
|
| - holder,
|
| - name,
|
| - &lookup,
|
| - a1,
|
| - a3,
|
| - t0,
|
| - a0,
|
| - &miss);
|
| - if (result->IsFailure()) {
|
| - return result;
|
| - }
|
| + compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0,
|
| + &miss);
|
|
|
| // Move returned value, the function to call, to a1.
|
| __ mov(a1, v0);
|
| // Restore receiver.
|
| __ lw(a0, MemOperand(sp, argc * kPointerSize));
|
|
|
| - GenerateCallFunction(masm(), Handle<Object>(object), arguments(), &miss,
|
| - extra_state_);
|
| + GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_);
|
|
|
| // Handle call cache miss.
|
| __ bind(&miss);
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return TryGetCode(INTERCEPTOR, name);
|
| + return GetCode(INTERCEPTOR, name);
|
| }
|
|
|
|
|
| -MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
|
| - GlobalObject* holder,
|
| - JSGlobalPropertyCell* cell,
|
| - JSFunction* function,
|
| - String* name) {
|
| +Handle<Code> CallStubCompiler::CompileCallGlobal(
|
| + Handle<JSObject> object,
|
| + Handle<GlobalObject> holder,
|
| + Handle<JSGlobalPropertyCell> cell,
|
| + Handle<JSFunction> function,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a2 : name
|
| // -- ra : return address
|
| // -----------------------------------
|
|
|
| if (HasCustomCallGenerator(function)) {
|
| - MaybeObject* maybe_result = CompileCustomCall(
|
| - object, holder, cell, function, name);
|
| - Object* result;
|
| - if (!maybe_result->ToObject(&result)) return maybe_result;
|
| - // Undefined means bail out to regular compiler.
|
| - if (!result->IsUndefined()) return result;
|
| + Handle<Code> code = CompileCustomCall(object, holder, cell, function, name);
|
| + // A null handle means bail out to the regular compiler code below.
|
| + if (!code.is_null()) return code;
|
| }
|
|
|
| Label miss;
|
| -
|
| - GenerateNameCheck(Handle<String>(name), &miss);
|
| + GenerateNameCheck(name, &miss);
|
|
|
| // Get the number of arguments.
|
| const int argc = arguments().immediate();
|
| -
|
| GenerateGlobalReceiverCheck(object, holder, name, &miss);
|
| GenerateLoadFunctionFromCell(cell, function, &miss);
|
|
|
| @@ -2801,7 +2444,6 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
|
| // Jump to the cached code (tail call).
|
| Counters* counters = masm()->isolate()->counters();
|
| __ IncrementCounter(counters->call_global_inline(), 1, a3, t0);
|
| - Handle<Code> code(function->code());
|
| ParameterCount expected(function->shared()->formal_parameter_count());
|
| CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
| ? CALL_AS_FUNCTION
|
| @@ -2816,11 +2458,10 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
|
| // Handle call cache miss.
|
| __ bind(&miss);
|
| __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3);
|
| - MaybeObject* maybe_result = TryGenerateMissBranch();
|
| - if (maybe_result->IsFailure()) return maybe_result;
|
| + GenerateMissBranch();
|
|
|
| // Return the generated code.
|
| - return TryGetCode(NORMAL, name);
|
| + return GetCode(NORMAL, name);
|
| }
|
|
|
|
|
| @@ -3053,29 +2694,24 @@ Handle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object,
|
| }
|
|
|
|
|
| -MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
|
| - JSObject* object,
|
| - JSObject* holder,
|
| - AccessorInfo* callback) {
|
| +Handle<Code> LoadStubCompiler::CompileLoadCallback(
|
| + Handle<String> name,
|
| + Handle<JSObject> object,
|
| + Handle<JSObject> holder,
|
| + Handle<AccessorInfo> callback) {
|
| // ----------- S t a t e -------------
|
| // -- a0 : receiver
|
| // -- a2 : name
|
| // -- ra : return address
|
| // -----------------------------------
|
| Label miss;
|
| -
|
| - MaybeObject* result = GenerateLoadCallback(object, holder, a0, a2, a3, a1, t0,
|
| - callback, name, &miss);
|
| - if (result->IsFailure()) {
|
| - miss.Unuse();
|
| - return result;
|
| - }
|
| -
|
| + GenerateLoadCallback(object, holder, a0, a2, a3, a1, t0, callback, name,
|
| + &miss);
|
| __ bind(&miss);
|
| GenerateLoadMiss(masm(), Code::LOAD_IC);
|
|
|
| // Return the generated code.
|
| - return TryGetCode(CALLBACKS, name);
|
| + return GetCode(CALLBACKS, name);
|
| }
|
|
|
|
|
| @@ -3099,9 +2735,9 @@ Handle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object,
|
| }
|
|
|
|
|
| -MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
|
| - JSObject* holder,
|
| - String* name) {
|
| +Handle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object,
|
| + Handle<JSObject> holder,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- a0 : receiver
|
| // -- a2 : name
|
| @@ -3112,21 +2748,13 @@ MaybeObject* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
|
|
|
| LookupResult lookup(isolate());
|
| LookupPostInterceptor(holder, name, &lookup);
|
| - GenerateLoadInterceptor(object,
|
| - holder,
|
| - &lookup,
|
| - a0,
|
| - a2,
|
| - a3,
|
| - a1,
|
| - t0,
|
| - name,
|
| + GenerateLoadInterceptor(object, holder, &lookup, a0, a2, a3, a1, t0, name,
|
| &miss);
|
| __ bind(&miss);
|
| GenerateLoadMiss(masm(), Code::LOAD_IC);
|
|
|
| // Return the generated code.
|
| - return TryGetCode(INTERCEPTOR, name);
|
| + return GetCode(INTERCEPTOR, name);
|
| }
|
|
|
|
|
| @@ -3200,11 +2828,11 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
|
| }
|
|
|
|
|
| -MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
|
| - String* name,
|
| - JSObject* receiver,
|
| - JSObject* holder,
|
| - AccessorInfo* callback) {
|
| +Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
|
| + Handle<String> name,
|
| + Handle<JSObject> receiver,
|
| + Handle<JSObject> holder,
|
| + Handle<AccessorInfo> callback) {
|
| // ----------- S t a t e -------------
|
| // -- ra : return address
|
| // -- a0 : key
|
| @@ -3213,19 +2841,14 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadCallback(
|
| Label miss;
|
|
|
| // Check the key is the cached one.
|
| - __ Branch(&miss, ne, a0, Operand(Handle<String>(name)));
|
| -
|
| - MaybeObject* result = GenerateLoadCallback(receiver, holder, a1, a0, a2, a3,
|
| - t0, callback, name, &miss);
|
| - if (result->IsFailure()) {
|
| - miss.Unuse();
|
| - return result;
|
| - }
|
| + __ Branch(&miss, ne, a0, Operand(name));
|
|
|
| + GenerateLoadCallback(receiver, holder, a1, a0, a2, a3, t0, callback, name,
|
| + &miss);
|
| __ bind(&miss);
|
| GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
|
|
| - return TryGetCode(CALLBACKS, name);
|
| + return GetCode(CALLBACKS, name);
|
| }
|
|
|
|
|
| @@ -3253,9 +2876,10 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant(
|
| }
|
|
|
|
|
| -MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
|
| - JSObject* holder,
|
| - String* name) {
|
| +Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
|
| + Handle<JSObject> receiver,
|
| + Handle<JSObject> holder,
|
| + Handle<String> name) {
|
| // ----------- S t a t e -------------
|
| // -- ra : return address
|
| // -- a0 : key
|
| @@ -3264,24 +2888,16 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
|
| Label miss;
|
|
|
| // Check the key is the cached one.
|
| - __ Branch(&miss, ne, a0, Operand(Handle<String>(name)));
|
| + __ Branch(&miss, ne, a0, Operand(name));
|
|
|
| LookupResult lookup(isolate());
|
| LookupPostInterceptor(holder, name, &lookup);
|
| - GenerateLoadInterceptor(receiver,
|
| - holder,
|
| - &lookup,
|
| - a1,
|
| - a0,
|
| - a2,
|
| - a3,
|
| - t0,
|
| - name,
|
| + GenerateLoadInterceptor(receiver, holder, &lookup, a1, a0, a2, a3, t0, name,
|
| &miss);
|
| __ bind(&miss);
|
| GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
|
|
| - return TryGetCode(INTERCEPTOR, name);
|
| + return GetCode(INTERCEPTOR, name);
|
| }
|
|
|
|
|
| @@ -3496,7 +3112,8 @@ Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
|
| }
|
|
|
|
|
| -MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
|
| +Handle<Code> ConstructStubCompiler::CompileConstructStub(
|
| + Handle<JSFunction> function) {
|
| // a0 : argc
|
| // a1 : constructor
|
| // ra : return address
|
| @@ -3541,12 +3158,7 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
|
| // a2: initial map
|
| // t7: undefined
|
| __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
|
| - __ AllocateInNewSpace(a3,
|
| - t4,
|
| - t5,
|
| - t6,
|
| - &generic_stub_call,
|
| - SIZE_IN_WORDS);
|
| + __ AllocateInNewSpace(a3, t4, t5, t6, &generic_stub_call, SIZE_IN_WORDS);
|
|
|
| // Allocated the JSObject, now initialize the fields. Map is set to initial
|
| // map and properties and elements are set to empty fixed array.
|
| @@ -3581,7 +3193,7 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
|
| // t7: undefined
|
| // Fill the initialized properties with a constant value or a passed argument
|
| // depending on the this.x = ...; assignment in the function.
|
| - SharedFunctionInfo* shared = function->shared();
|
| + Handle<SharedFunctionInfo> shared(function->shared());
|
| for (int i = 0; i < shared->this_property_assignments_count(); i++) {
|
| if (shared->IsThisPropertyAssignmentArgument(i)) {
|
| Label not_passed, next;
|
| @@ -4053,9 +3665,9 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
| __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
|
|
| __ bind(&miss_force_generic);
|
| - Code* stub = masm->isolate()->builtins()->builtin(
|
| - Builtins::kKeyedLoadIC_MissForceGeneric);
|
| - __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
|
| + Handle<Code> stub =
|
| + masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
| + __ Jump(stub, RelocInfo::CODE_TARGET);
|
| }
|
|
|
|
|
| @@ -4483,9 +4095,9 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
|
| __ Ret();
|
|
|
| __ bind(&miss_force_generic);
|
| - Code* stub = masm->isolate()->builtins()->builtin(
|
| - Builtins::kKeyedLoadIC_MissForceGeneric);
|
| - __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
|
| + Handle<Code> stub =
|
| + masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
| + __ Jump(stub, RelocInfo::CODE_TARGET);
|
| }
|
|
|
|
|
|
|