| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/code-stubs.h" | 5 #include "src/code-stubs.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/ast/ast.h" | 9 #include "src/ast/ast.h" |
| 10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
| (...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 | 311 |
| 312 // static | 312 // static |
| 313 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime( | 313 void BinaryOpICWithAllocationSiteStub::GenerateAheadOfTime( |
| 314 Isolate* isolate, const BinaryOpICState& state) { | 314 Isolate* isolate, const BinaryOpICState& state) { |
| 315 if (state.CouldCreateAllocationMementos()) { | 315 if (state.CouldCreateAllocationMementos()) { |
| 316 BinaryOpICWithAllocationSiteStub stub(isolate, state); | 316 BinaryOpICWithAllocationSiteStub stub(isolate, state); |
| 317 stub.GetCode(); | 317 stub.GetCode(); |
| 318 } | 318 } |
| 319 } | 319 } |
| 320 | 320 |
| 321 | |
| 322 std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags) { | |
| 323 switch (flags) { | |
| 324 case STRING_ADD_CHECK_NONE: | |
| 325 return os << "CheckNone"; | |
| 326 case STRING_ADD_CHECK_LEFT: | |
| 327 return os << "CheckLeft"; | |
| 328 case STRING_ADD_CHECK_RIGHT: | |
| 329 return os << "CheckRight"; | |
| 330 case STRING_ADD_CHECK_BOTH: | |
| 331 return os << "CheckBoth"; | |
| 332 case STRING_ADD_CONVERT_LEFT: | |
| 333 return os << "ConvertLeft"; | |
| 334 case STRING_ADD_CONVERT_RIGHT: | |
| 335 return os << "ConvertRight"; | |
| 336 case STRING_ADD_CONVERT: | |
| 337 break; | |
| 338 } | |
| 339 UNREACHABLE(); | |
| 340 return os; | |
| 341 } | |
| 342 | |
| 343 | |
| 344 void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT | 321 void StringAddStub::PrintBaseName(std::ostream& os) const { // NOLINT |
| 345 os << "StringAddStub_" << flags() << "_" << pretenure_flag(); | 322 os << "StringAddStub_" << flags() << "_" << pretenure_flag(); |
| 346 } | 323 } |
| 347 | 324 |
| 348 void StringAddStub::GenerateAssembly(CodeStubAssembler* assembler) const { | 325 void StringAddStub::GenerateAssembly(CodeStubAssembler* assembler) const { |
| 349 typedef compiler::Node Node; | 326 typedef compiler::Node Node; |
| 350 Node* left = assembler->Parameter(Descriptor::kLeft); | 327 Node* left = assembler->Parameter(Descriptor::kLeft); |
| 351 Node* right = assembler->Parameter(Descriptor::kRight); | 328 Node* right = assembler->Parameter(Descriptor::kRight); |
| 352 Node* context = assembler->Parameter(Descriptor::kContext); | 329 Node* context = assembler->Parameter(Descriptor::kContext); |
| 353 | 330 |
| (...skipping 1996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2350 // Note: Although a no-op transition is semantically OK, it is hinting at a | 2327 // Note: Although a no-op transition is semantically OK, it is hinting at a |
| 2351 // bug somewhere in our state transition machinery. | 2328 // bug somewhere in our state transition machinery. |
| 2352 DCHECK(from != to); | 2329 DCHECK(from != to); |
| 2353 if (!FLAG_trace_ic) return; | 2330 if (!FLAG_trace_ic) return; |
| 2354 OFStream os(stdout); | 2331 OFStream os(stdout); |
| 2355 os << "["; | 2332 os << "["; |
| 2356 PrintBaseName(os); | 2333 PrintBaseName(os); |
| 2357 os << ": " << from << "=>" << to << "]" << std::endl; | 2334 os << ": " << from << "=>" << to << "]" << std::endl; |
| 2358 } | 2335 } |
| 2359 | 2336 |
| 2360 | |
| 2361 // TODO(svenpanne) Make this a real infix_ostream_iterator. | |
| 2362 class SimpleListPrinter { | |
| 2363 public: | |
| 2364 explicit SimpleListPrinter(std::ostream& os) : os_(os), first_(true) {} | |
| 2365 | |
| 2366 void Add(const char* s) { | |
| 2367 if (first_) { | |
| 2368 first_ = false; | |
| 2369 } else { | |
| 2370 os_ << ","; | |
| 2371 } | |
| 2372 os_ << s; | |
| 2373 } | |
| 2374 | |
| 2375 private: | |
| 2376 std::ostream& os_; | |
| 2377 bool first_; | |
| 2378 }; | |
| 2379 | |
| 2380 | |
| 2381 void CallICStub::PrintState(std::ostream& os) const { // NOLINT | 2337 void CallICStub::PrintState(std::ostream& os) const { // NOLINT |
| 2382 os << state(); | 2338 os << state(); |
| 2383 } | 2339 } |
| 2384 | 2340 |
| 2385 | 2341 |
| 2386 void JSEntryStub::FinishCode(Handle<Code> code) { | 2342 void JSEntryStub::FinishCode(Handle<Code> code) { |
| 2387 Handle<FixedArray> handler_table = | 2343 Handle<FixedArray> handler_table = |
| 2388 code->GetIsolate()->factory()->NewFixedArray(1, TENURED); | 2344 code->GetIsolate()->factory()->NewFixedArray(1, TENURED); |
| 2389 handler_table->set(0, Smi::FromInt(handler_offset_)); | 2345 handler_table->set(0, Smi::FromInt(handler_offset_)); |
| 2390 code->set_handler_table(*handler_table); | 2346 code->set_handler_table(*handler_table); |
| (...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3036 STORE_AND_GROW_NO_TRANSITION).GetCode(); | 2992 STORE_AND_GROW_NO_TRANSITION).GetCode(); |
| 3037 for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) { | 2993 for (int i = FIRST_FAST_ELEMENTS_KIND; i <= LAST_FAST_ELEMENTS_KIND; i++) { |
| 3038 ElementsKind kind = static_cast<ElementsKind>(i); | 2994 ElementsKind kind = static_cast<ElementsKind>(i); |
| 3039 StoreFastElementStub(isolate, true, kind, STANDARD_STORE).GetCode(); | 2995 StoreFastElementStub(isolate, true, kind, STANDARD_STORE).GetCode(); |
| 3040 StoreFastElementStub(isolate, true, kind, STORE_AND_GROW_NO_TRANSITION) | 2996 StoreFastElementStub(isolate, true, kind, STORE_AND_GROW_NO_TRANSITION) |
| 3041 .GetCode(); | 2997 .GetCode(); |
| 3042 } | 2998 } |
| 3043 } | 2999 } |
| 3044 | 3000 |
| 3045 bool ToBooleanICStub::UpdateStatus(Handle<Object> object) { | 3001 bool ToBooleanICStub::UpdateStatus(Handle<Object> object) { |
| 3046 Types new_types = types(); | 3002 ToBooleanHints old_hints = hints(); |
| 3047 Types old_types = new_types; | 3003 ToBooleanHints new_hints = old_hints; |
| 3048 bool to_boolean_value = new_types.UpdateStatus(isolate(), object); | 3004 bool to_boolean_value = false; // Dummy initialization. |
| 3049 TraceTransition(old_types, new_types); | 3005 if (object->IsUndefined(isolate())) { |
| 3050 set_sub_minor_key(TypesBits::update(sub_minor_key(), new_types.ToIntegral())); | 3006 new_hints |= ToBooleanHint::kUndefined; |
| 3007 to_boolean_value = false; |
| 3008 } else if (object->IsBoolean()) { |
| 3009 new_hints |= ToBooleanHint::kBoolean; |
| 3010 to_boolean_value = object->IsTrue(isolate()); |
| 3011 } else if (object->IsNull(isolate())) { |
| 3012 new_hints |= ToBooleanHint::kNull; |
| 3013 to_boolean_value = false; |
| 3014 } else if (object->IsSmi()) { |
| 3015 new_hints |= ToBooleanHint::kSmallInteger; |
| 3016 to_boolean_value = Smi::cast(*object)->value() != 0; |
| 3017 } else if (object->IsJSReceiver()) { |
| 3018 new_hints |= ToBooleanHint::kReceiver; |
| 3019 to_boolean_value = !object->IsUndetectable(); |
| 3020 } else if (object->IsString()) { |
| 3021 DCHECK(!object->IsUndetectable()); |
| 3022 new_hints |= ToBooleanHint::kString; |
| 3023 to_boolean_value = String::cast(*object)->length() != 0; |
| 3024 } else if (object->IsSymbol()) { |
| 3025 new_hints |= ToBooleanHint::kSymbol; |
| 3026 to_boolean_value = true; |
| 3027 } else if (object->IsHeapNumber()) { |
| 3028 DCHECK(!object->IsUndetectable()); |
| 3029 new_hints |= ToBooleanHint::kHeapNumber; |
| 3030 double value = HeapNumber::cast(*object)->value(); |
| 3031 to_boolean_value = value != 0 && !std::isnan(value); |
| 3032 } else if (object->IsSimd128Value()) { |
| 3033 new_hints |= ToBooleanHint::kSimdValue; |
| 3034 to_boolean_value = true; |
| 3035 } else { |
| 3036 // We should never see an internal object at runtime here! |
| 3037 UNREACHABLE(); |
| 3038 to_boolean_value = true; |
| 3039 } |
| 3040 TraceTransition(old_hints, new_hints); |
| 3041 set_sub_minor_key(HintsBits::update(sub_minor_key(), new_hints)); |
| 3051 return to_boolean_value; | 3042 return to_boolean_value; |
| 3052 } | 3043 } |
| 3053 | 3044 |
| 3054 void ToBooleanICStub::PrintState(std::ostream& os) const { // NOLINT | 3045 void ToBooleanICStub::PrintState(std::ostream& os) const { // NOLINT |
| 3055 os << types(); | 3046 os << hints(); |
| 3056 } | 3047 } |
| 3057 | 3048 |
| 3058 std::ostream& operator<<(std::ostream& os, const ToBooleanICStub::Types& s) { | |
| 3059 os << "("; | |
| 3060 SimpleListPrinter p(os); | |
| 3061 if (s.IsEmpty()) p.Add("None"); | |
| 3062 if (s.Contains(ToBooleanICStub::UNDEFINED)) p.Add("Undefined"); | |
| 3063 if (s.Contains(ToBooleanICStub::BOOLEAN)) p.Add("Bool"); | |
| 3064 if (s.Contains(ToBooleanICStub::NULL_TYPE)) p.Add("Null"); | |
| 3065 if (s.Contains(ToBooleanICStub::SMI)) p.Add("Smi"); | |
| 3066 if (s.Contains(ToBooleanICStub::SPEC_OBJECT)) p.Add("SpecObject"); | |
| 3067 if (s.Contains(ToBooleanICStub::STRING)) p.Add("String"); | |
| 3068 if (s.Contains(ToBooleanICStub::SYMBOL)) p.Add("Symbol"); | |
| 3069 if (s.Contains(ToBooleanICStub::HEAP_NUMBER)) p.Add("HeapNumber"); | |
| 3070 if (s.Contains(ToBooleanICStub::SIMD_VALUE)) p.Add("SimdValue"); | |
| 3071 return os << ")"; | |
| 3072 } | |
| 3073 | |
| 3074 bool ToBooleanICStub::Types::UpdateStatus(Isolate* isolate, | |
| 3075 Handle<Object> object) { | |
| 3076 if (object->IsUndefined(isolate)) { | |
| 3077 Add(UNDEFINED); | |
| 3078 return false; | |
| 3079 } else if (object->IsBoolean()) { | |
| 3080 Add(BOOLEAN); | |
| 3081 return object->IsTrue(isolate); | |
| 3082 } else if (object->IsNull(isolate)) { | |
| 3083 Add(NULL_TYPE); | |
| 3084 return false; | |
| 3085 } else if (object->IsSmi()) { | |
| 3086 Add(SMI); | |
| 3087 return Smi::cast(*object)->value() != 0; | |
| 3088 } else if (object->IsJSReceiver()) { | |
| 3089 Add(SPEC_OBJECT); | |
| 3090 return !object->IsUndetectable(); | |
| 3091 } else if (object->IsString()) { | |
| 3092 DCHECK(!object->IsUndetectable()); | |
| 3093 Add(STRING); | |
| 3094 return String::cast(*object)->length() != 0; | |
| 3095 } else if (object->IsSymbol()) { | |
| 3096 Add(SYMBOL); | |
| 3097 return true; | |
| 3098 } else if (object->IsHeapNumber()) { | |
| 3099 DCHECK(!object->IsUndetectable()); | |
| 3100 Add(HEAP_NUMBER); | |
| 3101 double value = HeapNumber::cast(*object)->value(); | |
| 3102 return value != 0 && !std::isnan(value); | |
| 3103 } else if (object->IsSimd128Value()) { | |
| 3104 Add(SIMD_VALUE); | |
| 3105 return true; | |
| 3106 } else { | |
| 3107 // We should never see an internal object at runtime here! | |
| 3108 UNREACHABLE(); | |
| 3109 return true; | |
| 3110 } | |
| 3111 } | |
| 3112 | |
| 3113 bool ToBooleanICStub::Types::NeedsMap() const { | |
| 3114 return Contains(ToBooleanICStub::SPEC_OBJECT) || | |
| 3115 Contains(ToBooleanICStub::STRING) || | |
| 3116 Contains(ToBooleanICStub::SYMBOL) || | |
| 3117 Contains(ToBooleanICStub::HEAP_NUMBER) || | |
| 3118 Contains(ToBooleanICStub::SIMD_VALUE); | |
| 3119 } | |
| 3120 | |
| 3121 | |
| 3122 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) { | 3049 void StubFailureTrampolineStub::GenerateAheadOfTime(Isolate* isolate) { |
| 3123 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE); | 3050 StubFailureTrampolineStub stub1(isolate, NOT_JS_FUNCTION_STUB_MODE); |
| 3124 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE); | 3051 StubFailureTrampolineStub stub2(isolate, JS_FUNCTION_STUB_MODE); |
| 3125 stub1.GetCode(); | 3052 stub1.GetCode(); |
| 3126 stub2.GetCode(); | 3053 stub2.GetCode(); |
| 3127 } | 3054 } |
| 3128 | 3055 |
| 3129 | 3056 |
| 3130 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function, | 3057 void ProfileEntryHookStub::EntryHookTrampoline(intptr_t function, |
| 3131 intptr_t stack_pointer, | 3058 intptr_t stack_pointer, |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3304 assembler->Return(assembler->CallRuntime(Runtime::kGrowArrayElements, context, | 3231 assembler->Return(assembler->CallRuntime(Runtime::kGrowArrayElements, context, |
| 3305 object, key)); | 3232 object, key)); |
| 3306 } | 3233 } |
| 3307 | 3234 |
| 3308 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate) | 3235 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate) |
| 3309 : PlatformCodeStub(isolate) {} | 3236 : PlatformCodeStub(isolate) {} |
| 3310 | 3237 |
| 3311 InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate) | 3238 InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate) |
| 3312 : PlatformCodeStub(isolate) {} | 3239 : PlatformCodeStub(isolate) {} |
| 3313 | 3240 |
| 3314 Representation RepresentationFromMachineType(MachineType type) { | |
| 3315 if (type == MachineType::Int32()) { | |
| 3316 return Representation::Integer32(); | |
| 3317 } | |
| 3318 | |
| 3319 if (type == MachineType::TaggedSigned()) { | |
| 3320 return Representation::Smi(); | |
| 3321 } | |
| 3322 | |
| 3323 if (type == MachineType::Pointer()) { | |
| 3324 return Representation::External(); | |
| 3325 } | |
| 3326 | |
| 3327 return Representation::Tagged(); | |
| 3328 } | |
| 3329 | |
| 3330 } // namespace internal | 3241 } // namespace internal |
| 3331 } // namespace v8 | 3242 } // namespace v8 |
| OLD | NEW |