code-factory.cc 15 KB
Newer Older
1 2 3 4
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "src/codegen/code-factory.h"
6

7
#include "src/builtins/builtins-descriptors.h"
8
#include "src/ic/ic.h"
9
#include "src/init/bootstrapper.h"
10
#include "src/objects/allocation-site-inl.h"
11
#include "src/objects/objects-inl.h"
12 13 14 15

namespace v8 {
namespace internal {

16 17
// static
Handle<Code> CodeFactory::RuntimeCEntry(Isolate* isolate, int result_size) {
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
  return CodeFactory::CEntry(isolate, result_size);
}

#define CENTRY_CODE(RS, SD, AM, BE) \
  BUILTIN_CODE(isolate, CEntry_##RS##_##SD##_##AM##_##BE)

// static
Handle<Code> CodeFactory::CEntry(Isolate* isolate, int result_size,
                                 SaveFPRegsMode save_doubles,
                                 ArgvMode argv_mode, bool builtin_exit_frame) {
  // Aliases for readability below.
  const int rs = result_size;
  const SaveFPRegsMode sd = save_doubles;
  const ArgvMode am = argv_mode;
  const bool be = builtin_exit_frame;

34 35
  if (rs == 1 && sd == SaveFPRegsMode::kIgnore && am == ArgvMode::kStack &&
      !be) {
36
    return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvOnStack, NoBuiltinExit);
37 38
  } else if (rs == 1 && sd == SaveFPRegsMode::kIgnore &&
             am == ArgvMode::kStack && be) {
39
    return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvOnStack, BuiltinExit);
40 41
  } else if (rs == 1 && sd == SaveFPRegsMode::kIgnore &&
             am == ArgvMode::kRegister && !be) {
42
    return CENTRY_CODE(Return1, DontSaveFPRegs, ArgvInRegister, NoBuiltinExit);
43 44
  } else if (rs == 1 && sd == SaveFPRegsMode::kSave && am == ArgvMode::kStack &&
             !be) {
45
    return CENTRY_CODE(Return1, SaveFPRegs, ArgvOnStack, NoBuiltinExit);
46 47
  } else if (rs == 1 && sd == SaveFPRegsMode::kSave && am == ArgvMode::kStack &&
             be) {
48
    return CENTRY_CODE(Return1, SaveFPRegs, ArgvOnStack, BuiltinExit);
49 50
  } else if (rs == 2 && sd == SaveFPRegsMode::kIgnore &&
             am == ArgvMode::kStack && !be) {
51
    return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvOnStack, NoBuiltinExit);
52 53
  } else if (rs == 2 && sd == SaveFPRegsMode::kIgnore &&
             am == ArgvMode::kStack && be) {
54
    return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvOnStack, BuiltinExit);
55 56
  } else if (rs == 2 && sd == SaveFPRegsMode::kIgnore &&
             am == ArgvMode::kRegister && !be) {
57
    return CENTRY_CODE(Return2, DontSaveFPRegs, ArgvInRegister, NoBuiltinExit);
58 59
  } else if (rs == 2 && sd == SaveFPRegsMode::kSave && am == ArgvMode::kStack &&
             !be) {
60
    return CENTRY_CODE(Return2, SaveFPRegs, ArgvOnStack, NoBuiltinExit);
61 62
  } else if (rs == 2 && sd == SaveFPRegsMode::kSave && am == ArgvMode::kStack &&
             be) {
63 64 65 66
    return CENTRY_CODE(Return2, SaveFPRegs, ArgvOnStack, BuiltinExit);
  }

  UNREACHABLE();
67 68
}

69 70
#undef CENTRY_CODE

71 72
// static
Callable CodeFactory::ApiGetter(Isolate* isolate) {
73
  return Builtins::CallableFor(isolate, Builtin::kCallApiGetter);
74
}
75

76
// static
77
Callable CodeFactory::CallApiCallback(Isolate* isolate) {
78
  return Builtins::CallableFor(isolate, Builtin::kCallApiCallback);
79 80
}

81 82
// static
Callable CodeFactory::LoadGlobalIC(Isolate* isolate, TypeofMode typeof_mode) {
83
  return typeof_mode == TypeofMode::kNotInside
84
             ? Builtins::CallableFor(isolate, Builtin::kLoadGlobalICTrampoline)
85
             : Builtins::CallableFor(
86
                   isolate, Builtin::kLoadGlobalICInsideTypeofTrampoline);
87 88 89 90 91
}

// static
Callable CodeFactory::LoadGlobalICInOptimizedCode(Isolate* isolate,
                                                  TypeofMode typeof_mode) {
92
  return typeof_mode == TypeofMode::kNotInside
93
             ? Builtins::CallableFor(isolate, Builtin::kLoadGlobalIC)
94
             : Builtins::CallableFor(isolate,
95
                                     Builtin::kLoadGlobalICInsideTypeof);
96
}
97

98 99 100
Callable CodeFactory::StoreOwnIC(Isolate* isolate) {
  // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
  // already exist in the boilerplate therefore we can use StoreIC.
101
  return Builtins::CallableFor(isolate, Builtin::kStoreICTrampoline);
102 103 104 105 106
}

Callable CodeFactory::StoreOwnICInOptimizedCode(Isolate* isolate) {
  // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
  // already exist in the boilerplate therefore we can use StoreIC.
107
  return Builtins::CallableFor(isolate, Builtin::kStoreIC);
108 109
}

110 111 112 113
// static
Callable CodeFactory::NonPrimitiveToPrimitive(Isolate* isolate,
                                              ToPrimitiveHint hint) {
  return Callable(isolate->builtins()->NonPrimitiveToPrimitive(hint),
114
                  TypeConversionDescriptor{});
115 116 117 118 119 120
}

// static
Callable CodeFactory::OrdinaryToPrimitive(Isolate* isolate,
                                          OrdinaryToPrimitiveHint hint) {
  return Callable(isolate->builtins()->OrdinaryToPrimitive(hint),
121
                  TypeConversionDescriptor{});
122
}
123

124
// static
125 126 127
Callable CodeFactory::StringAdd(Isolate* isolate, StringAddFlags flags) {
  switch (flags) {
    case STRING_ADD_CHECK_NONE:
128
      return Builtins::CallableFor(isolate, Builtin::kStringAdd_CheckNone);
129
    case STRING_ADD_CONVERT_LEFT:
130
      return Builtins::CallableFor(isolate, Builtin::kStringAddConvertLeft);
131
    case STRING_ADD_CONVERT_RIGHT:
132
      return Builtins::CallableFor(isolate, Builtin::kStringAddConvertRight);
133 134
  }
  UNREACHABLE();
135 136
}

137 138
// static
Callable CodeFactory::ResumeGenerator(Isolate* isolate) {
139
  return Builtins::CallableFor(isolate, Builtin::kResumeGeneratorTrampoline);
140 141
}

142
// static
143 144
Callable CodeFactory::FastNewFunctionContext(Isolate* isolate,
                                             ScopeType scope_type) {
145 146 147
  switch (scope_type) {
    case ScopeType::EVAL_SCOPE:
      return Builtins::CallableFor(isolate,
148
                                   Builtin::kFastNewFunctionContextEval);
149 150
    case ScopeType::FUNCTION_SCOPE:
      return Builtins::CallableFor(isolate,
151
                                   Builtin::kFastNewFunctionContextFunction);
152 153 154
    default:
      UNREACHABLE();
  }
155 156
}

157
// static
158
Callable CodeFactory::Call(Isolate* isolate, ConvertReceiverMode mode) {
159
  return Callable(isolate->builtins()->Call(mode), CallTrampolineDescriptor{});
160 161
}

162 163 164 165 166 167
// static
Callable CodeFactory::Call_WithFeedback(Isolate* isolate,
                                        ConvertReceiverMode mode) {
  switch (mode) {
    case ConvertReceiverMode::kNullOrUndefined:
      return Builtins::CallableFor(
168
          isolate, Builtin::kCall_ReceiverIsNullOrUndefined_WithFeedback);
169 170
    case ConvertReceiverMode::kNotNullOrUndefined:
      return Builtins::CallableFor(
171
          isolate, Builtin::kCall_ReceiverIsNotNullOrUndefined_WithFeedback);
172 173
    case ConvertReceiverMode::kAny:
      return Builtins::CallableFor(isolate,
174
                                   Builtin::kCall_ReceiverIsAny_WithFeedback);
175 176 177 178
  }
  UNREACHABLE();
}

179 180
// static
Callable CodeFactory::CallWithArrayLike(Isolate* isolate) {
181
  return Builtins::CallableFor(isolate, Builtin::kCallWithArrayLike);
182 183
}

184 185
// static
Callable CodeFactory::CallWithSpread(Isolate* isolate) {
186
  return Builtins::CallableFor(isolate, Builtin::kCallWithSpread);
187 188
}

189
// static
190 191
Callable CodeFactory::CallFunction(Isolate* isolate, ConvertReceiverMode mode) {
  return Callable(isolate->builtins()->CallFunction(mode),
192
                  CallTrampolineDescriptor{});
193 194
}

195 196
// static
Callable CodeFactory::CallVarargs(Isolate* isolate) {
197
  return Builtins::CallableFor(isolate, Builtin::kCallVarargs);
198 199
}

200 201
// static
Callable CodeFactory::CallForwardVarargs(Isolate* isolate) {
202
  return Builtins::CallableFor(isolate, Builtin::kCallForwardVarargs);
203 204 205 206
}

// static
Callable CodeFactory::CallFunctionForwardVarargs(Isolate* isolate) {
207
  return Builtins::CallableFor(isolate, Builtin::kCallFunctionForwardVarargs);
208 209
}

210 211
// static
Callable CodeFactory::Construct(Isolate* isolate) {
212
  return Builtins::CallableFor(isolate, Builtin::kConstruct);
213 214
}

215 216
// static
Callable CodeFactory::ConstructWithSpread(Isolate* isolate) {
217
  return Builtins::CallableFor(isolate, Builtin::kConstructWithSpread);
218 219
}

220 221
// static
Callable CodeFactory::ConstructFunction(Isolate* isolate) {
222
  return Builtins::CallableFor(isolate, Builtin::kConstructFunction);
223 224
}

225 226
// static
Callable CodeFactory::ConstructVarargs(Isolate* isolate) {
227
  return Builtins::CallableFor(isolate, Builtin::kConstructVarargs);
228 229
}

230 231
// static
Callable CodeFactory::ConstructForwardVarargs(Isolate* isolate) {
232
  return Builtins::CallableFor(isolate, Builtin::kConstructForwardVarargs);
233 234 235 236
}

// static
Callable CodeFactory::ConstructFunctionForwardVarargs(Isolate* isolate) {
237
  return Builtins::CallableFor(isolate,
238
                               Builtin::kConstructFunctionForwardVarargs);
239 240
}

241
// static
242 243
Callable CodeFactory::InterpreterPushArgsThenCall(
    Isolate* isolate, ConvertReceiverMode receiver_mode,
244
    InterpreterPushArgsMode mode) {
245 246 247 248 249 250 251
  switch (mode) {
    case InterpreterPushArgsMode::kArrayFunction:
      // There is no special-case handling of calls to Array. They will all go
      // through the kOther case below.
      UNREACHABLE();
    case InterpreterPushArgsMode::kWithFinalSpread:
      return Builtins::CallableFor(
252
          isolate, Builtin::kInterpreterPushArgsThenCallWithFinalSpread);
253 254 255 256
    case InterpreterPushArgsMode::kOther:
      switch (receiver_mode) {
        case ConvertReceiverMode::kNullOrUndefined:
          return Builtins::CallableFor(
257
              isolate, Builtin::kInterpreterPushUndefinedAndArgsThenCall);
258 259 260
        case ConvertReceiverMode::kNotNullOrUndefined:
        case ConvertReceiverMode::kAny:
          return Builtins::CallableFor(isolate,
261
                                       Builtin::kInterpreterPushArgsThenCall);
262 263 264
      }
  }
  UNREACHABLE();
265 266
}

267
// static
268
Callable CodeFactory::InterpreterPushArgsThenConstruct(
269
    Isolate* isolate, InterpreterPushArgsMode mode) {
270 271 272
  switch (mode) {
    case InterpreterPushArgsMode::kArrayFunction:
      return Builtins::CallableFor(
273
          isolate, Builtin::kInterpreterPushArgsThenConstructArrayFunction);
274 275
    case InterpreterPushArgsMode::kWithFinalSpread:
      return Builtins::CallableFor(
276
          isolate, Builtin::kInterpreterPushArgsThenConstructWithFinalSpread);
277 278
    case InterpreterPushArgsMode::kOther:
      return Builtins::CallableFor(isolate,
279
                                   Builtin::kInterpreterPushArgsThenConstruct);
280 281
  }
  UNREACHABLE();
282 283
}

284
// static
285
Callable CodeFactory::InterpreterCEntry(Isolate* isolate, int result_size) {
286 287
  // Note: If we ever use fpregs in the interpreter then we will need to
  // save fpregs too.
288 289
  Handle<Code> code = CodeFactory::CEntry(
      isolate, result_size, SaveFPRegsMode::kIgnore, ArgvMode::kRegister);
290 291 292 293 294 295
  if (result_size == 1) {
    return Callable(code, InterpreterCEntry1Descriptor{});
  } else {
    DCHECK_EQ(result_size, 2);
    return Callable(code, InterpreterCEntry2Descriptor{});
  }
296 297
}

298 299
// static
Callable CodeFactory::InterpreterOnStackReplacement(Isolate* isolate) {
300
  return Builtins::CallableFor(isolate,
301
                               Builtin::kInterpreterOnStackReplacement);
302 303
}

304 305 306 307
// static
Callable CodeFactory::InterpreterOnStackReplacement_ToBaseline(
    Isolate* isolate) {
  return Builtins::CallableFor(
308
      isolate, Builtin::kInterpreterOnStackReplacement_ToBaseline);
309 310
}

311 312 313 314
// static
Callable CodeFactory::ArrayNoArgumentConstructor(
    Isolate* isolate, ElementsKind kind,
    AllocationSiteOverrideMode override_mode) {
315 316 317 318
#define CASE(kind_caps, kind_camel, mode_camel) \
  case kind_caps:                               \
    return Builtins::CallableFor(               \
        isolate,                                \
319
        Builtin::kArrayNoArgumentConstructor_##kind_camel##_##mode_camel);
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
  if (override_mode == DONT_OVERRIDE && AllocationSite::ShouldTrack(kind)) {
    DCHECK(IsSmiElementsKind(kind));
    switch (kind) {
      CASE(PACKED_SMI_ELEMENTS, PackedSmi, DontOverride);
      CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DontOverride);
      default:
        UNREACHABLE();
    }
  } else {
    DCHECK(override_mode == DISABLE_ALLOCATION_SITES ||
           !AllocationSite::ShouldTrack(kind));
    switch (kind) {
      CASE(PACKED_SMI_ELEMENTS, PackedSmi, DisableAllocationSites);
      CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DisableAllocationSites);
      CASE(PACKED_ELEMENTS, Packed, DisableAllocationSites);
      CASE(HOLEY_ELEMENTS, Holey, DisableAllocationSites);
      CASE(PACKED_DOUBLE_ELEMENTS, PackedDouble, DisableAllocationSites);
      CASE(HOLEY_DOUBLE_ELEMENTS, HoleyDouble, DisableAllocationSites);
      default:
        UNREACHABLE();
    }
  }
#undef CASE
343 344 345 346 347 348
}

// static
Callable CodeFactory::ArraySingleArgumentConstructor(
    Isolate* isolate, ElementsKind kind,
    AllocationSiteOverrideMode override_mode) {
349 350 351 352
#define CASE(kind_caps, kind_camel, mode_camel) \
  case kind_caps:                               \
    return Builtins::CallableFor(               \
        isolate,                                \
353
        Builtin::kArraySingleArgumentConstructor_##kind_camel##_##mode_camel)
354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
  if (override_mode == DONT_OVERRIDE && AllocationSite::ShouldTrack(kind)) {
    DCHECK(IsSmiElementsKind(kind));
    switch (kind) {
      CASE(PACKED_SMI_ELEMENTS, PackedSmi, DontOverride);
      CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DontOverride);
      default:
        UNREACHABLE();
    }
  } else {
    DCHECK(override_mode == DISABLE_ALLOCATION_SITES ||
           !AllocationSite::ShouldTrack(kind));
    switch (kind) {
      CASE(PACKED_SMI_ELEMENTS, PackedSmi, DisableAllocationSites);
      CASE(HOLEY_SMI_ELEMENTS, HoleySmi, DisableAllocationSites);
      CASE(PACKED_ELEMENTS, Packed, DisableAllocationSites);
      CASE(HOLEY_ELEMENTS, Holey, DisableAllocationSites);
      CASE(PACKED_DOUBLE_ELEMENTS, PackedDouble, DisableAllocationSites);
      CASE(HOLEY_DOUBLE_ELEMENTS, HoleyDouble, DisableAllocationSites);
      default:
        UNREACHABLE();
    }
  }
#undef CASE
377 378
}

379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
#ifdef V8_IS_TSAN
// static
Builtin CodeFactory::GetTSANRelaxedStoreStub(SaveFPRegsMode fp_mode, int size) {
  if (size == kInt8Size) {
    return fp_mode == SaveFPRegsMode::kIgnore
               ? Builtin::kTSANRelaxedStore8IgnoreFP
               : Builtin::kTSANRelaxedStore8SaveFP;
  } else if (size == kInt16Size) {
    return fp_mode == SaveFPRegsMode::kIgnore
               ? Builtin::kTSANRelaxedStore16IgnoreFP
               : Builtin::kTSANRelaxedStore16SaveFP;
  } else if (size == kInt32Size) {
    return fp_mode == SaveFPRegsMode::kIgnore
               ? Builtin::kTSANRelaxedStore32IgnoreFP
               : Builtin::kTSANRelaxedStore32SaveFP;
  } else {
    CHECK_EQ(size, kInt64Size);
    return fp_mode == SaveFPRegsMode::kIgnore
               ? Builtin::kTSANRelaxedStore64IgnoreFP
               : Builtin::kTSANRelaxedStore64SaveFP;
  }
}

// static
Builtin CodeFactory::GetTSANRelaxedLoadStub(SaveFPRegsMode fp_mode, int size) {
  if (size == kInt32Size) {
    return fp_mode == SaveFPRegsMode::kIgnore
               ? Builtin::kTSANRelaxedLoad32IgnoreFP
               : Builtin::kTSANRelaxedLoad32SaveFP;
  } else {
    CHECK_EQ(size, kInt64Size);
    return fp_mode == SaveFPRegsMode::kIgnore
               ? Builtin::kTSANRelaxedLoad64IgnoreFP
               : Builtin::kTSANRelaxedLoad64SaveFP;
  }
}
#endif  // V8_IS_TSAN

417 418
}  // namespace internal
}  // namespace v8